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 #include <alloca.h>
00062 #include <stdlib.h>
00063 #include <math.h>
00064 #include <float.h>
00065 #include <limits.h>
00066
00067 #include "defs.h"
00068 #include "config.h"
00069 #include "config_opt.h"
00070 #include "timing.h"
00071 #include "glob.h"
00072 #include "erglob.h"
00073 #include "erbe.h"
00074 #include "tracing.h"
00075 #include "mempool.h"
00076 #include "data_layout.h"
00077 #include "strtab.h"
00078 #include "config_asm.h"
00079 #include "cgir.h"
00080 #include "cg.h"
00081 #include "cg_internal.h"
00082 #include "cgtarget.h"
00083 #include "bb_map.h"
00084 #include "gra_live.h"
00085 #include "gtn_universe.h"
00086 #include "gtn_set.h"
00087 #include "cgexp.h"
00088 #include "variants.h"
00089 #include "cg_flags.h"
00090 #include "cg_region.h"
00091 #include "irbdata.h"
00092 #include "whirl2ops.h"
00093 #include "freq.h"
00094 #include "bb_set.h"
00095 #include "cg_sched_est.h"
00096 #include "note.h"
00097 #include "ir_reader.h"
00098 #include "tn_set.h"
00099 #include "gtn_tn_set.h"
00100 #include "label_util.h"
00101 #include "eh_region.h"
00102 #include "targ_proc_properties.h"
00103 #include "hb_cflow.h"
00104
00105 #include "cflow.h"
00106
00107 #ifdef KEY
00108 #include <float.h>
00109 #endif
00110 #ifdef TARG_IA64
00111 #include "region.h"
00112 #include "region_bb_util.h"
00113 #include "vt_region.h"
00114 #include "ipfec_options.h"
00115 #endif
00116 #ifdef TARG_IA64
00117 #include "speculation.h"
00118 #endif
00119
00120 #define DEBUG_CFLOW Is_True_On
00121
00122
00123
00124 #if Is_True_On && defined(TARG_MIPS)
00125 #define VERIFY_INDIRECT_JUMP_TARGET
00126 #endif
00127
00128 static BOOL have_eh_regions;
00129
00130
00131
00132 static float br_taken_cost;
00133 static float br_fall_cost;
00134 #ifdef KEY
00135 static float br_static_cost;
00136 #endif
00137
00138
00139
00140 static INT32 disabled_flags;
00141 static INT32 current_flags;
00142
00143
00144
00145 static BOOL freqs_computed;
00146
00147
00148
00149 static BB *deleted_bbs;
00150
00151
00152
00153 static BOOL eh_label_removed;
00154
00155
00156
00157 #define TRACE_CFLOW 0x0001
00158 #define TRACE_DETAIL 0x0002
00159 #define TRACE_UNREACH 0x0004
00160 #define TRACE_BRANCH 0x0008
00161 #define TRACE_MERGE 0x0010
00162 #define TRACE_REORDER 0x0020
00163 #define TRACE_FREQ_ORDER 0x0040
00164 #define TRACE_CLONE 0x0080
00165 #define TRACE_FREQ 0x0100
00166 #define TRACE_DOM 0x0200
00167 #ifdef TARG_IA64
00168 #define TRACE_Empty_BB_Elim 0x0400
00169 #endif
00170
00171
00172 BOOL CFLOW_Trace;
00173 BOOL CFLOW_Trace_Detail;
00174 BOOL CFLOW_Trace_Unreach;
00175 BOOL CFLOW_Trace_Branch;
00176 BOOL CFLOW_Trace_Merge;
00177 BOOL CFLOW_Trace_Reorder;
00178 BOOL CFLOW_Trace_Freq_Order;
00179 BOOL CFLOW_Trace_Clone;
00180 BOOL CFLOW_Trace_Freq;
00181 BOOL CFLOW_Trace_Dom;
00182
00183 #ifdef TARG_IA64
00184 BOOL CFLOW_Trace_Empty_BB_Elim;
00185 #endif
00186
00187
00188
00189
00190
00191 static BB_MAP bb_info_map;
00192
00193
00194
00195 struct logif_info {
00196 TN *tn1;
00197 TN *tn2;
00198 OP *compare_op;
00199 VARIANT variant;
00200 mBOOL b_likely;
00201 };
00202
00203 struct vargoto_info {
00204 ST *listvar;
00205 INT *refcount;
00206 };
00207
00208 struct succedge {
00209 INT64 offset;
00210 BB *bb;
00211 float prob;
00212 };
00213
00214 #define BBINFO_NSUCCS (2)
00215
00216
00217
00218
00219
00220
00221 typedef struct bbinfo {
00222 BBKIND kind;
00223 union {
00224 struct logif_info l;
00225 struct vargoto_info v;
00226 } u;
00227 mUINT16 eh_rgn;
00228 mBOOL cold;
00229 INT nsuccs;
00230 struct succedge succs[BBINFO_NSUCCS];
00231
00232
00233 } BBINFO;
00234
00235
00236
00237 #define BB_BBINFO(bb) ((BBINFO *)BB_MAP_Get(bb_info_map, (bb)))
00238
00239 #define BBINFO_kind(b) ((BBKIND)BB_BBINFO(b)->kind)
00240 #define Set_BBINFO_kind(b,k) (BB_BBINFO(b)->kind=(k))
00241 #define BBINFO_eh_rgn(b) (BB_BBINFO(b)->eh_rgn+0)
00242 #define Set_BBINFO_eh_rgn(b, e) (BB_BBINFO(b)->eh_rgn=(e))
00243 #define BBINFO_cold(b) (BB_BBINFO(b)->cold+0)
00244 #define Set_BBINFO_cold(b, e) (BB_BBINFO(b)->cold=(e))
00245 #define BBINFO_nsuccs(b) (BB_BBINFO(b)->nsuccs+0)
00246 #define Set_BBINFO_nsuccs(b,n) (BB_BBINFO(b)->nsuccs=(n))
00247 #define BBINFO_succ_bb(b, n) (BB_BBINFO(b)->succs[n].bb+0)
00248 #define Set_BBINFO_succ_bb(b, n, s) (BB_BBINFO(b)->succs[n].bb=(s))
00249 #define BBINFO_succ_offset(b, n) (BB_BBINFO(b)->succs[n].offset+0)
00250 #define Set_BBINFO_succ_offset(b, n, o) (BB_BBINFO(b)->succs[n].offset=(o))
00251 #define BBINFO_succ_prob(b, n) (BB_BBINFO(b)->succs[n].prob+0)
00252 #define Set_BBINFO_succ_prob(b, n, p) (BB_BBINFO(b)->succs[n].prob=(p))
00253 #define BBINFO_variant(b) ((VARIANT)BB_BBINFO(b)->u.l.variant)
00254 #define Set_BBINFO_variant(b, v) (BB_BBINFO(b)->u.l.variant=(v))
00255 #define BBINFO_b_likely(b) (BB_BBINFO(b)->u.l.b_likely+0)
00256 #define Set_BBINFO_b_likely(b, v) (BB_BBINFO(b)->u.l.b_likely=(v))
00257 #define BBINFO_condval1(b) (BB_BBINFO(b)->u.l.tn1+0)
00258 #define Set_BBINFO_condval1(b, tn) (BB_BBINFO(b)->u.l.tn1=(tn))
00259 #define BBINFO_condval2(b) (BB_BBINFO(b)->u.l.tn2+0)
00260 #define Set_BBINFO_condval2(b, tn) (BB_BBINFO(b)->u.l.tn2=(tn))
00261 #define BBINFO_compare_op(b) (BB_BBINFO(b)->u.l.compare_op+0)
00262 #define Set_BBINFO_compare_op(b, op) (BB_BBINFO(b)->u.l.compare_op=(op))
00263 #define BBINFO_vargoto_listvar(b) (BB_BBINFO(b)->u.v.listvar+0)
00264 #define Set_BBINFO_vargoto_listvar(b, l) (BB_BBINFO(b)->u.v.listvar=(l))
00265 #define BBINFO_vargoto_refcount(b) (BB_BBINFO(b)->u.v.refcount+0)
00266 #define Set_BBINFO_vargoto_refcount(b, r) (BB_BBINFO(b)->u.v.refcount=(r))
00267
00268
00269
00270
00271
00272 typedef struct listvar_count {
00273 struct listvar_count *next;
00274 ST *listvar;
00275 INT count;
00276 } LISTVAR_COUNT;
00277
00278
00279
00280 static LISTVAR_COUNT *listvar_counts;
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292 void Print_BB_Info(BB *bb);
00293 #pragma mips_frequency_hint NEVER Print_BB_Info
00294 void Print_Cflow_Graph(const char *banner);
00295 #pragma mips_frequency_hint NEVER Print_Cflow_Graph
00296
00297 #ifdef TARG_X8664
00298
00299
00300
00301
00302
00303
00304
00305
00306 static inline OP*
00307 BB_savexmms_op( BB *bb )
00308 {
00309 OP* op = BB_last_op(bb);
00310 return ( (op != NULL) && (OP_code(op) == TOP_savexmms) ) ? op : NULL;
00311 }
00312
00313 static inline bool
00314 BB_first_OP_computes_got (BB* bb)
00315 {
00316 OP *first_op = BB_first_op(bb);
00317 return ((first_op != NULL) && OP_computes_got(first_op));
00318 }
00319
00320 static inline bool
00321 BB_last_OP_computes_got (BB* bb)
00322 {
00323 OP *last_op = BB_last_op(bb);
00324 return ((last_op != NULL) && OP_computes_got(last_op));
00325 }
00326 #endif
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338 static const char *
00339 Format_Succ(BB *bb, INT isucc)
00340 {
00341 static char buf[] = "BB:12345+9223372036854775807 (probability 12345678901234567890)";
00342 INT len;
00343 INT nsuccs = BBINFO_nsuccs(bb);
00344
00345 if (nsuccs == 0) {
00346 strcpy(buf, "BB:-1");
00347 } else {
00348 INT64 offset = BBINFO_succ_offset(bb, isucc);
00349 len = sprintf(buf, "BB:%2d", BB_id(BBINFO_succ_bb(bb, isucc)));
00350 if (offset != 0) {
00351 len += sprintf(buf + len, "+%lld", offset);
00352 }
00353 if (freqs_computed) {
00354 sprintf(buf + len, " (probability %#.2f)", BBINFO_succ_prob(bb, isucc));
00355 }
00356 }
00357
00358 return buf;
00359 }
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370 void
00371 Print_BB_Info(BB *bb)
00372 {
00373 INT i;
00374
00375 fprintf(TFile, "part of %s region\n", BBINFO_cold(bb) ? "cold" : "hot");
00376 fprintf(TFile, "rid = 0x%p\n", BB_rid(bb));
00377 fprintf(TFile, "eh_rgn = %d\n", BBINFO_eh_rgn(bb));
00378
00379 fprintf(TFile, "kind = %s", BBKIND_Name(BBINFO_kind(bb)));
00380 switch (BBINFO_kind(bb)) {
00381 case BBKIND_GOTO:
00382 fprintf(TFile, "\nTarget:\t\t%s\n", Format_Succ(bb, 0));
00383 break;
00384 case BBKIND_LOGIF:
00385 fprintf(TFile, "%s\n", BBINFO_b_likely(bb) ? " (likely)" : "");
00386 fprintf(TFile, "Target 0:\t%s\n", Format_Succ(bb, 0));
00387 fprintf(TFile, "Target 1:\t%s\n", Format_Succ(bb, 1));
00388 fprintf(TFile, "Condition:\t");
00389 if (BBINFO_condval2(bb)) {
00390 Print_TN(BBINFO_condval1(bb), FALSE);
00391 fprintf(TFile, " %s ", BR_Variant_Name(BBINFO_variant(bb)));
00392 Print_TN(BBINFO_condval2(bb), FALSE);
00393 } else {
00394 fprintf(TFile, " %s ", BR_Variant_Name(BBINFO_variant(bb)));
00395 Print_TN(BBINFO_condval1(bb), FALSE);
00396 }
00397 fprintf(TFile, "\n");
00398 fprintf(TFile, "Compare OP:\t");
00399 Print_OP_No_SrcLine(BBINFO_compare_op(bb));
00400 break;
00401 case BBKIND_VARGOTO:
00402 fprintf(TFile, "\nListvar: 0x%p\n", BBINFO_vargoto_listvar(bb));
00403 fprintf(TFile, "RefCount: %d\n", *BBINFO_vargoto_refcount(bb));
00404 for (i = 0; i < BBINFO_nsuccs(bb); i++) {
00405 fprintf(TFile, "Target %d:\t%s\n", i, Format_Succ(bb, i));
00406 }
00407 break;
00408 case BBKIND_INDGOTO:
00409 fprintf(TFile, "\n");
00410 for (i = 0; i < BBINFO_nsuccs(bb); i++) {
00411 fprintf(TFile, "Target %d:\t%s\n", i, Format_Succ(bb, i));
00412 }
00413 break;
00414 case BBKIND_CALL:
00415 fprintf(TFile, "\nSuccessor:\t%s\n", Format_Succ(bb, 0));
00416 break;
00417 #if defined(TARG_SL)
00418 case BBKIND_ZDL_BODY:
00419 fprintf( TFile, "\nSuccessor 0:\t%s\n", Format_Succ(bb, 0));
00420 fprintf( TFile, "Successor 1:\t%s\n", Format_Succ(bb, 1));
00421 break;
00422 case BBKIND_FORK:
00423 fprintf( TFile, "\nSuccessor 0:\t%s\n", Format_Succ(bb, 0));
00424 fprintf( TFile, "Successor 1:\t%s\n", Format_Succ(bb, 1));
00425 break;
00426 #endif
00427 default:
00428 fprintf(TFile, "\n");
00429 break;
00430 }
00431 }
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442 void
00443 Print_Cflow_Graph(const char *banner)
00444 {
00445 BB *bb;
00446
00447 fprintf(TFile, "\n%s %s\n%s", DBar, banner, DBar);
00448
00449 for (bb = REGION_First_BB; bb; bb = BB_next(bb)) {
00450 fprintf(TFile, "\n%sBB:%d\n%s"
00451 "BB:%d (length:%d) -- flags = 0x%04x",
00452 SBar, BB_id(bb), SBar,
00453 BB_id(bb), BB_length(bb), BB_flag(bb));
00454 if (freqs_computed) fprintf(TFile, ", frequency = %g", BB_freq(bb));
00455 fprintf(TFile, "\n");
00456 if (BB_branch_wn(bb)) {
00457 fprintf(TFile, "Branch WN: ");
00458 fdump_tree(TFile, BB_branch_wn(bb));
00459 }
00460 Print_BB_Info(bb);
00461 }
00462 }
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485 static void Move_LoopHead(BB *head)
00486 {
00487 BB *bb;
00488 BB *new_head;
00489 INT cnt;
00490
00491
00492
00493
00494 new_head = head;
00495 cnt = 0;
00496 while (new_head = BB_Unique_Successor(new_head)) {
00497 if (BB_loop_head_bb(new_head) != BB_loop_head_bb(head)) {
00498
00499
00500
00501 new_head = NULL;
00502 break;
00503 }
00504
00505 if (!BB_unreachable(new_head)) {
00506
00507
00508
00509 BB_Copy_Annotations(new_head, head, ANNOT_LOOPINFO);
00510 BB_Copy_Annotations(new_head, head, ANNOT_PRAGMA);
00511 break;
00512 }
00513
00514 if (++cnt >= PU_BB_Count) {
00515
00516
00517
00518 new_head = NULL;
00519 break;
00520 }
00521 }
00522
00523
00524
00525
00526 for (bb = REGION_First_BB; bb; bb = BB_next(bb)) {
00527 if (BB_loop_head_bb(bb) == head) Set_BB_loop_head_bb(bb, new_head);
00528 }
00529 }
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541 static INT *ListVar_RefCount(ST *listvar)
00542 {
00543 LISTVAR_COUNT *counts;
00544
00545 if (listvar == NULL) return NULL;
00546
00547 for (counts = listvar_counts; counts; counts = counts->next) {
00548 if (counts->listvar == listvar) break;
00549 }
00550
00551 if (counts == NULL) {
00552 counts = TYPE_MEM_POOL_ALLOC(LISTVAR_COUNT, &MEM_local_nz_pool);
00553 counts->listvar = listvar;
00554 counts->count = 0;
00555 counts->next = listvar_counts;
00556 listvar_counts = counts;
00557 }
00558
00559 return &counts->count;
00560 }
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575 #if defined (TARG_IA64)
00576 static BOOL
00577 #else
00578 static void
00579 #endif
00580 Cflow_Change_Succ(BB *bb, INT isucc, BB *old_succ, BB *new_succ)
00581 {
00582 #if defined (TARG_IA64)
00583 if(IPFEC_Enable_Region_Formation && RGN_Formed) {
00584 if(Home_Region(bb)->Is_No_Further_Opt() ||
00585 Home_Region(old_succ)->Is_No_Further_Opt() ||
00586 Home_Region(new_succ)->Is_No_Further_Opt())
00587
00588
00589
00590
00591
00592 return FALSE;
00593 }
00594 #endif
00595
00596 INT i;
00597 INT nsuccs = BBINFO_nsuccs(bb);
00598 float prob = BBINFO_succ_prob(bb, isucc);
00599 BOOL prob_acced = FALSE;
00600
00601
00602 #if Is_True_On
00603 {
00604 BBINFO *old_bbinfo = BB_BBINFO(old_succ);
00605 BBINFO *new_bbinfo = BB_BBINFO(new_succ);
00606 if (new_bbinfo && old_bbinfo) {
00607 Is_True(old_bbinfo->cold == new_bbinfo->cold,
00608 ("changing succ of BB:%d from BB:%d to BB:%d crosses cold region",
00609 BB_id(bb), BB_id(old_succ), BB_id(new_succ)));
00610 }
00611 }
00612 #endif
00613
00614 BBLIST *old_edge = BB_Find_Succ(bb, old_succ);
00615 BBLIST *new_edge = BB_Find_Succ(bb, new_succ);
00616
00617 FmtAssert( old_edge, ("Expect old_edge") );
00618
00619 if ( new_edge
00620 && BBLIST_prob_fb_based(new_edge)
00621 && BBLIST_prob_fb_based(old_edge) ) {
00622
00623 BBLIST_prob(new_edge) += BBLIST_prob(old_edge);
00624 BBLIST_prob(old_edge) = 0;
00625 prob_acced = TRUE;
00626 }
00627 Set_BBINFO_succ_bb(bb, isucc, new_succ);
00628
00629
00630 for (i = 0; i < nsuccs; ++i) {
00631 if (i != isucc && BBINFO_succ_bb(bb, i) == old_succ) {
00632 if ( freqs_computed ) {
00633 float old_prob = BBLIST_prob(old_edge);
00634 BBLIST_prob(old_edge) = prob > old_prob ? 0.0 : old_prob - prob;
00635 }
00636 #if defined (TARG_IA64)
00637 if(IPFEC_Enable_Region_Formation && RGN_Formed) {
00638 RGN_Link_Pred_Succ_With_Prob(bb,new_succ,prob);
00639 return TRUE;
00640 } else {
00641 Link_Pred_Succ_with_Prob(bb, new_succ, prob);
00642 return TRUE;
00643 }
00644 #else
00645 Link_Pred_Succ_with_Prob(bb, new_succ, prob);
00646 return;
00647 #endif
00648 }
00649 }
00650 #if defined (TARG_IA64)
00651 if (IPFEC_Enable_Region_Formation && RGN_Formed) {
00652 RGN_Unlink_Pred_Succ(bb,old_succ);
00653 RGN_Link_Pred_Succ_With_Prob(bb,new_succ,prob);
00654 } else {
00655 Unlink_Pred_Succ(bb, old_succ);
00656 #if defined(KEY)
00657 Link_Pred_Succ_with_Prob(bb, new_succ, prob, FALSE, TRUE,
00658 BBLIST_prob_hint_based(old_edge) != 0, !prob_acced);
00659 #else
00660 Link_Pred_Succ_with_Prob(bb, new_succ, prob, FALSE, TRUE);
00661 #endif
00662 }
00663
00664 return TRUE;
00665 #else
00666 Unlink_Pred_Succ(bb, old_succ);
00667 #if defined(KEY)
00668 Link_Pred_Succ_with_Prob(bb, new_succ, prob, FALSE, TRUE,
00669 BBLIST_prob_hint_based(old_edge) != 0);
00670 #else
00671 Link_Pred_Succ_with_Prob(bb, new_succ, prob, FALSE, TRUE);
00672 #endif
00673 #endif
00674 }
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685 inline BOOL
00686 Pragma_Affects_Cflow(BB * )
00687 {
00688
00689
00690
00691
00692 return FALSE;
00693 }
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705 static BOOL
00706 Falls_Thru(BB *b, BB *succ)
00707 {
00708 INT i;
00709 INT nsuccs;
00710
00711 if (succ == NULL) {
00712 succ = BB_next(b);
00713 if (succ == NULL) return FALSE;
00714 }
00715
00716
00717
00718
00719 if (BBINFO_kind(b) == BBKIND_VARGOTO || BBINFO_kind(b) == BBKIND_INDGOTO) {
00720 return FALSE;
00721 }
00722
00723 nsuccs = BBINFO_nsuccs(b);
00724 for (i = 0; i < nsuccs; ++i) {
00725 if (BBINFO_succ_offset(b, i) == 0 && BBINFO_succ_bb(b, i) == succ) {
00726 return TRUE;
00727 }
00728 }
00729 return FALSE;
00730 }
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741 static BB *
00742 Alloc_BB_Like(BB *model)
00743 {
00744 BB *new_bb = deleted_bbs;
00745 BB_NUM id;
00746
00747
00748
00749 if (new_bb == NULL) return Gen_BB_Like(model);
00750
00751
00752
00753
00754 if (CFLOW_Trace) {
00755 #pragma mips_frequency_hint NEVER
00756 fprintf(TFile, "recycling BB:%d\n", BB_id(new_bb));
00757 }
00758 deleted_bbs = BB_next(new_bb);
00759 id = BB_id(new_bb);
00760 BZERO(new_bb, sizeof(*new_bb));
00761 new_bb->id = id;
00762 if (model) BB_rid(new_bb) = BB_rid(model);
00763 return new_bb;
00764 }
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774
00775 static void
00776 Remove_Annotations(BB *bb, ANNOTATION_KIND kind)
00777 {
00778 ANNOTATION *ant;
00779 ANNOTATION *next;
00780
00781 for (ant = ANNOT_First(BB_annotations(bb), kind); ant; ant = next) {
00782 next = ANNOT_Next(ant, kind);
00783 BB_annotations(bb) = ANNOT_Unlink(BB_annotations(bb), ant);
00784 }
00785 }
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797 static void
00798 Delete_BB_Contents(BB *bp)
00799 {
00800 BBLIST *edge;
00801
00802 if (CFLOW_Trace_Unreach) {
00803 #pragma mips_frequency_hint NEVER
00804 fprintf(TFile, "removing contents of BB:%d\n", BB_id(bp));
00805 }
00806
00807
00808
00809 if (BB_entry(bp)) {
00810 Entry_BB_Head = BB_LIST_Delete(bp, Entry_BB_Head);
00811 Reset_BB_entry(bp);
00812 Remove_Annotations(bp, ANNOT_ENTRYINFO);
00813 }
00814
00815 if (BB_exit(bp)) {
00816 Exit_BB_Head = BB_LIST_Delete(bp, Exit_BB_Head);
00817 Reset_BB_exit(bp);
00818 Remove_Annotations(bp, ANNOT_EXITINFO);
00819 }
00820
00821 if (BB_call(bp)) {
00822 Reset_BB_call(bp);
00823 Remove_Annotations(bp, ANNOT_CALLINFO);
00824 }
00825
00826 if (BB_asm(bp)) {
00827 Reset_BB_asm(bp);
00828 Remove_Annotations(bp, ANNOT_ASMINFO);
00829 }
00830
00831 if (BBINFO_kind(bp) == BBKIND_VARGOTO) {
00832 INT *refcount = BBINFO_vargoto_refcount(bp);
00833
00834
00835
00836 if (refcount != NULL && --(*refcount) == 0) {
00837 ST *listvar = BBINFO_vargoto_listvar(bp);
00838 Set_ST_is_not_used(listvar);
00839 }
00840 Remove_Annotations(bp, ANNOT_SWITCH);
00841 }
00842
00843 BB_branch_wn(bp) = NULL;
00844 BB_freq(bp) = 0.0;
00845
00846 if (!CG_localize_tns) {
00847 GTN_SET_ClearD(BB_live_in(bp));
00848 GTN_SET_ClearD(BB_live_out(bp));
00849 GTN_SET_ClearD(BB_defreach_in(bp));
00850 GTN_SET_ClearD(BB_defreach_out(bp));
00851 GTN_SET_ClearD(BB_live_use(bp));
00852 GTN_SET_ClearD(BB_live_def(bp));
00853 }
00854
00855
00856
00857 BB_Remove_All(bp);
00858 #ifdef TARG_IA64
00859 if (IPFEC_Enable_Region_Formation && RGN_Formed ) {
00860
00861
00862
00863 RGN_Unlink_BB_Edges(bp, Home_Region(bp)->Regional_Cfg());
00864
00865 }else{
00866 #endif
00867
00868
00869 FOR_ALL_BB_SUCCS(bp, edge) {
00870 BB *succ = BBLIST_item(edge);
00871 BBlist_Delete_BB(&BB_preds(succ), bp);
00872 }
00873 BBlist_Free(&BB_succs(bp));
00874
00875
00876
00877 FOR_ALL_BB_PREDS(bp, edge) {
00878 BB *pred = BBLIST_item(edge);
00879 BBlist_Delete_BB(&BB_succs(pred), bp);
00880 }
00881 BBlist_Free(&BB_preds(bp));
00882 #ifdef TARG_IA64
00883 }
00884 #endif
00885 Set_BBINFO_kind(bp, BBKIND_GOTO);
00886 Set_BBINFO_nsuccs(bp, 0);
00887 }
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898
00899 static void
00900 Delete_BB(BB *bp, BOOL trace)
00901 {
00902 BBLIST *edge;
00903
00904 if (trace) {
00905 #pragma mips_frequency_hint NEVER
00906 fprintf(TFile, "removing BB:%d\n", BB_id(bp));
00907 }
00908
00909
00910
00911
00912 if (BB_loophead(bp)) {
00913 Move_LoopHead(bp);
00914 }
00915
00916
00917
00918 if (BB_entry(bp)) Entry_BB_Head = BB_LIST_Delete(bp, Entry_BB_Head);
00919 if (BB_exit(bp)) Exit_BB_Head = BB_LIST_Delete(bp, Exit_BB_Head);
00920
00921
00922
00923
00924 if (BBINFO_kind(bp) == BBKIND_VARGOTO) {
00925 INT *refcount = BBINFO_vargoto_refcount(bp);
00926 if (refcount != NULL && --(*refcount) == 0) {
00927 ST *listvar = BBINFO_vargoto_listvar(bp);
00928 Set_ST_is_not_used(listvar);
00929 }
00930 }
00931
00932
00933
00934 BB_Remove_All(bp);
00935 #ifdef TARG_IA64
00936 if (IPFEC_Enable_Region_Formation && RGN_Formed ) {
00937
00938
00939
00940 RGN_Remove_BB_And_Edges(bp, Home_Region(bp)->Regional_Cfg());
00941
00942 }else{
00943 #endif
00944
00945
00946 Remove_BB(bp);
00947
00948
00949 HB_CFLOW_Remove_Block(bp);
00950
00951
00952
00953 FOR_ALL_BB_SUCCS(bp, edge) {
00954 BB *succ = BBLIST_item(edge);
00955 BBlist_Delete_BB(&BB_preds(succ), bp);
00956 }
00957 BBlist_Free(&BB_succs(bp));
00958
00959
00960
00961 FOR_ALL_BB_PREDS(bp, edge) {
00962 BB *pred = BBLIST_item(edge);
00963 BBlist_Delete_BB(&BB_succs(pred), bp);
00964 }
00965 BBlist_Free(&BB_preds(bp));
00966 #ifdef TARG_IA64
00967 }
00968 #endif
00969 Set_BBINFO_kind(bp, BBKIND_UNKNOWN);
00970 Set_BBINFO_nsuccs(bp, 0);
00971
00972
00973
00974 BB_next(bp) = deleted_bbs;
00975 deleted_bbs = BB_next(bp);
00976 }
00977
00978
00979 #ifdef VERIFY_INDIRECT_JUMP_TARGET
00980
00981
00982
00983
00984
00985
00986
00987
00988 static void
00989 Verify_Indirect_Jump_Target(OP *br, BB *tgt, INT64 offset)
00990 {
00991 INT i;
00992 OP *op;
00993 BB *bb = OP_bb(br);
00994 TN *tgt_tn = OP_opnd(br, 0);
00995
00996 FmtAssert(TN_is_register(tgt_tn), ("branch target not a register"));
00997
00998 FOR_ALL_BB_OPs_REV(bb, op) {
00999 for (i = OP_results(op) - 1; i >= 0; --i) {
01000 if (OP_result(op,i) == tgt_tn) goto got_result;
01001 }
01002 }
01003 got_result:
01004 if (op && OP_iadd(op) && TN_is_label(OP_opnd(op, 1))) {
01005 LABEL_IDX lab;
01006 TN *tn = OP_opnd(op, 1);
01007 INT64 tn_offset = TN_offset(tn);
01008 lab = TN_label(tn);
01009 FmtAssert(Is_Label_For_BB(lab, tgt) && tn_offset == offset,
01010 ("indirect jump add mistmatch"));
01011
01012 tgt_tn = OP_opnd(op, 0);
01013 for (op = OP_prev(op); op; op = OP_prev(op)) {
01014 for (i = OP_results(op) - 1; i >= 0; --i) {
01015 if (OP_result(op,i) == tgt_tn) goto got_prev_result;
01016 }
01017 }
01018 got_prev_result:
01019 if (op && OP_load(op) && TN_is_label(OP_opnd(op, 1))) {
01020 tn = OP_opnd(op, 1);
01021 lab = TN_label(tn);
01022 tn_offset = TN_offset(tn);
01023 FmtAssert(Is_Label_For_BB(lab, tgt) && tn_offset == offset,
01024 ("indirect jump load mistmatch"));
01025 }
01026 }
01027 }
01028 #endif
01029
01030
01031
01032
01033
01034
01035
01036
01037
01038
01039
01040 static BOOL
01041 Negate_Branch(OP *br)
01042 {
01043 TOP top = OP_code(br);
01044 TOP new_top = CGTARG_Invert(top);
01045
01046 if (new_top != TOP_UNDEFINED) {
01047 OP_Change_Opcode(br, new_top);
01048 return TRUE;
01049 }
01050
01051 if (OP_has_predicate(br)) {
01052 BB *br_bb = OP_bb(br);
01053 OP *cmp = BBINFO_compare_op(br_bb);
01054 if (cmp != NULL && OP_results(cmp) == 2) {
01055 if ( OP_has_predicate(cmp)
01056 && !TN_is_true_pred(OP_opnd(cmp,OP_PREDICATE_OPND))) return FALSE;
01057
01058 BB *cmp_bb = OP_bb(cmp);
01059 TN *r0 = OP_result(cmp,0);
01060 TN *r1 = OP_result(cmp,1);
01061 TN *pred = OP_opnd(br,OP_PREDICATE_OPND);
01062 TN *neg_tn = r0 == pred ? r1 : r0;
01063
01064 if (TN_is_true_pred(neg_tn)) {
01065 DevWarn("negative cmp result is a sink");
01066 return FALSE;
01067 }
01068
01069 Set_OP_opnd(br, OP_PREDICATE_OPND, neg_tn);
01070
01071 if (br_bb != cmp_bb && !CG_localize_tns) {
01072 GRA_LIVE_Compute_Local_Info(br_bb);
01073 GRA_LIVE_Region_Start();
01074 GRA_LIVE_Region_Entry(cmp_bb);
01075 GRA_LIVE_Region_Exit(br_bb);
01076 GRA_LIVE_Region_Compute_Global_Live_Info();
01077 }
01078
01079 return TRUE;
01080 }
01081 }
01082
01083 return FALSE;
01084 }
01085
01086
01087
01088
01089
01090
01091
01092
01093
01094
01095
01096
01097
01098
01099 static void Insert_Goto_BB(
01100 BB *bb,
01101 BB *targ_bb,
01102 INT64 targ_offset,
01103 BOOL fill_delay_slots
01104 )
01105 {
01106 LABEL_IDX lab;
01107 TN *lab_tn;
01108 BBLIST *sedge;
01109 BB *goto_bb;
01110 float goto_prob;
01111 BOOL goto_prob_fb;
01112 OPS ops = OPS_EMPTY;
01113 RID *rid = BB_rid(bb);
01114 BOOL region_is_scheduled = rid && RID_level(rid) >= RL_CGSCHED;
01115
01116
01117
01118
01119
01120
01121
01122 sedge = BB_Find_Succ(bb, targ_bb);
01123 goto_prob = BBLIST_prob(sedge);
01124 goto_prob_fb = BBLIST_prob_fb_based(sedge);
01125
01126 goto_bb = Alloc_BB_Like(bb);
01127 #ifdef TARG_IA64
01128 if (IPFEC_Enable_Region_Formation && RGN_Formed )
01129 RGN_Gen_And_Insert_Node(goto_bb, bb, targ_bb);
01130 #endif
01131
01132 BB_freq(goto_bb) = BB_freq(bb) * goto_prob;
01133
01134 Insert_BB(goto_bb, bb);
01135 #ifdef TARG_IA64
01136 if (IPFEC_Enable_Region_Formation && RGN_Formed )
01137 RGN_Link_Pred_Succ_With_Prob(goto_bb,targ_bb, 1.0);
01138 else
01139 Link_Pred_Succ_with_Prob(goto_bb, targ_bb, 1.0);
01140 #else
01141 Link_Pred_Succ_with_Prob(goto_bb, targ_bb, 1.0);
01142 #endif
01143 if (BB_freq_fb_based(bb) && goto_prob_fb) {
01144 BBLIST *edge = BB_Find_Succ(goto_bb, targ_bb);
01145 Set_BB_freq_fb_based(goto_bb);
01146 Set_BBLIST_prob_fb_based(edge);
01147 }
01148
01149 lab = Gen_Label_For_BB(targ_bb);
01150 lab_tn = Gen_Label_TN(lab, targ_offset);
01151 Exp_OP1(OPC_GOTO, NULL, lab_tn, &ops);
01152
01153 #ifdef TARG_SL
01154
01155 if (BB_last_op(bb) && (OP_srcpos(BB_last_op(bb)) != 0)) {
01156 OP_srcpos(OPS_last(&ops)) = OP_srcpos(BB_last_op(bb));
01157 }
01158 #endif
01159
01160 if ( PROC_has_branch_delay_slot()
01161 && (fill_delay_slots || region_is_scheduled))
01162 {
01163 Exp_Noop(&ops);
01164 Set_BB_scheduled(goto_bb);
01165 }
01166 BB_Append_Ops(goto_bb, &ops);
01167 #ifdef TARG_IA64
01168 if (IPFEC_Enable_Region_Formation && RGN_Formed ){
01169 RGN_Unlink_Pred_Succ(bb, targ_bb);
01170 RGN_Link_Pred_Succ_With_Prob(bb, goto_bb, goto_prob);
01171 }else{
01172 Unlink_Pred_Succ(bb, targ_bb);
01173 Link_Pred_Succ_with_Prob(bb, goto_bb, goto_prob);
01174 }
01175 #else
01176 Unlink_Pred_Succ(bb, targ_bb);
01177 Link_Pred_Succ_with_Prob(bb, goto_bb, goto_prob);
01178 #endif
01179 if (goto_prob_fb) {
01180 BBLIST *edge = BB_Find_Succ(bb, goto_bb);
01181 Set_BBLIST_prob_fb_based(edge);
01182 }
01183
01184 if (!CG_localize_tns) GRA_LIVE_Compute_Liveness_For_BB(goto_bb);
01185 }
01186
01187
01188
01189
01190
01191
01192
01193
01194
01195
01196 static void
01197 Finalize_BB(BB *bp)
01198 {
01199 BOOL fill_delay_slots = (current_flags & CFLOW_FILL_DELAY_SLOTS) != 0;
01200 #ifdef TARG_IA64
01201
01202
01203
01204
01205
01206
01207
01208 BOOL unreachable_bb = BB_unreachable(bp);
01209 if (unreachable_bb)
01210 return;
01211 #endif
01212 switch (BBINFO_kind(bp)) {
01213 case BBKIND_LOGIF:
01214 #ifdef TARG_IA64
01215 case BBKIND_CHK:
01216 #endif
01217 {
01218 INT tfirst;
01219 INT tcount;
01220 LABEL_IDX lab;
01221 TN *lab_tn;
01222 BB *fall_through;
01223 BB *target;
01224 float fall_through_prob;
01225 float target_prob;
01226 INT64 fall_through_offset;
01227 INT64 target_offset;
01228 OP *br = BB_branch_op(bp);
01229 #ifdef TARG_IA64
01230 if ((br == NULL) || OP_noop(br))
01231 {
01232 br = BB_Last_chk_op(bp);
01233 }
01234 #endif
01235
01236
01237 fall_through = BBINFO_succ_bb(bp, 1);
01238 fall_through_offset = BBINFO_succ_offset(bp, 1);
01239 fall_through_prob = BBINFO_succ_prob(bp, 1);
01240 target = BBINFO_succ_bb(bp, 0);
01241 target_offset = BBINFO_succ_offset(bp, 0);
01242 target_prob = BBINFO_succ_prob(bp, 0);
01243 #if defined(TARG_SL)
01244 if (!CG_sl2) {
01245
01246 if (fall_through_prob > target_prob) {
01247 if (BBINFO_b_likely(bp)) {
01248
01249 }
01250 else if (Negate_Branch(br)) {
01251 target = fall_through;
01252 target_offset = fall_through_offset;
01253 target_prob = fall_through_prob;
01254 fall_through = BBINFO_succ_bb(bp, 0);
01255 fall_through_offset = BBINFO_succ_offset(bp, 0);
01256 fall_through_prob = BBINFO_succ_prob(bp, 0);
01257 }
01258 }
01259 }
01260 else
01261 #endif
01262
01263
01264
01265
01266
01267 if ( (target == BB_next(bp) && target_offset == 0)
01268 || ( (fall_through != BB_next(bp) || fall_through_offset != 0)
01269 && (fall_through_prob > target_prob))
01270 ) {
01271 if (BBINFO_b_likely(bp)) {
01272
01273
01274
01275
01276
01277
01278
01279 } else if (Negate_Branch(br)) {
01280 target = fall_through;
01281 target_offset = fall_through_offset;
01282 target_prob = fall_through_prob;
01283 fall_through = BBINFO_succ_bb(bp, 0);
01284 fall_through_offset = BBINFO_succ_offset(bp, 0);
01285 fall_through_prob = BBINFO_succ_prob(bp, 0);
01286 }
01287 }
01288
01289
01290
01291
01292 Is_True(BB_Find_Succ(bp, target),
01293 ("BB:%d preds/succs don't match BBINFO", BB_id(bp)));
01294 Is_True( !freqs_computed
01295 || ( BBLIST_prob(BB_Find_Succ(bp, target))
01296 == (target != fall_through ? target_prob : 1.0)),
01297 ("BB:%d preds/succs don't match BBINFO", BB_id(bp)));
01298 lab = Gen_Label_For_BB(target);
01299 lab_tn = Gen_Label_TN(lab, target_offset);
01300 CGTARG_Branch_Info(br, &tfirst, &tcount);
01301 FmtAssert(tcount == 1, ("unexpected number of branch targets"));
01302 Set_OP_opnd(br, tfirst, lab_tn);
01303
01304
01305
01306
01307 Is_True(BB_Find_Succ(bp, fall_through),
01308 ("BB:%d preds/succs don't match BBINFO", BB_id(bp)));
01309 Is_True( !freqs_computed
01310 || ( BBLIST_prob(BB_Find_Succ(bp, fall_through))
01311 == (target != fall_through ? fall_through_prob : 1.0)),
01312 ("BB:%d preds/succs don't match BBINFO", BB_id(bp)));
01313 Is_True(BB_succs_len(bp) == (1 + (target != fall_through)),
01314 ("BB:%d preds/succs don't match BBINFO", BB_id(bp)));
01315 if (fall_through_offset != 0 || fall_through != BB_next(bp)) {
01316 Insert_Goto_BB(bp, fall_through, fall_through_offset, fill_delay_slots);
01317 }
01318 }
01319 break;
01320
01321 #if defined(TARG_SL)
01322 case BBKIND_ZDL_BODY:
01323 case BBKIND_FORK:
01324 {
01325 INT64 fall_through_offset;
01326 BB* fall_through;
01327 fall_through = BBINFO_succ_bb(bp, 1);
01328 fall_through_offset = BBINFO_succ_offset(bp, 1);
01329 if (fall_through_offset != 0 || fall_through != BB_next(bp)) {
01330 Insert_Goto_BB(bp, fall_through, fall_through_offset, fill_delay_slots);
01331 }
01332 }
01333 break;
01334 #endif
01335
01336 case BBKIND_GOTO:
01337 if (BBINFO_nsuccs(bp)) {
01338 BB *succ_bb = BBINFO_succ_bb(bp, 0);
01339 INT64 offset = BBINFO_succ_offset(bp, 0);
01340 RID *rid = BB_rid(bp);
01341 BOOL region_is_scheduled = rid && RID_level(rid) >= RL_CGSCHED;
01342
01343 Is_True(BB_Find_Succ(bp, succ_bb),
01344 ("BB:%d preds/succs don't match BBINFO", BB_id(bp)));
01345 Is_True( !freqs_computed
01346 #if defined(TARG_SL)
01347 || BB_freq_unbalanced(bp)
01348 #endif
01349 || (BBLIST_prob(BB_Find_Succ(bp, succ_bb)) == 1.0),
01350 ("BB:%d preds/succs don't match BBINFO", BB_id(bp)));
01351
01352 if ( offset == 0
01353 && succ_bb == BB_next(bp)
01354 && BBINFO_cold(bp) == BBINFO_cold(succ_bb)
01355 )
01356 {
01357
01358
01359
01360 #ifdef TARG_X8664
01361 if (!region_is_scheduled) BB_Remove_Branch(bp);
01362 #else
01363 if (!region_is_scheduled) {
01364 BB_Remove_Branch(bp);
01365 Reset_BB_scheduled(bp);
01366 }
01367 #endif
01368 } else if (BB_asm(bp)) {
01369
01370
01371
01372
01373
01374 Insert_Goto_BB(bp, succ_bb, offset, fill_delay_slots);
01375 } else {
01376
01377
01378
01379 OP *br = BB_branch_op(bp);
01380 LABEL_IDX lab = Gen_Label_For_BB(succ_bb);
01381 TN *lab_tn = Gen_Label_TN(lab, offset);
01382
01383 if (br != NULL) {
01384 INT tfirst;
01385 INT tcount;
01386
01387
01388
01389 CGTARG_Branch_Info(br, &tfirst, &tcount);
01390 if (tcount == 1) {
01391 Set_OP_opnd(br, tfirst, lab_tn);
01392 } else {
01393 FmtAssert(tcount == 0, ("unexpected number of branch targets"));
01394 #ifdef VERIFY_INDIRECT_JUMP_TARGET
01395 Verify_Indirect_Jump_Target(br, succ_bb, offset);
01396 #endif
01397 }
01398 } else {
01399 OPS ops = OPS_EMPTY;
01400
01401
01402
01403
01404 Exp_OP1(OPC_GOTO, NULL, lab_tn, &ops);
01405 if ( PROC_has_branch_delay_slot()
01406 && (fill_delay_slots || region_is_scheduled)) {
01407 Exp_Noop(&ops);
01408 }
01409 BB_Append_Ops(bp, &ops);
01410 #ifdef TARG_IA64
01411 Reset_BB_scheduled(bp);
01412 #endif
01413 }
01414 }
01415 }
01416 break;
01417
01418 case BBKIND_VARGOTO:
01419 case BBKIND_INDGOTO:
01420 #if 0
01421 {
01422 INT i;
01423 INT nsuccs = BBINFO_nsuccs(bp);
01424 struct succedge *edges = (struct succedge *)alloca(nsuccs * sizeof(struct succedge));
01425 INT n = 0;
01426 for (i = 0; i < nsuccs; ++i) {
01427 INT j;
01428 for (j = 0; j < n; ++j) {
01429 if (edges[j].bb == BBINFO_succ_bb(bp, i)) break;
01430 }
01431 if (j == n) {
01432 edges[j].bb = BBINFO_succ_bb(bp, i);
01433 edges[j].prob = BBINFO_succ_prob(bp, i);
01434 ++n;
01435 } else {
01436 edges[j].prob += BBINFO_succ_prob(bp, i);
01437 }
01438 }
01439 for (i = 0; i < n; ++i) {
01440 BB *succ = edges[i].bb;
01441 float prob = edges[i].prob;
01442 BBLIST *edge = BB_Find_Succ(bp, succ);
01443 Is_True(edge, ("BB:%d preds/succs don't match BBINFO", BB_id(bp)));
01444 Is_True(!freqs_computed || (BBLIST_prob(edge) == prob),
01445 ("BB:%d preds/succs don't match BBINFO", BB_id(bp)));
01446 }
01447 }
01448 #endif
01449 #if Is_True_On
01450 if (BBINFO_kind(bp) == BBKIND_VARGOTO) {
01451 ANNOTATION *ant = ANNOT_Get(BB_annotations(bp), ANNOT_SWITCH);
01452 ST *ant_listvar = ant ? ANNOT_switch(ant) : NULL;
01453 WN *br_wn = BB_branch_wn(bp);
01454 ST *bb_listvar = br_wn ? WN_st(br_wn) : NULL;
01455 ST *listvar = BBINFO_vargoto_listvar(bp);
01456 INT *refcount = BBINFO_vargoto_refcount(bp);
01457 Is_True(listvar == bb_listvar,
01458 ("bad WN_st for BB:%d listvar; bb-listvar=0x%p, bbinfo-listvar=0x%p",
01459 BB_id(bp), bb_listvar, listvar));
01460 Is_True(ant_listvar == listvar,
01461 ("bad ANNOT_switch for BB:%d; bad=0x%p, good=0x%p",
01462 BB_id(bp), ant_listvar, listvar));
01463 Is_True(listvar == NULL || *refcount > 0,
01464 ("bad VARGOTO jump table RefCount: %d", *refcount));
01465 }
01466 #endif
01467 break;
01468
01469 case BBKIND_CALL:
01470 if (BBINFO_nsuccs(bp)) {
01471 INT64 offset = BBINFO_succ_offset(bp, 0);
01472 BB *succ_bb = BBINFO_succ_bb(bp, 0);
01473 BB *next_bb = BB_next(bp);
01474
01475 Is_True( BBlist_Len(BB_succs(bp)) == 1
01476 && BBLIST_item(BB_succs(bp)) == succ_bb,
01477 ("BB:%d preds/succs don't match BBINFO", BB_id(bp)));
01478 Is_True(!freqs_computed || BBLIST_prob(BB_Find_Succ(bp, succ_bb)) == 1.0,
01479 ("BB:%d preds/succs don't match BBINFO", BB_id(bp)));
01480 Is_True(offset == 0, ("CALL BB:%d offset non-zero", BB_id(bp)));
01481
01482
01483
01484
01485 if (next_bb != succ_bb || offset != 0) {
01486 Insert_Goto_BB(bp, succ_bb, offset, fill_delay_slots);
01487 }
01488 }
01489 break;
01490
01491 case BBKIND_RETURN:
01492 case BBKIND_REGION_EXIT:
01493 case BBKIND_TAIL_CALL:
01494
01495
01496 break;
01497
01498 default:
01499 #pragma mips_frequency_hint NEVER
01500 FmtAssert(FALSE, ("Finalize_BB: unhandled BB kind (%s)",
01501 BBKIND_Name(BBINFO_kind(bp))));
01502
01503 }
01504 }
01505
01506
01507
01508
01509
01510
01511
01512
01513
01514
01515 static void
01516 Finalize_All_BBs(void)
01517 {
01518 BB *bp;
01519 BB *next;
01520
01521 for (bp = REGION_First_BB; bp; bp = next) {
01522
01523
01524
01525
01526 next = BB_next(bp);
01527
01528 Finalize_BB(bp);
01529 }
01530
01531
01532
01533 if (eh_label_removed) {
01534 EH_Prune_Range_List();
01535 }
01536 }
01537
01538
01539
01540
01541
01542
01543
01544
01545
01546
01547
01548
01549
01550
01551
01552
01553
01554
01555
01556 static BOOL
01557 Normalize_Branch_Target(BB **ptarget, INT64 *poffset)
01558 {
01559 BB *succ;
01560 OP *op;
01561 INT64 op_offset;
01562 BB *target = *ptarget;
01563 INT64 offset = *poffset;
01564
01565
01566
01567
01568 for (op_offset = 0, op = BB_first_op(target);;) {
01569 if (op == NULL) {
01570
01571
01572
01573
01574
01575 succ = BB_Unique_Successor(target);
01576 if (succ != BB_next(target)) return FALSE;
01577 target = succ;
01578 offset -= op_offset;
01579 op_offset = 0;
01580 op = BB_first_op(target);
01581 continue;
01582 } else if (op_offset >= offset) {
01583
01584
01585
01586
01587 break;
01588 } else {
01589
01590
01591
01592 INT num_ops = OP_Real_Ops(op);
01593 op_offset += num_ops * 4;
01594 op = OP_next(op);
01595 }
01596 }
01597
01598
01599
01600 *ptarget = target;
01601 *poffset = offset;
01602 return TRUE;
01603 }
01604
01605
01606
01607
01608
01609
01610
01611
01612
01613
01614
01615
01616
01617 static BOOL
01618 Initialize_BB_Info(void)
01619 {
01620
01621
01622
01623
01624 struct eh_ctx {
01625 INT32 rgn;
01626 struct eh_ctx *prev;
01627 struct eh_ctx *next;
01628 };
01629
01630 struct eh_ctx eh_stack;
01631 struct eh_ctx *eh_tos;
01632
01633
01634 INT eh_rgn;
01635 INT eh_id;
01636 BB *bb;
01637
01638
01639
01640
01641 eh_id = 0;
01642
01643
01644
01645
01646
01647 eh_tos = &eh_stack;
01648 eh_tos->rgn = 0;
01649 eh_tos->prev = NULL;
01650 eh_tos->next = NULL;
01651
01652 bb_info_map = BB_MAP_Create();
01653 for (bb = REGION_First_BB; bb; bb = BB_next(bb)) {
01654 BBINFO *bbinfo;
01655 INT bbinfo_size;
01656 BBKIND bbkind = BB_kind(bb);
01657
01658
01659
01660 bbinfo_size = sizeof(BBINFO);
01661 if (bbkind == BBKIND_VARGOTO || bbkind == BBKIND_INDGOTO) {
01662 INT incr = (BBlist_Len(BB_succs(bb)) - BBINFO_NSUCCS)
01663 * sizeof(struct succedge);
01664 if (incr > 0) bbinfo_size += incr;
01665 }
01666 bbinfo = (BBINFO *)MEM_POOL_Alloc(&MEM_local_nz_pool, bbinfo_size);
01667 BB_MAP_Set(bb_info_map, bb, bbinfo);
01668
01669
01670
01671 eh_rgn = eh_tos->rgn;
01672 if (BB_has_label(bb)) {
01673 ANNOTATION *ant;
01674
01675 for (ant = ANNOT_First(BB_annotations(bb), ANNOT_LABEL);
01676 ant != NULL;
01677 ant = ANNOT_Next(ant, ANNOT_LABEL)
01678 ) {
01679 LABEL_IDX lab = ANNOT_label(ant);
01680 switch (LABEL_kind(Label_Table[lab])) {
01681 case LKIND_BEGIN_EH_RANGE:
01682 {
01683 struct eh_ctx *eh_next = eh_tos->next;
01684
01685
01686
01687
01688
01689 if (eh_next == NULL) {
01690 eh_next = (eh_ctx *)alloca(sizeof(struct eh_ctx));
01691 eh_next->next = NULL;
01692 eh_next->prev = eh_tos;
01693 eh_tos->next = eh_next;
01694 }
01695 eh_tos = eh_next;
01696 eh_rgn = ++eh_id;
01697 eh_tos->rgn = eh_rgn;
01698 }
01699 break;
01700 case LKIND_END_EH_RANGE:
01701
01702
01703
01704 eh_tos = eh_tos->prev;
01705 Is_True(eh_tos, ("exception stack underflow"));
01706 break;
01707 }
01708 }
01709 }
01710
01711
01712
01713 bbinfo->eh_rgn = eh_rgn;
01714
01715
01716
01717
01718
01719 bbinfo->cold = BB_Is_Cold(bb);
01720
01721
01722
01723 bbinfo->kind = bbkind;
01724
01725 switch (bbkind) {
01726 case BBKIND_TAIL_CALL:
01727 case BBKIND_REGION_EXIT:
01728 case BBKIND_RETURN:
01729
01730
01731
01732 bbinfo->nsuccs = 0;
01733 continue;
01734
01735 case BBKIND_CALL:
01736 bbinfo->nsuccs = BB_succs(bb) ? 1 : 0;
01737 if (BB_succs(bb)) {
01738 bbinfo->succs[0].bb = BBLIST_item(BB_succs(bb));
01739 bbinfo->succs[0].offset = 0;
01740 bbinfo->succs[0].prob = 1.0;
01741 }
01742 continue;
01743
01744 case BBKIND_UNKNOWN:
01745
01746
01747
01748
01749 DevWarn("cflow giving up because BB:%d's kind is UNKNOWN", BB_id(bb));
01750 return FALSE;
01751
01752 case BBKIND_GOTO:
01753 bbinfo->nsuccs = BB_succs(bb) ? 1 : 0;
01754 if (BB_succs(bb)) {
01755 TN *lab_tn;
01756 OP *br = BB_branch_op(bb);
01757 BB *target = BBLIST_item(BB_succs(bb));
01758
01759 bbinfo->succs[0].bb = target;
01760 bbinfo->succs[0].offset = 0;
01761 bbinfo->succs[0].prob = 1.0;
01762
01763 if (br) {
01764 INT tfirst;
01765 INT tcount;
01766 CGTARG_Branch_Info(br, &tfirst, &tcount);
01767 FmtAssert(tcount == 1, ("unexpected number of branch targets"));
01768 lab_tn = OP_opnd(br, tfirst);
01769 if (TN_is_label(lab_tn)) {
01770 INT64 offset = TN_offset(lab_tn);
01771 if (offset != 0) {
01772 BB *orig_target = target;
01773 if (!Normalize_Branch_Target(&target, &offset)) {
01774 DevWarn("BB:%d branches past end of target BB:%d at line %d of %s",
01775 BB_id(bb), BB_id(target), __LINE__, __FILE__);
01776 return FALSE;
01777 }
01778 bbinfo->succs[0].offset = offset;
01779
01780 if (target != orig_target) {
01781 LABEL_IDX lab = Gen_Label_For_BB(target);
01782 TN *lab_tn = Gen_Label_TN(lab, offset);
01783 Set_OP_opnd(br, tfirst, lab_tn);
01784 Cflow_Change_Succ(bb, 0, orig_target, target);
01785 }
01786 }
01787 }
01788 } else if (target != BB_next(bb)) {
01789 DevWarn("BB:%d doesn't fall through, but branch inst not found at line %d of %s",
01790 BB_id(bb), __LINE__, __FILE__);
01791 return FALSE;
01792 }
01793 }
01794 continue;
01795
01796 case BBKIND_LOGIF:
01797 #ifdef TARG_IA64
01798 case BBKIND_CHK:
01799 #endif
01800 #if defined(TARG_SL)
01801 case BBKIND_ZDL_BODY:
01802 case BBKIND_FORK:
01803 #endif
01804 {
01805 INT tfirst;
01806 INT tcount;
01807 TN *lab_tn;
01808 BB *target;
01809 BBLIST *target_edge;
01810 BBLIST *fall_through_edge;
01811 OP *br = BB_branch_op(bb);
01812 #ifdef TARG_IA64
01813 if ((br == NULL) || OP_noop(br))
01814 {
01815 br = BB_Last_chk_op(bb);
01816 }
01817 #endif
01818
01819
01820
01821 target_edge = BB_succs(bb);
01822 fall_through_edge = BBLIST_next(target_edge);
01823 target = BBLIST_item(target_edge);
01824 if (fall_through_edge == NULL) {
01825 fall_through_edge = target_edge;
01826 } else if (target == BB_next(bb)) {
01827 target_edge = fall_through_edge;
01828 fall_through_edge = BB_succs(bb);
01829 target = BBLIST_item(target_edge);
01830 }
01831
01832 bbinfo->nsuccs = 2;
01833
01834 bbinfo->succs[0].bb = target;
01835 bbinfo->succs[0].offset = 0;
01836 bbinfo->succs[0].prob = BBLIST_prob(target_edge);
01837
01838 bbinfo->succs[1].bb = BB_next(bb);
01839 bbinfo->succs[1].offset = 0;
01840 bbinfo->succs[1].prob = BBLIST_prob(fall_through_edge);
01841
01842 #if defined(TARG_SL)
01843 if(br == NULL) continue;
01844 #endif
01845 CGTARG_Branch_Info(br, &tfirst, &tcount);
01846 FmtAssert(tcount == 1, ("unexpected number of branch targets"));
01847 lab_tn = OP_opnd(br, tfirst);
01848 if (TN_is_label(lab_tn)) {
01849 INT64 offset = TN_offset(lab_tn);
01850 if (offset != 0) {
01851 BB *orig_target = target;
01852 if (!Normalize_Branch_Target(&target, &offset)) {
01853 DevWarn("BB:%d branches past end of target BB:%d at line %d of %s",
01854 BB_id(bb), BB_id(target), __LINE__, __FILE__);
01855 return FALSE;
01856 }
01857 bbinfo->succs[0].offset = offset;
01858
01859 if (target != orig_target) {
01860 LABEL_IDX lab = Gen_Label_For_BB(target);
01861 TN *lab_tn = Gen_Label_TN(lab, offset);
01862 Set_OP_opnd(br, tfirst, lab_tn);
01863 Cflow_Change_Succ(bb, 0, orig_target, target);
01864 }
01865 }
01866 }
01867
01868
01869
01870 {
01871 TN *tn1 = NULL;
01872 TN *tn2 = NULL;
01873 OP *cmp = NULL;
01874 VARIANT variant = CGTARG_Analyze_Compare(br, &tn1, &tn2, &cmp);
01875
01876
01877
01878
01879
01880
01881 if ( cmp != NULL
01882 && OP_has_predicate(cmp)
01883 && !TN_is_true_pred(OP_opnd(cmp,OP_PREDICATE_OPND)))
01884 {
01885 cmp = NULL;
01886 }
01887
01888
01889
01890
01891
01892
01893 if (cmp == NULL) {
01894 variant = CGTARG_Analyze_Branch(br, &tn1, &tn2);
01895 cmp = br;
01896 }
01897
01898 bbinfo->u.l.variant = variant;
01899 bbinfo->u.l.tn1 = tn1;
01900 bbinfo->u.l.tn2 = tn2;
01901 bbinfo->u.l.compare_op = cmp;
01902 bbinfo->u.l.b_likely = OP_likely(br) != 0;
01903 }
01904 continue;
01905 }
01906
01907 case BBKIND_VARGOTO:
01908 case BBKIND_INDGOTO:
01909 {
01910 BBLIST *succ;
01911 INT nsuccs;
01912 if (bbkind == BBKIND_VARGOTO) {
01913 WN *br_wn = BB_branch_wn(bb);
01914 ST *listvar = br_wn ? WN_st(br_wn) : NULL;
01915 bbinfo->u.v.listvar = listvar;
01916 bbinfo->u.v.refcount = ListVar_RefCount(listvar);
01917 ++(*bbinfo->u.v.refcount);
01918 }
01919
01920 for (nsuccs = 0, succ = BB_succs(bb);
01921 succ != NULL;
01922 ++nsuccs, succ = BBLIST_next(succ)
01923 ) {
01924 bbinfo->succs[nsuccs].bb = BBLIST_item(succ);
01925 bbinfo->succs[nsuccs].offset = 0;
01926 bbinfo->succs[nsuccs].prob = BBLIST_prob(succ);
01927 }
01928 bbinfo->nsuccs = nsuccs;
01929
01930 #ifdef KEY
01931
01932
01933
01934
01935
01936 if( nsuccs == 0 &&
01937 bbkind == BBKIND_INDGOTO ){
01938 DevWarn( "%s BB:%d has no successors",
01939 BBKIND_Name(bbkind), BB_id(bb) );
01940 } else
01941 #endif
01942
01943 FmtAssert(nsuccs, ("%s BB:%d has no successors",
01944 BBKIND_Name(bbkind), BB_id(bb)));
01945 continue;
01946 }
01947 }
01948
01949 DevWarn("Don't know how to generate BBINFO for BB:%d at line %d of %s",
01950 BB_id(bb), __LINE__, __FILE__);
01951 return FALSE;
01952 }
01953
01954 have_eh_regions = eh_id != 0;
01955
01956 return TRUE;
01957 }
01958
01959
01960
01961
01962
01963
01964
01965
01966
01967
01968
01969
01970 static BOOL
01971 Is_Empty_BB(BB *bb)
01972 {
01973
01974
01975
01976
01977
01978 if (BB_gra_spill(bb)) return FALSE;
01979
01980 switch (BB_length(bb)) {
01981 #ifdef TARG_IA64
01982 case 3:
01983 if (BBINFO_kind(bb) == BBKIND_GOTO
01984 && BBINFO_nsuccs(bb)
01985 && BBINFO_cold(BBINFO_succ_bb(bb, 0)) != BBINFO_cold(bb)) return FALSE;
01986 if (BB_branch_op(bb) != NULL && OP_noop(BB_first_op(bb)) && OP_noop(BB_first_op(bb)->next)) return TRUE;
01987 #endif
01988 case 2:
01989 if (!PROC_has_branch_delay_slot() || !OP_noop(BB_last_op(bb))) return FALSE;
01990
01991 case 1:
01992 if (BBINFO_kind(bb) == BBKIND_GOTO
01993 && BBINFO_nsuccs(bb)
01994 && BBINFO_cold(BBINFO_succ_bb(bb, 0)) != BBINFO_cold(bb)) return FALSE;
01995 return BB_branch_op(bb) != NULL;
01996 case 0:
01997 return TRUE;
01998 }
01999 return FALSE;
02000 }
02001
02002
02003
02004
02005
02006
02007
02008
02009
02010
02011
02012
02013
02014
02015
02016
02017 static BOOL
02018 Normalize_Delay_Slots(void)
02019 {
02020 BB *bb;
02021 BOOL changed = FALSE;
02022
02023 for (bb = REGION_First_BB; bb; bb = BB_next(bb)) {
02024 OP *br_op = BB_branch_op(bb);
02025 if (br_op && OP_next(br_op) == NULL) {
02026 OP *op;
02027 INT delay_offset;
02028 BB *delay_bb;
02029 OP *delay_op;
02030
02031
02032
02033 for (delay_offset = 0, op = BB_first_op(bb); op; op = OP_next(op)) {
02034 INT num_ops = OP_Real_Ops(op);
02035 delay_offset += num_ops * 4;
02036 }
02037
02038 for (delay_bb = BB_next(bb);; delay_bb = BB_next(delay_bb)) {
02039 BBLIST *pred_edge;
02040
02041 FmtAssert(delay_bb, ("couldn't find delay slot op BB for BB:%d", BB_id(bb)));
02042 FOR_ALL_BB_PREDS(delay_bb, pred_edge) {
02043 INT nsuccs;
02044 INT i;
02045 BOOL found_succ;
02046 BB *pred = BBLIST_item(pred_edge);
02047 if (Falls_Thru(pred, delay_bb)) continue;
02048
02049 found_succ = FALSE;
02050 nsuccs = BBINFO_nsuccs(pred);
02051 for (i = 0; i < nsuccs; ++i) {
02052 if (BBINFO_succ_bb(pred, i) == delay_bb) {
02053 INT64 offset = BBINFO_succ_offset(pred, i);
02054 if (offset == 0) {
02055 Cflow_Change_Succ(pred, i, delay_bb, bb);
02056 Set_BBINFO_succ_offset(pred, i, delay_offset);
02057 DevWarn("moving BB:%d edge to delay slot op", BB_id(pred));
02058 } else {
02059 Set_BBINFO_succ_offset(pred, i, offset - 4);
02060 DevWarn("adjust BB:%d edge offset to delay BB", BB_id(pred));
02061 }
02062 found_succ = TRUE;
02063 }
02064 }
02065 FmtAssert(found_succ, ("no adjustments made on BB:%d -> BB:%d edge",
02066 BB_id(pred), BB_id(delay_bb)));
02067 changed = TRUE;
02068 }
02069
02070 FOR_ALL_BB_OPs_FWD(delay_bb, delay_op) {
02071 INT num_ops = OP_Real_Ops(delay_op);
02072 if (num_ops != 0) {
02073 FmtAssert(num_ops == 1, ("BB:%d delay slot op is > 1 real ops",
02074 BB_id(bb)));
02075 goto found_delay_op;
02076 }
02077 }
02078 }
02079 found_delay_op:
02080 DevWarn("BB:%d has delay slot op in BB:%d", BB_id(bb), BB_id(delay_bb));
02081
02082 BB_Remove_Op(delay_bb, delay_op);
02083 BB_Append_Op(bb, delay_op);
02084 }
02085 }
02086
02087 return changed;
02088 }
02089
02090
02091
02092
02093
02094
02095
02096
02097
02098
02099
02100
02101
02102
02103
02104
02105
02106
02107
02108
02109
02110
02111
02112 static BB *
02113 Collapse_Empty_Goto(BB *bp, BB *targ, float in_freq)
02114 {
02115 BB_NUM cnt;
02116 BB *new_targ;
02117
02118 if (BBINFO_cold(bp) != BBINFO_cold(targ)) return targ;
02119
02120 #ifdef TARG_X8664
02121 if( BB_savexmms_op(bp) != NULL )
02122 return targ;
02123 #endif
02124
02125 new_targ = targ;
02126 cnt = 0;
02127 while ( BBINFO_kind(new_targ) == BBKIND_GOTO
02128 && Is_Empty_BB(new_targ)
02129 && !BB_Has_Exc_Label(new_targ)
02130 && BBINFO_nsuccs(new_targ)
02131 && BBINFO_succ_bb(new_targ, 0) != new_targ
02132 ) {
02133 BB *last_targ;
02134 if (freqs_computed || BB_freq_fb_based(new_targ)) {
02135 float new_freq = BB_freq(new_targ) - in_freq;
02136 if (new_freq < 0.0F) {
02137 if ( CG_warn_bad_freqs
02138 && !BB_freq_fb_based(new_targ)
02139 && !FREQ_Match(BB_freq(new_targ), in_freq)
02140 ) {
02141 DevWarn("cflow (Collapse_Empty_Goto) found inconsistent freqs:\n"
02142 "\tmost likely, something before cflow is broken.\n"
02143 "\tcflow will cope but please submit a pv");
02144 }
02145 new_freq = 0.0F;
02146 }
02147 BB_freq(new_targ) = new_freq;
02148 }
02149 last_targ = new_targ;
02150 new_targ = BBINFO_succ_bb(new_targ, 0);
02151
02152
02153
02154
02155
02156 if (BB_has_note(last_targ)) {
02157 BB_Copy_Annotations(new_targ, last_targ, ANNOT_NOTE);
02158 Reset_BB_has_note(last_targ);
02159 }
02160
02161 cnt++;
02162 if (cnt >= PU_BB_Count) break;
02163
02164 }
02165
02166 if (CFLOW_Trace_Branch && new_targ != targ) {
02167 #pragma mips_frequency_hint NEVER
02168 fprintf(TFile, "replacing target BB:%d of %s BB:%d with BB:%d\n",
02169 BB_id(targ),
02170 BBKIND_Name(BBINFO_kind(bp)), BB_id(bp),
02171 BB_id(new_targ));
02172 }
02173
02174 return new_targ;
02175 }
02176
02177
02178
02179
02180
02181
02182
02183
02184
02185
02186
02187
02188
02189
02190
02191
02192
02193
02194 static BOOL
02195 Redundant_Logif(BB *pred, BB *succ, BOOL *pnegated)
02196 {
02197 OP *pred_cmp, *succ_cmp;
02198 BOOL negated;
02199 VARIANT pred_variant = BBINFO_variant(pred);
02200 VARIANT succ_variant = BBINFO_variant(succ);
02201
02202
02203
02204 if (pred_variant == succ_variant) {
02205 negated = FALSE;
02206 } else if (Negate_BR_Variant(pred_variant) == succ_variant) {
02207 negated = TRUE;
02208 } else {
02209 return FALSE;
02210 }
02211
02212
02213
02214 if ( BBINFO_condval1(pred) != BBINFO_condval1(succ)
02215 || BBINFO_condval2(pred) != BBINFO_condval2(succ)) return FALSE;
02216
02217
02218
02219
02220
02221 pred_cmp = BBINFO_compare_op(pred);
02222 succ_cmp = BBINFO_compare_op(succ);
02223 if ( pred_cmp != succ_cmp
02224 && (pred_cmp != BB_branch_op(pred) || succ_cmp != BB_branch_op(succ))
02225 ) return FALSE;
02226
02227 #ifdef TARG_NVISA
02228
02229
02230
02231 if (pred_cmp != succ_cmp) {
02232 DevWarn("differing cmp ops");
02233 if (OP_code(pred_cmp) == TOP_bra_p && OP_code(succ_cmp) == TOP_bra_np)
02234 negated = TRUE;
02235 else if (OP_code(pred_cmp) == TOP_bra_np && OP_code(succ_cmp) == TOP_bra_p)
02236 negated = TRUE;
02237 }
02238 #endif
02239
02240 #ifdef KEY
02241
02242
02243 if( PROC_has_branch_delay_slot() ){
02244 OP* last_op = BB_last_op( pred );
02245 if( !OP_br( last_op ) ){
02246 for( int i = 0; i < OP_results( last_op ); i++ ){
02247 TN* result = OP_result( last_op, i );
02248 if( result == BBINFO_condval1(succ) ||
02249 result == BBINFO_condval2(succ) ){
02250
02251 return FALSE;
02252 }
02253 }
02254 }
02255 }
02256 #endif
02257
02258
02259
02260 *pnegated = negated;
02261 return TRUE;
02262 }
02263
02264
02265
02266
02267
02268
02269
02270
02271
02272
02273
02274
02275
02276
02277
02278
02279
02280
02281
02282
02283
02284
02285
02286
02287 static BB *
02288 Collapse_Same_Logif(BB *bp, BB *targ, INT targ_idx, float edge_freq)
02289 {
02290 BOOL negated;
02291 BB *succ = Collapse_Empty_Goto(bp, targ, edge_freq);
02292 BB *new_succ = succ;
02293
02294 Is_True(BBINFO_kind(bp) == BBKIND_LOGIF,
02295 ("Collapse_Same_Logif called with %s BB:%d",
02296 BBKIND_Name(BBINFO_kind(bp)), BB_id(bp)));
02297
02298
02299
02300
02301
02302
02303
02304
02305 if ( bp != succ
02306 && Is_Empty_BB(succ)
02307 && BBINFO_kind(succ) == BBKIND_LOGIF
02308 && Redundant_Logif(bp, succ, &negated))
02309 {
02310 if (PROC_has_branch_delay_slot()) {
02311 OP *br_op = BB_branch_op(bp);
02312 OP *last_op = BB_last_op(bp);
02313 if ( last_op != br_op
02314 && OP_has_result(last_op)
02315 && OP_Refs_TN(br_op, OP_result(last_op,0))) return succ;
02316 }
02317
02318 new_succ = BBINFO_succ_bb(succ, targ_idx ^ negated);
02319 }
02320
02321 if (new_succ != succ) {
02322 if (freqs_computed || BB_freq_fb_based(succ)) {
02323
02324
02325
02326
02327
02328 float new_freq = BB_freq(succ) - edge_freq;
02329 if (new_freq < 0.0F) {
02330 if ( CG_warn_bad_freqs
02331 && !BB_freq_fb_based(succ)
02332 && !FREQ_Match(BB_freq(succ), edge_freq)
02333 ) {
02334 DevWarn("cflow (Collapse_Same_Logif) found inconsistent freqs:\n"
02335 "\tmost likely, something before cflow is broken.\n"
02336 "\tcflow will cope but please submit a pv");
02337 }
02338 new_freq = 0.0F;
02339 }
02340 BB_freq(succ) = new_freq;
02341 }
02342
02343 if (CFLOW_Trace_Branch) {
02344 #pragma mips_frequency_hint NEVER
02345 fprintf(TFile, "replacing target BB:%d of LOGIF BB:%d with BB:%d\n",
02346 BB_id(succ),
02347 BB_id(bp),
02348 BB_id(new_succ));
02349 }
02350 }
02351
02352 return new_succ;
02353 }
02354
02355
02356
02357
02358
02359
02360
02361
02362
02363
02364
02365
02366 static BOOL
02367 Convert_Indirect_Goto_To_Direct ( BB *bp )
02368 {
02369 INT i;
02370 BB *target;
02371 ST *listvar;
02372 BOOL vargoto = (BBINFO_kind(bp) == BBKIND_VARGOTO);
02373 INT nsuccs = BBINFO_nsuccs(bp);
02374
02375
02376
02377 if (nsuccs == 0) return FALSE;
02378
02379
02380
02381 target = BBINFO_succ_bb(bp, 0);
02382 for (i = 1; i < nsuccs; ++i) {
02383 if (BBINFO_succ_bb(bp, i) != target) return FALSE;
02384 }
02385
02386
02387
02388
02389 if (vargoto) {
02390 listvar = BBINFO_vargoto_listvar(bp);
02391 if (listvar == NULL) {
02392 DevWarn("Convert_Indirect_Goto_To_Direct: unable to convert BB:%d, no listvar",
02393 BB_id(bp));
02394 return FALSE;
02395 }
02396 if (--(*BBINFO_vargoto_refcount(bp)) == 0) Set_ST_is_not_used(listvar);
02397 }
02398
02399
02400
02401
02402 BBLIST_prob(BB_Find_Succ(bp, target)) = 1.0;
02403 Is_True( BBlist_Len(BB_succs(bp)) == 1
02404 && BBLIST_item(BB_succs(bp)) == target
02405 && BB_in_preds(target, bp),
02406 ("BB:%d preds/succs don't match BBINFO", BB_id(bp)));
02407
02408
02409
02410 Set_BBINFO_kind(bp, BBKIND_GOTO);
02411 Set_BBINFO_nsuccs(bp, 1);
02412 Set_BBINFO_succ_bb(bp, 0, target);
02413 Set_BBINFO_succ_offset(bp, 0, 0);
02414 Set_BBINFO_succ_prob(bp, 0, 1.0);
02415
02416
02417
02418 if (vargoto) Remove_Annotations(bp, ANNOT_SWITCH);
02419
02420
02421
02422
02423 BB_Remove_Branch(bp);
02424
02425 if (CFLOW_Trace_Branch) {
02426 #pragma mips_frequency_hint NEVER
02427 fprintf(TFile, "changing %s BB:%d to GOTO BB:%d\n",
02428 vargoto ? "VARGOTO" : "INDGOTO",
02429 BB_id(bp), BB_id(BBINFO_succ_bb(bp, 0)));
02430 }
02431 return TRUE;
02432 }
02433
02434
02435
02436
02437
02438
02439
02440
02441
02442
02443
02444
02445
02446
02447
02448 static BOOL
02449 Identical_Return_Blocks(BB *bb1, BB *bb2)
02450 {
02451 OP *op1, *op2;
02452 if (BB_length(bb1) != BB_length(bb2)) return FALSE;
02453 if (BBINFO_kind(bb1) != BBKIND_RETURN) return FALSE;
02454 if (BBINFO_kind(bb2) != BBKIND_RETURN) return FALSE;
02455
02456 for (op1 = BB_first_op(bb1), op2 = BB_first_op(bb2);
02457 op1;
02458 op1 = OP_next(op1), op2 = OP_next(op2)
02459 ) {
02460 INT i;
02461 if (OP_code(op1) != OP_code(op2)) return FALSE;
02462 if (OP_flags(op1) != OP_flags(op2)) return FALSE;
02463 for (i = 0; i < OP_results(op1); ++i) {
02464 if (OP_result(op1,i) != OP_result(op2,i)) return FALSE;
02465 }
02466 for (i = 0; i < OP_opnds(op1); ++i) {
02467 if (OP_opnd(op1,i) != OP_opnd(op2,i)) return FALSE;
02468 }
02469 }
02470
02471 return TRUE;
02472 }
02473
02474
02475
02476
02477
02478
02479
02480
02481
02482
02483
02484
02485
02486 static BOOL
02487 Convert_If_To_Goto ( BB *bp )
02488 {
02489 INT64 v1,v2;
02490 BOOL result;
02491 TN* tn1 = NULL;
02492 TN* tn2 = NULL;
02493 OP *compare_op = NULL;
02494 VARIANT br_variant = V_br_condition(BBINFO_variant(bp));
02495 BOOL false_br = V_false_br(BBINFO_variant(bp)) != 0;
02496 #ifdef TARG_IA64
02497 OP *op_br=BB_xfer_op(bp);
02498 TN *tn = OP_opnd(op_br, 0);
02499 if (tn==True_TN) {
02500 return FALSE;
02501 }
02502 #endif
02503
02504
02505 switch (br_variant) {
02506 case V_BR_NONE:
02507 case V_BR_CLOOP:
02508 case V_BR_CTOP:
02509 case V_BR_CEXIT:
02510 case V_BR_WTOP:
02511 case V_BR_WEXIT:
02512 return FALSE;
02513 }
02514
02515
02516
02517
02518 if ( !BBINFO_b_likely(bp)
02519 && BBINFO_succ_offset(bp, 0) == BBINFO_succ_offset(bp, 1)
02520 && ( BBINFO_succ_bb(bp, 0) == BBINFO_succ_bb(bp, 1)
02521 || Identical_Return_Blocks(BBINFO_succ_bb(bp, 0),
02522 BBINFO_succ_bb(bp, 1)))
02523 ) {
02524 result = FALSE;
02525 goto convert_it;
02526 }
02527
02528
02529
02530
02531 tn1 = BBINFO_condval1(bp);
02532 tn2 = BBINFO_condval2(bp);
02533 compare_op = BBINFO_compare_op(bp);
02534
02535 Is_True(tn1 != NULL, ("compare with no operands in BB:%d", BB_id(bp)));
02536
02537 if (!TN_Value_At_Op(tn1, compare_op, &v1)) goto try_identities;
02538
02539 if (tn2 && !TN_Value_At_Op(tn2, compare_op, &v2)) goto try_identities;
02540
02541
02542
02543 switch (br_variant) {
02544 case V_BR_I4EQ:
02545 case V_BR_U4EQ: result = (INT32)v1 == (INT32)v2; break;
02546 case V_BR_I4NE:
02547 case V_BR_U4NE: result = (INT32)v1 != (INT32)v2; break;
02548 case V_BR_I4GE: result = (INT32)v1 >= (INT32)v2; break;
02549 case V_BR_I4GT: result = (INT32)v1 > (INT32)v2; break;
02550 case V_BR_I4LE: result = (INT32)v1 <= (INT32)v2; break;
02551 case V_BR_I4LT: result = (INT32)v1 < (INT32)v2; break;
02552 case V_BR_U4GT: result = (UINT32)v1 > (UINT32)v2; break;
02553 case V_BR_U4GE: result = (UINT32)v1 >= (UINT32)v2; break;
02554 case V_BR_U4LT: result = (UINT32)v1 < (UINT32)v2; break;
02555 case V_BR_U4LE: result = (UINT32)v1 <= (UINT32)v2; break;
02556 case V_BR_I8EQ:
02557 case V_BR_U8EQ: result = v1 == v2; break;
02558 case V_BR_I8NE:
02559 case V_BR_U8NE: result = v1 != v2; break;
02560 case V_BR_I8GE: result = v1 >= v2; break;
02561 case V_BR_I8GT: result = v1 > v2; break;
02562 case V_BR_I8LE: result = v1 <= v2; break;
02563 case V_BR_I8LT: result = v1 < v2; break;
02564 case V_BR_U8GT: result = (UINT64)v1 > (UINT64)v2; break;
02565 case V_BR_U8GE: result = (UINT64)v1 >= (UINT64)v2; break;
02566 case V_BR_U8LT: result = (UINT64)v1 < (UINT64)v2; break;
02567 case V_BR_U8LE: result = (UINT64)v1 <= (UINT64)v2; break;
02568 default:
02569 #pragma mips_frequency_hint NEVER
02570 DevWarn("Unhandled branch VARIANT (%lld) for BB:%d at line %d of %s",
02571 (INT64)br_variant, BB_id(bp), __LINE__, __FILE__);
02572 return FALSE;
02573 }
02574
02575
02576
02577 convert_it:
02578 {
02579 BOOL br_taken = result ^ false_br;
02580 INT itarg = br_taken ? 0 : 1;
02581 INT64 offset = BBINFO_succ_offset(bp, itarg);
02582 BB *targ = BBINFO_succ_bb(bp, itarg);
02583 BB *dead = BBINFO_succ_bb(bp, !itarg);
02584 OP *br = BB_branch_op(bp);
02585
02586
02587
02588
02589
02590
02591 if (freqs_computed) {
02592 float freq = BB_freq(bp) * BBINFO_succ_prob(bp, !itarg);
02593 BB_freq(targ) += freq;
02594 BB_freq(dead) -= freq;
02595 if (BB_freq(dead) < 0.0F) BB_freq(dead) = 0.0F;
02596 }
02597
02598
02599
02600
02601
02602 if (!br_taken && BBINFO_b_likely(bp) && br != BB_last_op(bp)) {
02603 BB_Remove_Op(bp, BB_last_op(bp));
02604 }
02605
02606
02607
02608
02609 #ifdef TARG_X8664
02610 if( compare_op != NULL ){
02611 FmtAssert( OP_bb( compare_op ) == bp,
02612 ("compare op and branch op are located at different bbs") );
02613
02614 OP *op;
02615 BOOL delete_compare = TRUE;
02616 for (op = OP_next(compare_op); ; op = OP_next(op)) {
02617 if (op == br)
02618 break;
02619 else if (OP_reads_rflags(op)) {
02620 delete_compare = FALSE;
02621 break;
02622 }
02623 }
02624 if (delete_compare)
02625 BB_Remove_Op( bp, compare_op );
02626 }
02627 #endif
02628 BB_Remove_Op(bp, br);
02629
02630
02631
02632 #ifdef TARG_IA64
02633 if (targ != dead) {
02634 if (IPFEC_Enable_Region_Formation && RGN_Formed) {
02635 RGN_Unlink_Pred_Succ(bp,dead);
02636 } else {
02637 Unlink_Pred_Succ(bp, dead);
02638 }
02639 }
02640 #else
02641 if (targ != dead) Unlink_Pred_Succ(bp, dead);
02642 #endif
02643 BBLIST_prob(BB_Find_Succ(bp, targ)) = 1.0;
02644 Is_True( BBlist_Len(BB_succs(bp)) == 1
02645 && BBLIST_item(BB_succs(bp)) == targ
02646 && BB_in_preds(targ, bp),
02647 ("BB:%d preds/succs don't match BBINFO", BB_id(bp)));
02648
02649
02650
02651 Set_BBINFO_kind(bp, BBKIND_GOTO);
02652 Set_BBINFO_nsuccs(bp, 1);
02653 Set_BBINFO_succ_bb(bp, 0, targ);
02654 Set_BBINFO_succ_offset(bp, 0, offset);
02655 Set_BBINFO_succ_prob(bp, 0, 1.0);
02656
02657 if ( CFLOW_Trace_Branch ) {
02658 #pragma mips_frequency_hint NEVER
02659 fprintf(TFile, "changing BB:%d from LOGIF to GOTO-BB:%d\n",
02660 BB_id(bp), BB_id(targ));
02661 }
02662 }
02663 return TRUE;
02664
02665 try_identities:
02666 if ( tn1 == tn2 ) {
02667 switch (br_variant) {
02668 case V_BR_FGE:
02669 case V_BR_DGE:
02670 case V_BR_FLE:
02671 case V_BR_DLE:
02672 case V_BR_FEQ:
02673 case V_BR_DEQ:
02674 if (Force_IEEE_Comparisons) break;
02675
02676 case V_BR_I4GE:
02677 case V_BR_I4LE:
02678 case V_BR_U4GE:
02679 case V_BR_U4LE:
02680 case V_BR_I4EQ:
02681 case V_BR_U4EQ:
02682 case V_BR_I8GE:
02683 case V_BR_I8LE:
02684 case V_BR_U8GE:
02685 case V_BR_U8LE:
02686 case V_BR_I8EQ:
02687 case V_BR_U8EQ:
02688 result = TRUE; goto convert_it;
02689
02690 case V_BR_FLT:
02691 case V_BR_DLT:
02692 case V_BR_FGT:
02693 case V_BR_DGT:
02694 case V_BR_FNE:
02695 case V_BR_DNE:
02696 if (Force_IEEE_Comparisons) break;
02697
02698 case V_BR_I4LT:
02699 #ifdef KEY
02700 case V_BR_I4GT:
02701 #endif
02702 case V_BR_U4GT:
02703 case V_BR_U4LT:
02704 case V_BR_I4NE:
02705 case V_BR_U4NE:
02706 case V_BR_I8GT:
02707 case V_BR_I8LT:
02708 case V_BR_U8GT:
02709 case V_BR_U8LT:
02710 case V_BR_I8NE:
02711 case V_BR_U8NE:
02712 result = FALSE; goto convert_it;
02713
02714 case V_BR_FOR:
02715 case V_BR_FUO:
02716 case V_BR_DOR:
02717 case V_BR_DUO: break;
02718
02719 default:
02720 #pragma mips_frequency_hint NEVER
02721 DevWarn("Unhandled branch VARIANT (%lld) for BB:%d at line %d of %s",
02722 (INT64)br_variant, BB_id(bp), __LINE__, __FILE__);
02723 #ifdef TARG_X8664
02724 FmtAssert( false, ("NYI") );
02725 #endif
02726 }
02727 }
02728 return FALSE;
02729 }
02730
02731
02732
02733
02734
02735
02736
02737
02738
02739
02740
02741
02742
02743
02744
02745
02746
02747
02748
02749 static BOOL Branches_Around(BB *if_bb)
02750 {
02751 BB *succ0;
02752 BB *succ1;
02753 INT64 offset0;
02754 INT64 offset1;
02755 BB *next;
02756
02757
02758
02759 if (BBINFO_kind(if_bb) != BBKIND_LOGIF) return FALSE;
02760
02761
02762
02763 next = BB_next(if_bb);
02764 succ0 = BBINFO_succ_bb(if_bb, 0);
02765 succ1 = BBINFO_succ_bb(if_bb, 1);
02766 offset0 = BBINFO_succ_offset(if_bb, 0);
02767 offset1 = BBINFO_succ_offset(if_bb, 1);
02768
02769
02770
02771 if (succ0 != next) {
02772 BB *t;
02773
02774
02775
02776 if (succ1 != next) return FALSE;
02777
02778 t = succ0;
02779 succ0 = succ1;
02780 succ1 = t;
02781
02782 offset1 = offset0;
02783 }
02784
02785
02786
02787 if (offset1 != 0) return FALSE;
02788
02789
02790
02791 do {
02792 succ0 = next;
02793 next = BB_next(succ0);
02794 } while (Falls_Thru(succ0, next));
02795
02796
02797
02798 return next == succ1;
02799 }
02800
02801
02802
02803
02804
02805
02806
02807
02808
02809
02810
02811
02812 static BOOL
02813 Convert_Goto_To_If ( BB *bp, mBOOL *used_branch_around )
02814 {
02815 OP *compare_op;
02816 OP *old_cond_br;
02817 OP *new_cond_br;
02818 BB *targ_0;
02819 BB *targ_1;
02820 INT64 offset_0;
02821 INT64 offset_1;
02822 float prob_0;
02823 float prob_1;
02824 BB *targ;
02825
02826
02827
02828
02829 if (BBINFO_nsuccs(bp) == 0 || BBINFO_succ_offset(bp, 0) != 0) return FALSE;
02830
02831
02832
02833
02834 targ = BBINFO_succ_bb(bp, 0);
02835 if ( BBINFO_kind(targ) != BBKIND_LOGIF
02836 || BB_length(targ) != 1
02837 || BBINFO_b_likely(targ)
02838 ) return FALSE;
02839
02840
02841
02842 if (BB_scheduled(bp) || BB_scheduled(targ)) return FALSE;
02843
02844
02845
02846 targ_0 = BBINFO_succ_bb(targ, 0);
02847 targ_1 = BBINFO_succ_bb(targ, 1);
02848 offset_0 = BBINFO_succ_offset(targ, 0);
02849 offset_1 = BBINFO_succ_offset(targ, 1);
02850 prob_0 = BBINFO_succ_prob(targ, 0);
02851 prob_1 = BBINFO_succ_prob(targ, 1);
02852
02853 #ifdef TARG_IA64
02854
02855
02856
02857
02858 if (IPFEC_Enable_Region_Formation && RGN_Formed) {
02859 REGIONAL_CFG_NODE *node = Regional_Cfg_Node(targ);
02860 if (node->Is_Entry()) return FALSE;
02861 if (node->Is_Loop_Tail()) {
02862 DevWarn("LOST ONE CHANCE OF CONVERT GOTO TO IF BECAUSE OF LOOP TAIL!");
02863 return FALSE;
02864 }
02865 }
02866 #endif
02867
02868
02869
02870
02871
02872
02873 if (current_flags & CFLOW_OPT_ALL_BR_TO_BCOND) {
02874
02875
02876
02877 } else if ( (BB_next(bp) == targ_0 && offset_0 == 0)
02878 || (BB_next(bp) == targ_1 && offset_1 == 0)
02879 ) {
02880
02881
02882
02883
02884 } else if ( (current_flags & (CFLOW_REORDER | CFLOW_FREQ_ORDER))
02885 && !used_branch_around[BB_id(targ)]
02886 && Branches_Around(targ))
02887 {
02888
02889
02890
02891
02892
02893
02894
02895
02896
02897 used_branch_around[BB_id(targ)] = TRUE;
02898 #if 0
02899 } else if ( ) {
02900
02901
02902
02903
02904
02905 #endif
02906 } else {
02907
02908
02909
02910 return FALSE;
02911 }
02912
02913
02914
02915 BB_Remove_Branch(bp);
02916
02917
02918
02919 old_cond_br = BB_branch_op(targ);
02920 new_cond_br = Dup_OP(old_cond_br);
02921 BB_Append_Op(bp, new_cond_br);
02922
02923
02924
02925 if (!CG_localize_tns) {
02926 INT i;
02927 for (i = 0; i < OP_opnds(new_cond_br); ++i) {
02928 TN *tn = OP_opnd(new_cond_br, i);
02929 if (TN_is_constant(tn)) continue;
02930 if (TN_is_const_reg(tn)) continue;
02931 if (!GTN_SET_MemberP(BB_live_def(bp), tn)) {
02932 if (!TN_is_global_reg(tn))
02933 GTN_UNIVERSE_Add_TN(tn);
02934
02935 GRA_LIVE_Add_Live_Use_GTN(bp, tn);
02936 }
02937 }
02938 }
02939
02940
02941
02942 BB_branch_wn(bp) = BB_branch_wn(targ);
02943
02944
02945
02946
02947
02948 compare_op = BBINFO_compare_op(targ);
02949 if (compare_op == old_cond_br) compare_op = new_cond_br;
02950
02951
02952
02953 #ifdef TARG_IA64
02954 if (IPFEC_Enable_Region_Formation && RGN_Formed) {
02955 RGN_Unlink_Pred_Succ(bp,targ);
02956 } else {
02957 Unlink_Pred_Succ(bp, targ);
02958 }
02959 #else
02960 Unlink_Pred_Succ(bp, targ);
02961 #endif
02962
02963 Is_True(BB_succs(bp) == NULL,
02964 ("BB:%d preds/succs don't match BBINFO", BB_id(bp)));
02965 #ifdef TARG_IA64
02966 if (IPFEC_Enable_Region_Formation && RGN_Formed) {
02967 RGN_Link_Pred_Succ_With_Prob(bp,targ_0,prob_0);
02968 RGN_Link_Pred_Succ_With_Prob(bp,targ_1,prob_1);
02969 } else {
02970 Link_Pred_Succ_with_Prob(bp, targ_0, prob_0, FALSE, TRUE);
02971 Link_Pred_Succ_with_Prob(bp, targ_1, prob_1, FALSE, TRUE);
02972 }
02973 #else
02974 Link_Pred_Succ_with_Prob(bp, targ_0, prob_0, FALSE, TRUE);
02975 Link_Pred_Succ_with_Prob(bp, targ_1, prob_1, FALSE, TRUE);
02976 #endif
02977
02978
02979
02980
02981 Set_BBINFO_succ_bb(bp, 0, targ_0);
02982 Set_BBINFO_succ_bb(bp, 1, targ_1);
02983 Set_BBINFO_succ_offset(bp, 0, offset_0);
02984 Set_BBINFO_succ_offset(bp, 1, offset_1);
02985 Set_BBINFO_succ_prob(bp, 0, prob_0);
02986 Set_BBINFO_succ_prob(bp, 1, prob_1);
02987 Set_BBINFO_condval1(bp, BBINFO_condval1(targ));
02988 Set_BBINFO_condval2(bp, BBINFO_condval2(targ));
02989 Set_BBINFO_compare_op(bp, compare_op);
02990 Set_BBINFO_variant(bp, BBINFO_variant(targ));
02991 Set_BBINFO_b_likely(bp, FALSE);
02992 Set_BBINFO_nsuccs(bp, 2);
02993 Set_BBINFO_kind(bp, BBKIND_LOGIF);
02994
02995
02996
02997
02998 if (freqs_computed || (BB_freq_fb_based(bp) && BB_freq_fb_based(targ))) {
02999 double targ_freq = BB_freq(targ);
03000 double bb_freq = BB_freq(bp);
03001 double new_targ_freq = targ_freq - bb_freq;
03002
03003 if (new_targ_freq < 0.0F) {
03004 if ( CG_warn_bad_freqs
03005 && !BB_freq_fb_based(bp)
03006 && !BB_freq_fb_based(targ)
03007 && !FREQ_Match(targ_freq, bb_freq)
03008 ) {
03009 DevWarn("cflow (Convert_Goto_To_If) found inconsistent freqs:\n"
03010 "\tmost likely, something before cflow is broken.\n"
03011 "\tcflow will cope but please submit a pv");
03012 }
03013 new_targ_freq = 0.0F;
03014 }
03015 BB_freq(targ) = new_targ_freq;
03016 }
03017
03018 if ( CFLOW_Trace_Branch ) {
03019 #pragma mips_frequency_hint NEVER
03020 fprintf(TFile, "changing BB:%d from GOTO-BB:%d to LOGIF-(BB:%d, BB:%d)\n",
03021 BB_id(bp),
03022 BB_id(targ),
03023 BB_id(targ_1),
03024 BB_id(targ_0));
03025 }
03026
03027 return TRUE;
03028 }
03029
03030
03031
03032
03033
03034
03035
03036
03037
03038
03039
03040
03041 static BOOL
03042 Convert_Goto_To_Return ( BB *bp )
03043 {
03044 OP *new_op;
03045 OP *br_op;
03046 OP *br_delay_op;
03047 OP *rtn_op;
03048 BB *targ;
03049 INT64 offset;
03050
03051
03052
03053
03054 if ( BBINFO_nsuccs(bp) == 0 ) return FALSE;
03055 targ = BBINFO_succ_bb(bp, 0);
03056 offset = BBINFO_succ_offset(bp, 0);
03057
03058
03059
03060
03061 if ( BBINFO_kind(targ) != BBKIND_RETURN || offset < 0 ) return FALSE;
03062
03063 Is_True((offset % INST_BYTES) == 0,
03064 ("instruction offset not a multiple of %d", INST_BYTES));
03065
03066
03067
03068
03069
03070 for (rtn_op = BB_first_op(targ);
03071 ;
03072 rtn_op = OP_next(rtn_op), offset -= INST_BYTES)
03073 {
03074 if ( rtn_op == NULL ) return FALSE;
03075 if ( offset == 0 ) break;
03076 }
03077 if ( !OP_br(rtn_op) ) return FALSE;
03078
03079
03080
03081 if ( PROC_has_branch_delay_slot() ) {
03082 OP *rtn_delay_op = OP_next(rtn_op);
03083 if ( rtn_delay_op && !OP_noop(rtn_delay_op) ) return FALSE;
03084 }
03085
03086
03087
03088
03089 br_op = BB_branch_op(bp);
03090 br_delay_op = NULL;
03091 if (PROC_has_branch_delay_slot()) {
03092 BOOL fill_delay = (current_flags & CFLOW_FILL_DELAY_SLOTS) != 0;
03093 RID *rid = BB_rid(bp);
03094 BOOL region_is_scheduled = rid && RID_level(rid) >= RL_CGSCHED;
03095 if ( fill_delay || region_is_scheduled ) {
03096 br_delay_op = br_op ? OP_next(br_op) : BB_last_op(bp);
03097
03098
03099
03100 if (!Is_Delay_Slot_Op(br_op, br_delay_op)) return FALSE;
03101
03102 if (br_delay_op) {
03103 if (OP_Defs_Reg(br_delay_op, REGISTER_CLASS_ra, REGISTER_ra)) {
03104 br_delay_op = NULL;
03105 } else if (fill_delay && br_delay_op == BB_last_op(bp)) {
03106
03107
03108
03109
03110
03111
03112
03113
03114
03115 BB *prev = BB_prev(bp);
03116 if (prev && Falls_Thru(prev, bp)) {
03117 OP *last_op = BB_last_op(prev);
03118 if (last_op && last_op == BB_branch_op(prev)) {
03119 br_delay_op = NULL;
03120 }
03121 }
03122 }
03123 }
03124 if ( br_delay_op == NULL ) {
03125 OPS ops = OPS_EMPTY;
03126 Exp_Noop(&ops);
03127 BB_Append_Ops(bp, &ops);
03128 br_delay_op = BB_last_op(bp);
03129 }
03130 }
03131 }
03132
03133
03134
03135 new_op = Dup_OP(rtn_op);
03136 if ( br_delay_op ) {
03137 BB_Insert_Op_Before(bp, br_delay_op, new_op);
03138 } else {
03139 BB_Append_Op(bp, new_op);
03140 }
03141 if ( br_op ) BB_Remove_Op(bp, br_op);
03142
03143 #ifdef TARG_IA64
03144 if (IPFEC_Enable_Region_Formation && RGN_Formed) {
03145 RGN_Unlink_Pred_Succ(bp,targ);
03146 } else {
03147 Unlink_Pred_Succ(bp, targ);
03148 }
03149 #else
03150 Unlink_Pred_Succ(bp, targ);
03151 #endif
03152 Is_True(BB_succs(bp) == NULL,
03153 ("BB:%d preds/succs don't match BBINFO", BB_id(bp)));
03154
03155 Set_BBINFO_nsuccs(bp, 0);
03156 Set_BBINFO_kind(bp, BBKIND_RETURN);
03157
03158 if (BB_call(targ)) {
03159 FmtAssert(BB_Copy_Annotations(bp, targ, ANNOT_CALLINFO),
03160 ("no CALLINFO annotations for BB:%d", BB_id(targ)));
03161 }
03162
03163 if (BB_exit(targ)) {
03164 FmtAssert(BB_Copy_Annotations(bp, targ, ANNOT_EXITINFO),
03165 ("no EXITINFO annotations for BB:%d", BB_id(targ)));
03166
03167 ANNOTATION *ant = ANNOT_Get(BB_annotations(bp), ANNOT_EXITINFO);
03168 EXITINFO *exit_info = ANNOT_exitinfo(ant);
03169 OP *sp_adj = EXITINFO_sp_adj(exit_info);
03170 FmtAssert(sp_adj == NULL, ("bypassing sp-adjust in BB:%d", BB_id(bp)));
03171
03172 Exit_BB_Head = BB_LIST_Push(bp, Exit_BB_Head, &MEM_pu_pool);
03173 }
03174
03175
03176
03177
03178 if (freqs_computed || (BB_freq_fb_based(bp) && BB_freq_fb_based(targ))) {
03179 double targ_freq = BB_freq(targ);
03180 double bb_freq = BB_freq(bp);
03181 double new_targ_freq = targ_freq - bb_freq;
03182
03183 if (new_targ_freq < 0.0F) {
03184 if ( CG_warn_bad_freqs
03185 && !BB_freq_fb_based(bp)
03186 && !BB_freq_fb_based(targ)
03187 && !FREQ_Match(targ_freq, bb_freq)
03188 ) {
03189 DevWarn("cflow (Convert_Goto_To_Return) found inconsistent freqs:\n"
03190 "\tmost likely, something before cflow is broken.\n"
03191 "\tcflow will cope but please submit a pv");
03192 }
03193 new_targ_freq = 0.0F;
03194 }
03195 BB_freq(targ) = new_targ_freq;
03196 }
03197
03198 if ( CFLOW_Trace_Branch ) {
03199 #pragma mips_frequency_hint NEVER
03200 fprintf(TFile, "changing BB:%d from GOTO-BB:%d+%lld to RETURN\n",
03201 BB_id(bp),
03202 BB_id(targ),
03203 offset);
03204 }
03205
03206 return TRUE;
03207 }
03208
03209
03210
03211
03212
03213
03214
03215
03216
03217
03218
03219
03220
03221
03222
03223
03224
03225 static BOOL
03226 Optimize_Branches(void)
03227 {
03228 INT pass;
03229 mBOOL *used_branch_around;
03230 float edge_freq = 0.0;
03231 BOOL changed;
03232
03233 #ifdef TARG_IA64
03234
03235
03236
03237
03238 BOOL chan_succ = FALSE;
03239 #endif
03240
03241 used_branch_around = (mBOOL *)alloca((PU_BB_Count + 2) * sizeof(*used_branch_around));
03242 BZERO(used_branch_around, (PU_BB_Count + 2) * sizeof(*used_branch_around));
03243 pass = 0;
03244 do {
03245 BB *bp;
03246 changed = FALSE;
03247 pass++;
03248 for (bp = REGION_First_BB; bp; bp = BB_next(bp)) {
03249
03250 #ifdef TARG_IA64
03251 if (IPFEC_Enable_Region_Formation && RGN_Formed) {
03252 if(Home_Region(bp)->Is_No_Further_Opt())
03253 continue;
03254 }
03255 #endif
03256
03257 BB *old_tgt, *new_tgt;
03258 ST *st;
03259 INT i;
03260 RID *rid = BB_rid(bp);
03261 #ifdef TARG_IA64
03262 BOOL flag=FALSE;
03263 #endif
03264
03265
03266
03267 if (rid && RID_level(rid) >= RL_CGSCHED) continue;
03268
03269 switch (BBINFO_kind(bp)) {
03270 case BBKIND_LOGIF:
03271 if (Convert_If_To_Goto(bp)) {
03272 old_tgt = BBINFO_succ_bb(bp, 0);
03273 new_tgt = Collapse_Empty_Goto(bp, old_tgt, BB_freq(bp));
03274 if (new_tgt != old_tgt) {
03275 #ifdef TARG_IA64
03276 chan_succ = Cflow_Change_Succ(bp, 0, old_tgt, new_tgt);
03277 }
03278 changed = TRUE;
03279 } else {
03280 if (freqs_computed) {
03281 edge_freq = BBINFO_succ_prob(bp, 0) * BB_freq(bp);
03282 }
03283 old_tgt = BBINFO_succ_bb(bp, 0);
03284 if (IPFEC_Enable_Region_Formation && RGN_Formed) {
03285 REGIONAL_CFG_NODE *tgt_node=Regional_Cfg_Node(old_tgt);
03286 if((Home_Region(old_tgt)->Region_Type()==LOOP) &&
03287 (tgt_node->Succ_Num() == 0)) {
03288 flag=TRUE;
03289 }
03290 }
03291 if (!flag){
03292 new_tgt = Collapse_Same_Logif(bp, old_tgt, 0, edge_freq);
03293 if (new_tgt != old_tgt) {
03294 chan_succ = Cflow_Change_Succ(bp, 0, old_tgt, new_tgt);
03295 if (chan_succ) {
03296 changed = TRUE;
03297 } else {
03298 BB_freq(old_tgt) = edge_freq;
03299 }
03300 }
03301 }
03302
03303 flag=FALSE;
03304 if (freqs_computed) {
03305 edge_freq = BBINFO_succ_prob(bp, 1) * BB_freq(bp);
03306 }
03307 old_tgt = BBINFO_succ_bb(bp, 1);
03308 if (IPFEC_Enable_Region_Formation && RGN_Formed) {
03309 REGIONAL_CFG_NODE *tgt_node=Regional_Cfg_Node(old_tgt);
03310 if((Home_Region(old_tgt)->Region_Type()==LOOP) &&
03311 (tgt_node->Succ_Num() == 0)) {
03312 flag=TRUE;
03313 }
03314 }
03315 if (!flag){
03316 new_tgt = Collapse_Same_Logif(bp, old_tgt, 1, edge_freq);
03317 if (new_tgt != old_tgt) {
03318 chan_succ = Cflow_Change_Succ(bp, 1, old_tgt, new_tgt);
03319 if (chan_succ) {
03320 changed = TRUE;
03321 } else {
03322 BB_freq(old_tgt) = edge_freq;
03323 }
03324 }
03325 }
03326 #else
03327 Cflow_Change_Succ(bp, 0, old_tgt, new_tgt);
03328 }
03329 changed = TRUE;
03330 } else {
03331 if (freqs_computed) {
03332 edge_freq = BBINFO_succ_prob(bp, 0) * BB_freq(bp);
03333 }
03334 old_tgt = BBINFO_succ_bb(bp, 0);
03335 new_tgt = Collapse_Same_Logif(bp, old_tgt, 0, edge_freq);
03336 if (new_tgt != old_tgt) {
03337 changed = TRUE;
03338 Cflow_Change_Succ(bp, 0, old_tgt, new_tgt);
03339 }
03340
03341 if (freqs_computed) {
03342 edge_freq = BBINFO_succ_prob(bp, 1) * BB_freq(bp);
03343 }
03344 old_tgt = BBINFO_succ_bb(bp, 1);
03345 new_tgt = Collapse_Same_Logif(bp, old_tgt, 1, edge_freq);
03346 if (new_tgt != old_tgt) {
03347 changed = TRUE;
03348 Cflow_Change_Succ(bp, 1, old_tgt, new_tgt);
03349 }
03350 #endif // TARG_IA64
03351 #ifdef KEY
03352
03353
03354
03355 if( BBINFO_succ_bb(bp, 0) == BBINFO_succ_bb(bp, 1) ){
03356 if( !Convert_Indirect_Goto_To_Direct( bp ) ){
03357 FmtAssert( FALSE, ("Optimize_Branches: fail to merge") );
03358 }
03359 }
03360 #endif
03361 }
03362 break;
03363 case BBKIND_GOTO:
03364 if (BBINFO_nsuccs(bp) == 0) break;
03365
03366 old_tgt = BBINFO_succ_bb(bp, 0);
03367 new_tgt = Collapse_Empty_Goto(bp, old_tgt, BB_freq(bp));
03368 if (new_tgt != old_tgt) {
03369 #ifdef TARG_IA64
03370 chan_succ = Cflow_Change_Succ(bp, 0, old_tgt, new_tgt);
03371 if (chan_succ) changed = TRUE;
03372 #else
03373 changed = TRUE;
03374 Cflow_Change_Succ(bp, 0, old_tgt, new_tgt);
03375 #endif
03376 }
03377 if (new_tgt != BB_next(bp)) {
03378 if ( Convert_Goto_To_If(bp, used_branch_around)
03379 || Convert_Goto_To_Return(bp)
03380 ) changed = TRUE;
03381
03382 } else if ( pass == 1
03383 && BB_branch_op(bp)
03384 && BBINFO_cold(bp) == BBINFO_cold(new_tgt))
03385 {
03386
03387
03388
03389
03390
03391
03392
03393 ++pass;
03394
03395 if (CFLOW_Trace_Branch) {
03396 #pragma mips_frequency_hint NEVER
03397 fprintf(TFile, "removing branch to next BB from BB:%d\n", BB_id(bp));
03398 }
03399 }
03400 break;
03401 case BBKIND_VARGOTO:
03402 case BBKIND_INDGOTO:
03403 if (Convert_Indirect_Goto_To_Direct(bp)) {
03404 old_tgt = BBINFO_succ_bb(bp, 0);
03405 new_tgt = Collapse_Empty_Goto(bp, old_tgt, BB_freq(bp));
03406
03407
03408 if (new_tgt != old_tgt) {
03409 #ifdef TARG_IA64
03410 chan_succ = Cflow_Change_Succ(bp, 0, old_tgt, new_tgt);
03411 #else
03412 Cflow_Change_Succ(bp, 0, old_tgt, new_tgt);
03413 #endif
03414 }
03415
03416 changed = TRUE;
03417
03418 break;
03419 }
03420
03421 if (BBINFO_kind(bp) == BBKIND_VARGOTO) {
03422 st = BBINFO_vargoto_listvar(bp);
03423 if (st == NULL) break;
03424 for (i = 0; i < BBINFO_nsuccs(bp); i++) {
03425 if (freqs_computed) {
03426 edge_freq = BBINFO_succ_prob(bp, i) * BB_freq(bp);
03427 }
03428 old_tgt = BBINFO_succ_bb(bp, i);
03429 new_tgt = Collapse_Empty_Goto (bp, old_tgt, edge_freq);
03430
03431 if (new_tgt == old_tgt) continue;
03432
03433 if (!Change_Switchtable_Entries(st, old_tgt, new_tgt)) continue;
03434 #ifdef TARG_IA64
03435 chan_succ = Cflow_Change_Succ(bp, i, old_tgt, new_tgt);
03436 if (chan_succ) changed = TRUE;
03437 #else
03438 changed = TRUE;
03439 Cflow_Change_Succ(bp, i, old_tgt, new_tgt);
03440 #endif
03441 }
03442 }
03443 break;
03444 case BBKIND_CALL:
03445 if ( (current_flags & CFLOW_FREQ_ORDER)
03446 && freqs_computed
03447 && BBINFO_nsuccs(bp)
03448 ) {
03449 old_tgt = BBINFO_succ_bb(bp, 0);
03450 new_tgt = Collapse_Empty_Goto(bp, old_tgt, BB_freq(bp));
03451
03452 if (new_tgt != old_tgt) {
03453 #ifdef TARG_IA64
03454 chan_succ = Cflow_Change_Succ(bp, 0, old_tgt, new_tgt);
03455 if (chan_succ) changed = TRUE;
03456 #else
03457 changed = TRUE;
03458 Cflow_Change_Succ(bp, 0, old_tgt, new_tgt);
03459 #endif
03460 }
03461 }
03462 break;
03463 }
03464 }
03465 } while (changed);
03466
03467 return pass > 1;
03468 }
03469
03470
03471
03472
03473
03474
03475
03476
03477
03478
03479
03480
03481
03482
03483
03484
03485
03486
03487
03488
03489
03490
03491
03492
03493 static BOOL
03494 Delete_Unreachable_Blocks(void)
03495 {
03496 struct estack_elm {
03497 BOOL unreachable;
03498 struct estack_elm *next;
03499 struct estack_elm *prev;
03500 };
03501
03502 BB *bp;
03503 BB *next;
03504 struct estack_elm estack;
03505
03506
03507 struct estack_elm *etos = &estack;
03508
03509
03510 BOOL deleted = FALSE;
03511
03512
03513
03514 BB_Mark_Unreachable_Blocks();
03515
03516 estack.next = NULL;
03517 estack.prev = NULL;
03518
03519
03520
03521 for (bp = REGION_First_BB; bp; bp = next) {
03522 BOOL has_eh_lab = FALSE;
03523 BOOL unreachable_bb = BB_unreachable(bp);
03524 next = BB_next(bp);
03525
03526
03527
03528
03529
03530
03531
03532
03533
03534
03535
03536
03537
03538
03539
03540
03541
03542
03543
03544
03545
03546
03547 if (have_eh_regions && BB_has_label(bp)) {
03548 ANNOTATION *ant;
03549 ANNOTATION *next_ant;
03550
03551 ant = ANNOT_First(BB_annotations(bp), ANNOT_LABEL);
03552
03553 #ifdef KEY
03554 Is_True(ant != NULL, ("Delete_Unreachable_Blocks: BB has no label"));
03555 #endif
03556
03557 do {
03558 LABEL_IDX lab = ANNOT_label(ant);
03559
03560 next_ant = ANNOT_Next(ant, ANNOT_LABEL);
03561
03562 switch (LABEL_kind(Label_Table[lab])) {
03563 case LKIND_BEGIN_EH_RANGE:
03564 {
03565 struct estack_elm *enext = etos->next;
03566 if (enext == NULL) {
03567 enext = (struct estack_elm *)alloca(sizeof(struct estack_elm));
03568 enext->next = NULL;
03569 enext->prev = etos;
03570 etos->next = enext;
03571 }
03572 etos = enext;
03573 etos->unreachable = unreachable_bb;
03574
03575 if (unreachable_bb) {
03576 if (CFLOW_Trace_Unreach) {
03577 #pragma mips_frequency_hint NEVER
03578 fprintf(TFile, "Removing begin_eh_range label %s from BB:%d\n",
03579 LABEL_name(lab), BB_id(bp));
03580 }
03581 BB_annotations(bp) = ANNOT_Unlink(BB_annotations(bp), ant);
03582 if (ANNOT_First(BB_annotations(bp), ANNOT_LABEL) == NULL)
03583 Reset_BB_has_label(bp);
03584 Set_Label_BB(lab, NULL);
03585 eh_label_removed = TRUE;
03586 } else {
03587 has_eh_lab = TRUE;
03588 }
03589 }
03590 break;
03591 case LKIND_END_EH_RANGE:
03592 {
03593 BOOL unreachable_range = etos->unreachable;
03594 etos = etos->prev;
03595 FmtAssert(etos, ("estack underflow with label %s of BB:%d",
03596 LABEL_name(lab), BB_id(bp)));
03597 if (unreachable_range) {
03598 if (CFLOW_Trace_Unreach) {
03599 #pragma mips_frequency_hint NEVER
03600 fprintf(TFile, "Removing end_eh_range label %s from BB:%d\n",
03601 LABEL_name(lab), BB_id(bp));
03602 }
03603 BB_annotations(bp) = ANNOT_Unlink(BB_annotations(bp), ant);
03604 if (ANNOT_First(BB_annotations(bp), ANNOT_LABEL) == NULL)
03605 Reset_BB_has_label(bp);
03606 Set_Label_BB(lab, NULL);
03607 eh_label_removed = TRUE;
03608 } else {
03609 has_eh_lab = TRUE;
03610 }
03611 }
03612 break;
03613 }
03614 } while (ant = next_ant);
03615 }
03616
03617
03618
03619 if (!unreachable_bb) continue;
03620 #ifdef TARG_IA64
03621 if (IPFEC_Enable_Speculation) {
03622 if (BB_Hold_Disjoint_Speculative_Code(bp))
03623 continue;
03624
03625 Delete_Recovery_Info_For_BB(bp);
03626 }
03627 #endif
03628
03629
03630
03631 if ( has_eh_lab
03632 || BB_Has_Addr_Taken_Label(bp)
03633 || BB_Has_Outer_Block_Label(bp))
03634 {
03635 Delete_BB_Contents(bp);
03636 } else {
03637 Delete_BB(bp, CFLOW_Trace_Unreach);
03638 }
03639
03640 deleted = TRUE;
03641 }
03642
03643 FmtAssert(etos == &estack, ("estack not empty"));
03644
03645 return deleted;
03646 }
03647
03648
03649
03650
03651
03652
03653
03654
03655
03656
03657
03658
03659
03660
03661
03662
03663
03664
03665
03666 static BOOL
03667 Merge_With_Pred ( BB *b, BB *pred )
03668 {
03669 BB *b_targ;
03670 RID *b_rid;
03671 UINT32 i;
03672 BB *merged_pred;
03673
03674 #ifdef TARG_IA64
03675 if (IPFEC_Enable_Region_Formation && RGN_Formed ) {
03676 if(Regional_Cfg_Node(pred)->Is_Entry())
03677 return FALSE;
03678 if(Home_Region(b)->Is_No_Further_Opt() ||
03679 Home_Region(pred)->Is_No_Further_Opt())
03680 return FALSE;
03681 }
03682 #endif
03683
03684
03685
03686
03687 switch (BBINFO_kind(pred)) {
03688 case BBKIND_GOTO:
03689 case BBKIND_RETURN:
03690 case BBKIND_TAIL_CALL:
03691 case BBKIND_REGION_EXIT:
03692 case BBKIND_LOGIF:
03693 case BBKIND_VARGOTO:
03694 case BBKIND_INDGOTO:
03695 #ifdef TARG_IA64
03696 case BBKIND_CHK:
03697 #endif
03698 #if defined(TARG_SL)
03699 case BBKIND_ZDL_BODY:
03700 case BBKIND_FORK:
03701 #endif
03702 if (CFLOW_Trace_Merge) {
03703 #pragma mips_frequency_hint NEVER
03704 fprintf(TFile, "Merge_With_Pred rejecting merge of BB:%d into BB:%d (unsupported kind: %s)\n",
03705 BB_id(b), BB_id(pred), BBKIND_Name(BBINFO_kind(pred)));
03706 }
03707 return FALSE;
03708
03709 default:
03710 #pragma mips_frequency_hint NEVER
03711 FmtAssert(FALSE, ("Merge_With_Pred: unknown BB kind (%s)",
03712 BBKIND_Name(BBINFO_kind(pred))));
03713
03714
03715 case BBKIND_CALL:
03716 if (BBINFO_succ_bb(pred, 0) != BB_next(pred)) {
03717 if (CFLOW_Trace_Merge) {
03718 #pragma mips_frequency_hint NEVER
03719 fprintf(TFile, "Merge_With_Pred rejecting merge of BB:%d into BB:%d (call succ not next BB)\n",
03720 BB_id(b), BB_id(pred));
03721 }
03722 return FALSE;
03723 }
03724
03725
03726
03727 break;
03728 }
03729
03730
03731
03732 b_targ = BBINFO_succ_bb(b, 0);
03733 if (b_targ != BB_next(b)) {
03734 if (CFLOW_Trace_Merge) {
03735 #pragma mips_frequency_hint NEVER
03736 fprintf(TFile, "Merge_With_Pred rejecting merge of BB:%d into BB:%d (GOTO not a fall through)\n",
03737 BB_id(b), BB_id(pred));
03738 }
03739 return FALSE;
03740 }
03741
03742
03743
03744 if (BB_Has_Exc_Label(b)) {
03745 if (CFLOW_Trace_Merge) {
03746 #pragma mips_frequency_hint NEVER
03747 fprintf(TFile, "Merge_With_Pred rejecting merge of BB:%d into BB:%d (sucessor has exception label)\n",
03748 BB_id(b), BB_id(pred));
03749 }
03750 return FALSE;
03751 }
03752
03753
03754
03755 if (BB_Has_Addr_Taken_Label(b)) {
03756 if (CFLOW_Trace_Merge) {
03757 #pragma mips_frequency_hint NEVER
03758 fprintf(TFile, "Merge_With_Pred rejecting merge of BB:%d into BB:%d (sucessor has address-taken label)\n",
03759 BB_id(b), BB_id(pred));
03760 }
03761 return FALSE;
03762 }
03763
03764
03765
03766 if (BB_Has_Outer_Block_Label(b)) {
03767 if (CFLOW_Trace_Merge) {
03768 #pragma mips_frequency_hint NEVER
03769 fprintf(TFile, "Merge_With_Pred rejecting merge of BB:%d into BB:%d (sucessor is target of outer block goto)\n",
03770 BB_id(b), BB_id(pred));
03771 }
03772 return FALSE;
03773 }
03774
03775
03776
03777 if (BB_has_pragma(b) && Pragma_Affects_Cflow(b)) {
03778 if (CFLOW_Trace_Merge) {
03779 #pragma mips_frequency_hint NEVER
03780 fprintf(TFile, "Merge_With_Pred rejecting merge of BB:%d into BB:%d (pragma found)\n",
03781 BB_id(b), BB_id(pred));
03782 }
03783 return FALSE;
03784 }
03785
03786
03787
03788 b_rid = BB_rid(b);
03789 if (b_rid != BB_rid(pred)) {
03790 if (CFLOW_Trace_Merge) {
03791 #pragma mips_frequency_hint NEVER
03792 fprintf(TFile, "Merge_With_Pred rejecting merge of BB:%d into BB:%d (different regions)\n",
03793 BB_id(b), BB_id(pred));
03794 }
03795 return FALSE;
03796 }
03797
03798
03799
03800
03801 merged_pred = BB_Unique_Predecessor(pred);
03802 if ( merged_pred
03803 && b_targ != NULL
03804 && BB_rid(merged_pred) != b_rid
03805 && BB_rid(b_targ) != b_rid
03806 ) {
03807 if (CFLOW_Trace_Merge) {
03808 #pragma mips_frequency_hint NEVER
03809 fprintf(TFile, "Merge_With_Pred rejecting merge of BB:%d into BB:%d (would be a region entry and exit block)\n",
03810 BB_id(b), BB_id(pred));
03811 }
03812 return FALSE;
03813 }
03814
03815
03816
03817
03818 if ( BB_mod_pred_rotating_registers(b)
03819 || BB_mod_pred_rotating_registers(pred)
03820 || BB_mod_rotating_registers(b)
03821 || BB_mod_rotating_registers(pred))
03822 {
03823 if (CFLOW_Trace_Merge) {
03824 #pragma mips_frequency_hint NEVER
03825 fprintf(TFile, "Merge_With_Pred rejecting merge of BB:%d into BB:%d (one of the blocks modifies the rotating registers)\n",
03826 BB_id(b), BB_id(pred));
03827 }
03828 return FALSE;
03829 }
03830
03831
03832
03833
03834 if (!HB_CFLOW_Can_Merge_BBs(b,pred)) {
03835 return FALSE;
03836 }
03837
03838
03839
03840 BB_Copy_Annotations(b_targ, b, ANNOT_NOTE);
03841
03842
03843
03844 BB_Copy_Annotations(pred, b, ANNOT_PRAGMA);
03845
03846
03847
03848 #ifdef TARG_IA64
03849 if (IPFEC_Enable_Region_Formation && RGN_Formed ) {
03850 RGN_Unlink_Pred_Succ(pred,b);
03851 } else {
03852 Unlink_Pred_Succ(pred, b);
03853 }
03854 #else
03855 Unlink_Pred_Succ(pred, b);
03856 #endif
03857 for (i = 0; i < BBINFO_nsuccs(pred); ++i) {
03858 if (BBINFO_succ_bb(pred, i) == b) {
03859
03860 #if defined(TARG_SL)
03861 if(BB_zdl_prolog(b))
03862 Set_BB_zdl_prolog(pred);
03863 #endif
03864
03865 #ifdef TARG_IA64
03866 if (IPFEC_Enable_Region_Formation && RGN_Formed) {
03867 RGN_Link_Pred_Succ_With_Prob(pred, b_targ, BBINFO_succ_prob(pred, i));
03868 } else {
03869 Link_Pred_Succ_with_Prob(pred, b_targ, BBINFO_succ_prob(pred, i));
03870 }
03871 #else
03872 Link_Pred_Succ_with_Prob(pred, b_targ, BBINFO_succ_prob(pred, i));
03873 #endif
03874
03875
03876 Set_BBINFO_succ_bb(pred, i, b_targ);
03877 }
03878 }
03879
03880 if (CFLOW_Trace_Merge) {
03881 #pragma mips_frequency_hint NEVER
03882 fprintf(TFile, "Merge_With_Pred merged BB:%d into BB:%d\n", BB_id(b), BB_id(pred));
03883 }
03884
03885
03886
03887 HB_CFLOW_Replace_Block(b,pred);
03888 Delete_BB(b, CFLOW_Trace_Merge);
03889
03890 return TRUE;
03891 }
03892
03893
03894
03895
03896
03897
03898
03899
03900
03901
03902
03903
03904 static BOOL
03905 Can_Append_Succ(
03906 BB *b,
03907 BB *suc,
03908 BB *merged_pred,
03909 BOOL delete_suc,
03910 BOOL trace)
03911 {
03912 BB *merged_succ;
03913 RID *b_rid = BB_rid(b);
03914 const char *oper_name = delete_suc ? "merge" : "append";
03915 INT nsuccs = BBINFO_nsuccs(suc);
03916
03917
03918
03919 switch (BBINFO_kind(suc)) {
03920 case BBKIND_CALL:
03921
03922
03923
03924
03925
03926
03927
03928 if (nsuccs && suc != BB_next(b)) {
03929 if (trace) {
03930 #pragma mips_frequency_hint NEVER
03931 fprintf(TFile, "rejecting %s of BB:%d into BB:%d"
03932 " (BBKIND_CALL pred must be fall through)\n",
03933 oper_name, BB_id(suc), BB_id(b));
03934 }
03935 return FALSE;
03936 }
03937
03938 case BBKIND_GOTO:
03939 case BBKIND_LOGIF:
03940 case BBKIND_RETURN:
03941 case BBKIND_TAIL_CALL:
03942 case BBKIND_REGION_EXIT:
03943 case BBKIND_VARGOTO:
03944 case BBKIND_INDGOTO:
03945
03946
03947
03948 break;
03949 #if defined(TARG_SL)
03950 case BBKIND_ZDL_BODY:
03951 {
03952 if (trace) {
03953 #pragma mips_frequency_hint NEVER
03954 fprintf(TFile, "rejecting %s of BB:%d into BB:%d"
03955 " (BBKIND_ZDL must not be appended)\n",
03956 oper_name, BB_id(suc), BB_id(b));
03957 }
03958 return FALSE;
03959 }
03960 case BBKIND_FORK:
03961 {
03962 if (trace) {
03963 #pragma mips_frequency_hint NEVER
03964 fprintf(TFile, "rejecting %s of BB:%d into BB:%d"
03965 " (BBKIND_FORL can not be appended currently)\n",
03966 oper_name, BB_id(suc), BB_id(b));
03967 }
03968 return FALSE;
03969 }
03970 #endif
03971 default:
03972 if (trace) {
03973 #pragma mips_frequency_hint NEVER
03974 fprintf(TFile, "rejecting %s of BB:%d into BB:%d (unsupported kind: %s)",
03975 oper_name, BB_id(suc), BB_id(b), BBKIND_Name(BBINFO_kind(suc)));
03976 }
03977 return FALSE;
03978 }
03979
03980 #if defined(TARG_SL)
03981 if(BBINFO_kind(b) == BBKIND_ZDL_BODY) {
03982 if (trace) {
03983 #pragma mips_frequency_hint NEVER
03984 fprintf(TFile, "rejecting %s of BB:%d into BB:%d"
03985 " (BBKIND_ZDL must not append other bb)\n",
03986 oper_name, BB_id(suc), BB_id(b));
03987 }
03988 return FALSE;
03989 }
03990
03991 if(BBINFO_kind(b) == BBKIND_FORK) {
03992 if(trace) {
03993 #pragma mips_frequency_hint NEVER
03994 fprintf(TFile, "rejecting %s of BB:%d into BB:%d"
03995 " (BBKIND_FORL can not append other bb currently)\n",
03996 oper_name, BB_id(suc), BB_id(b));
03997 }
03998 return FALSE;
03999 }
04000 #endif
04001
04002
04003
04004 if (BB_asm(b)) {
04005 if (trace) {
04006 #pragma mips_frequency_hint NEVER
04007 fprintf(TFile, "rejecting %s of BB:%d into BB:%d"
04008 " (predecessor has an asm)\n",
04009 oper_name, BB_id(suc), BB_id(b));
04010 }
04011 return FALSE;
04012 }
04013
04014 #ifdef TARG_X8664
04015
04016 if( BB_savexmms_op(b) != NULL ){
04017 return FALSE;
04018 }
04019
04020 if (BB_last_OP_computes_got(b) ||
04021 BB_first_OP_computes_got(suc)) {
04022 return FALSE;
04023 }
04024 #endif
04025
04026
04027
04028 if (BB_entry(suc)) {
04029 if (trace) {
04030 #pragma mips_frequency_hint NEVER
04031 fprintf(TFile, "rejecting %s of BB:%d into BB:%d"
04032 " (successor is an entry point)\n",
04033 oper_name, BB_id(suc), BB_id(b));
04034 }
04035 return FALSE;
04036 }
04037
04038
04039
04040 if (BB_Has_Exc_Label(suc)) {
04041 if (trace) {
04042 #pragma mips_frequency_hint NEVER
04043 fprintf(TFile, "rejecting %s of BB:%d into BB:%d"
04044 " (successor has exception label)\n",
04045 oper_name, BB_id(suc), BB_id(b));
04046 }
04047 return FALSE;
04048 }
04049
04050
04051
04052 if (BB_Has_Addr_Taken_Label(suc)) {
04053 if (trace) {
04054 #pragma mips_frequency_hint NEVER
04055 fprintf(TFile, "rejecting %s of BB:%d into BB:%d"
04056 " (successor has address-taken label)\n",
04057 oper_name, BB_id(suc), BB_id(b));
04058 }
04059 return FALSE;
04060 }
04061
04062
04063
04064 if (BB_Has_Outer_Block_Label(suc)) {
04065 if (trace) {
04066 #pragma mips_frequency_hint NEVER
04067 fprintf(TFile, "rejecting %s of BB:%d into BB:%d"
04068 " (successor is target of outer block goto)\n",
04069 oper_name, BB_id(suc), BB_id(b));
04070 }
04071 return FALSE;
04072 }
04073
04074
04075
04076 if ( (BB_has_pragma(b) && Pragma_Affects_Cflow(b))
04077 || (BB_has_pragma(suc) && Pragma_Affects_Cflow(suc))
04078 ) {
04079 if (trace) {
04080 #pragma mips_frequency_hint NEVER
04081 fprintf(TFile, "rejecting %s of BB:%d into BB:%d (pragmas found)\n",
04082 oper_name, BB_id(suc), BB_id(b));
04083 }
04084 return FALSE;
04085 }
04086
04087
04088
04089 if (b_rid != BB_rid(suc)) {
04090 if (trace) {
04091 #pragma mips_frequency_hint NEVER
04092 fprintf(TFile, "rejecting %s of BB:%d into BB:%d (different regions)\n",
04093 oper_name, BB_id(suc), BB_id(b));
04094 }
04095 return FALSE;
04096 }
04097
04098
04099
04100
04101 if (delete_suc && suc == REGION_First_BB) {
04102 BB *suc_next = BB_next(suc);
04103 if (suc_next && BB_rid(suc) != BB_rid(suc_next)) {
04104 if (trace) {
04105 #pragma mips_frequency_hint NEVER
04106 fprintf(TFile, "rejecting %s of BB:%d into BB:%d (would change RID for REGION_First_BB)\n",
04107 oper_name, BB_id(suc), BB_id(b));
04108 }
04109 return FALSE;
04110 }
04111 }
04112
04113
04114
04115 if (b_rid && RID_level(b_rid) >= RL_CGSCHED) {
04116 if (trace) {
04117 #pragma mips_frequency_hint NEVER
04118 fprintf(TFile, "rejecting %s of BB:%d into BB:%d (scheduled region)\n",
04119 oper_name, BB_id(suc), BB_id(b));
04120 }
04121 return FALSE;
04122 }
04123
04124
04125
04126 if (b_rid && RID_has_reg_alloc(b_rid)) {
04127 if (trace) {
04128 #pragma mips_frequency_hint NEVER
04129 fprintf(TFile, "rejecting %s of BB:%d into BB:%d (reg alloced region)\n",
04130 oper_name, BB_id(suc), BB_id(b));
04131 }
04132 return FALSE;
04133 }
04134
04135
04136
04137 if (BB_length(b) + BB_length(suc) >= Split_BB_Length) {
04138 if (trace) {
04139 #pragma mips_frequency_hint NEVER
04140 fprintf(TFile, "rejecting %s of BB:%d into BB:%d"
04141 " (combined size too large)\n",
04142 oper_name, BB_id(suc), BB_id(b));
04143 }
04144 return FALSE;
04145 }
04146
04147
04148
04149
04150
04151
04152
04153 if (BB_unrollings(b) || BB_unrollings(suc)) {
04154 if ( !BB_unrollings(b)
04155 || !BB_unrollings(suc)
04156 || BB_loop_head_bb(b) != BB_loop_head_bb(suc)
04157 ) {
04158 if (trace) {
04159 #pragma mips_frequency_hint NEVER
04160 fprintf(TFile, "rejecting %s of BB:%d into BB:%d "
04161 "(not in same unrolled loop)\n",
04162 oper_name, BB_id(suc), BB_id(b));
04163 }
04164 return FALSE;
04165 }
04166 }
04167
04168
04169
04170
04171 merged_succ = (nsuccs == 1) ? BBINFO_succ_bb(suc, 0) : NULL;
04172 if ( merged_pred != NULL
04173 && merged_succ != NULL
04174 && BB_rid(merged_pred) != b_rid
04175 && BB_rid(merged_succ) != b_rid)
04176 {
04177 if (trace) {
04178 #pragma mips_frequency_hint NEVER
04179 fprintf(TFile, "rejecting %s of BB:%d into BB:%d (would be a region entry and exit block)\n",
04180 oper_name, BB_id(suc), BB_id(b));
04181 }
04182 return FALSE;
04183 }
04184
04185
04186
04187
04188 if ( BB_mod_pred_rotating_registers(b)
04189 || BB_mod_pred_rotating_registers(suc)
04190 || BB_mod_rotating_registers(b)
04191 || BB_mod_rotating_registers(suc))
04192 {
04193 if (CFLOW_Trace_Merge) {
04194 #pragma mips_frequency_hint NEVER
04195 fprintf(TFile, "rejecting %s of BB:%d into BB:%d (one of the blocks modifies the rotating registers)\n",
04196 oper_name, BB_id(suc), BB_id(b));
04197 }
04198 return FALSE;
04199 }
04200
04201
04202
04203
04204 if (!HB_CFLOW_Can_Merge_BBs(b,suc)) {
04205 return FALSE;
04206 }
04207
04208 return TRUE;
04209 }
04210
04211
04212 #if 0
04213
04214
04215
04216
04217
04218
04219
04220
04221
04222
04223
04224
04225
04226
04227
04228
04229
04230
04231 static ST *
04232 Copy_Jump_Table(ST *old_listvar)
04233 {
04234 TY_IDX table;
04235 ST *listvar;
04236 INITO_IDX old_ino;
04237 INITV_IDX old_inv;
04238 INITO_IDX ino;
04239 INITV_IDX inv;
04240 INITV_IDX prev_inv;
04241 INT num_entries;
04242
04243
04244
04245 old_ino = Find_INITO_For_Symbol(old_listvar);
04246
04247
04248
04249
04250 num_entries = 0;
04251 FOREACH_INITV(INITO_val(old_ino), old_inv) ++num_entries;
04252
04253
04254
04255 table = Make_Array_Type(Pointer_type, 1, num_entries);
04256 listvar = Gen_Read_Only_Symbol(table, "jump_table");
04257 Set_ST_is_initialized(listvar);
04258
04259
04260
04261 ino = New_INITO(listvar);
04262 prev_inv = INITV_IDX_ZERO;
04263 FOREACH_INITV(INITO_val(old_ino), old_inv) {
04264 LABEL_IDX lab = INITV_lab(old_inv);
04265 inv = New_INITV();
04266 INITV_Init_Label (inv, lab);
04267 prev_inv = Append_INITV (inv, ino, prev_inv);
04268 }
04269
04270 return listvar;
04271 }
04272 #endif
04273
04274
04275
04276
04277
04278
04279
04280
04281
04282
04283
04284 static void
04285 Append_Succ(
04286 BB *b,
04287 BB *suc,
04288 BOOL in_cgprep,
04289 BOOL delete_suc)
04290 {
04291 INT num;
04292 INT i;
04293 RID *b_rid = BB_rid(b);
04294 INT nsuccs = BBINFO_nsuccs(suc);
04295 #ifdef KEY
04296 OP *first_new_op = NULL;
04297 #endif
04298
04299
04300
04301 BB_Remove_Branch(b);
04302
04303
04304
04305 if (delete_suc) {
04306 BB_Append_All(b, suc);
04307 HB_CFLOW_Replace_Block(suc,b);
04308 } else {
04309 OP *op;
04310 FOR_ALL_BB_OPs_FWD(suc, op) {
04311 OP *new_op = Dup_OP(op);
04312 if (OP_memory(op)) Copy_WN_For_Memory_OP(new_op, op);
04313 BB_Append_Op(b, new_op);
04314 #ifdef KEY
04315 if (first_new_op == NULL)
04316 first_new_op = new_op;
04317 #endif
04318
04319
04320 if (!CG_localize_tns) {
04321 for (INT i = 0; i < OP_results(new_op); ++i) {
04322 TN *tn = OP_result(new_op, i);
04323 if (TN_is_constant(tn)) continue;
04324 if (TN_is_const_reg(tn)) continue;
04325 if (!TN_is_global_reg(tn))
04326 GTN_UNIVERSE_Add_TN(tn);
04327 }
04328 }
04329 }
04330 }
04331 if (!CG_localize_tns) {
04332 GRA_LIVE_Merge_Blocks(b, b, suc);
04333 Rename_TNs_For_BB(b, NULL);
04334 }
04335 #ifndef TARG_IA64
04336 else {
04337
04338
04339
04340 Rename_TNs_For_BB(b, NULL, first_new_op);
04341 }
04342 #endif
04343
04344
04345
04346 Set_BBINFO_kind(b, BBINFO_kind(suc));
04347 Set_BBINFO_nsuccs(b, nsuccs);
04348 switch (BBINFO_kind(suc)) {
04349 case BBKIND_TAIL_CALL:
04350 case BBKIND_CALL:
04351 case BBKIND_RETURN:
04352 if (BB_call(suc)) {
04353 FmtAssert(BB_Copy_Annotations(b, suc, ANNOT_CALLINFO),
04354 ("no CALLINFO annotations for BB:%d", BB_id(suc)));
04355 }
04356 if (BB_exit(suc)) {
04357 FmtAssert(BB_Copy_Annotations(b, suc, ANNOT_EXITINFO),
04358 ("no EXITINFO annotations for BB:%d", BB_id(suc)));
04359
04360 if (!delete_suc) {
04361 OP *b_op;
04362 OP *suc_op;
04363 ANNOTATION *ant = ANNOT_Get(BB_annotations(b), ANNOT_EXITINFO);
04364 EXITINFO *exit_info = ANNOT_exitinfo(ant);
04365 EXITINFO *new_info = TYPE_PU_ALLOC(EXITINFO);
04366 OP *sp_adj = EXITINFO_sp_adj(exit_info);
04367 *new_info = *exit_info;
04368 if (sp_adj) {
04369 for (suc_op = BB_last_op(suc), b_op = BB_last_op(b);
04370 suc_op != sp_adj;
04371 suc_op = OP_prev(suc_op), b_op = OP_prev(b_op))
04372 ;
04373 EXITINFO_sp_adj(new_info) = b_op;
04374 }
04375 ant->info = new_info;
04376 }
04377
04378
04379
04380
04381
04382 Exit_BB_Head = BB_LIST_Push(b, Exit_BB_Head, &MEM_pu_pool);
04383 }
04384 break;
04385 case BBKIND_GOTO:
04386 Is_True(delete_suc, ("keeping succ not handled"));
04387 if (BB_asm(suc)) {
04388 FmtAssert(BB_Copy_Annotations(b, suc, ANNOT_ASMINFO),
04389 ("no ASMINFO annotations for BB:%d", BB_id(suc)));
04390 }
04391 break;
04392 case BBKIND_REGION_EXIT:
04393
04394 Is_True(delete_suc, ("keeping succ not handled"));
04395 break;
04396 case BBKIND_LOGIF:
04397 Set_BBINFO_condval1(b, BBINFO_condval1(suc));
04398 Set_BBINFO_condval2(b, BBINFO_condval2(suc));
04399 Set_BBINFO_compare_op(b, BBINFO_compare_op(suc));
04400 if (!delete_suc) {
04401 OP *cmp_op = BBINFO_compare_op(suc);
04402 if (OP_bb(cmp_op) == suc) {
04403 OP *b_op, *suc_op;
04404 for (suc_op = BB_last_op(suc), b_op = BB_last_op(b);
04405 suc_op != cmp_op;
04406 suc_op = OP_prev(suc_op), b_op = OP_prev(b_op))
04407 ;
04408 Set_BBINFO_compare_op(b, b_op);
04409 }
04410 }
04411 Set_BBINFO_variant(b, BBINFO_variant(suc));
04412 Set_BBINFO_b_likely(b, BBINFO_b_likely(suc));
04413 break;
04414 case BBKIND_VARGOTO:
04415 {
04416 INT incr;
04417 ST *listvar;
04418 INT *refcount;
04419
04420 incr = (nsuccs - BBINFO_NSUCCS) * sizeof(struct succedge);
04421 if (incr > 0) {
04422 INT bbinfo_size = sizeof(BBINFO) + incr;
04423 BBINFO *new_bbinfo = (BBINFO *) MEM_POOL_Alloc(&MEM_local_nz_pool, bbinfo_size);
04424 *new_bbinfo = *BB_BBINFO(b);
04425 BB_MAP_Set(bb_info_map, b, new_bbinfo);
04426 }
04427
04428 refcount = BBINFO_vargoto_refcount(suc);
04429 listvar = BBINFO_vargoto_listvar(suc);
04430 if (listvar) {
04431 FmtAssert(BB_Copy_Annotations(b, suc, ANNOT_SWITCH),
04432 ("no switch annotation for BB:%d", BB_id(suc)));
04433
04434
04435
04436
04437
04438
04439
04440 ++(*refcount);
04441 }
04442 Set_BBINFO_vargoto_listvar(b, listvar);
04443 Set_BBINFO_vargoto_refcount(b, refcount);
04444 }
04445 break;
04446 case BBKIND_INDGOTO:
04447 {
04448 INT incr = (nsuccs - BBINFO_NSUCCS) * sizeof(struct succedge);
04449 if (incr > 0) {
04450 INT bbinfo_size = sizeof(BBINFO) + incr;
04451 BBINFO *new_bbinfo = (BBINFO *) MEM_POOL_Alloc(&MEM_local_nz_pool, bbinfo_size);
04452 *new_bbinfo = *BB_BBINFO(b);
04453 BB_MAP_Set(bb_info_map, b, new_bbinfo);
04454 }
04455 }
04456 break;
04457 default:
04458 #pragma mips_frequency_hint NEVER
04459 FmtAssert(FALSE, ("Append_Succ"));
04460
04461 }
04462
04463
04464 if (!delete_suc) {
04465 BBLIST *suc_lst = BBlist_Find_BB(BB_succs(b), suc);
04466 Is_True(suc_lst, ("Append_Succ: suc not successor of bb"));
04467 float freq_edge = BBLIST_prob(suc_lst) * BB_freq(b);
04468 BB_freq(suc) -= freq_edge;
04469 }
04470
04471 #ifdef TARG_IA64
04472 if (IPFEC_Enable_Region_Formation && RGN_Formed) {
04473 RGN_Unlink_Pred_Succ(b,suc);
04474 } else {
04475 Unlink_Pred_Succ(b, suc);
04476 }
04477 #else
04478 Unlink_Pred_Succ(b, suc);
04479 #endif
04480 for (i = 0; i < nsuccs; ++i) {
04481 BB *succ_i = BBINFO_succ_bb(suc, i);
04482 float prob_i = BBINFO_succ_prob(suc, i);
04483
04484 #ifdef TARG_IA64
04485 if (IPFEC_Enable_Region_Formation && RGN_Formed) {
04486 RGN_Link_Pred_Succ_With_Prob(b,succ_i,prob_i);
04487 } else {
04488 Link_Pred_Succ_with_Prob(b, succ_i, prob_i);
04489 }
04490 #else
04491 Link_Pred_Succ_with_Prob(b, succ_i, prob_i);
04492 #endif
04493
04494 Set_BBINFO_succ_bb(b, i, succ_i);
04495 Set_BBINFO_succ_prob(b, i, prob_i);
04496 Set_BBINFO_succ_offset(b, i, BBINFO_succ_offset(suc, i));
04497 }
04498
04499 BB_branch_wn(b) = BB_branch_wn(suc);
04500
04501 BB_Copy_Annotations(b, suc, ANNOT_NOTE);
04502 BB_Copy_Annotations(b, suc, ANNOT_PRAGMA);
04503
04504 if ((num = BB_REGION_Exit(suc, b_rid)) != NO_REGION_EXIT) {
04505
04506
04507
04508 CGRIN_exit_i(RID_cginfo(b_rid), num) = b;
04509 }
04510 if (BB_REGION_Entry(suc, b_rid)) {
04511
04512
04513
04514 CGRIN_entry(RID_cginfo(b_rid)) = b;
04515 }
04516 }
04517
04518
04519
04520
04521
04522
04523
04524
04525
04526
04527 static BOOL
04528 Merge_With_Succ(BB *b, BB *suc, BB *merged_pred, BOOL in_cgprep)
04529 {
04530
04531 #ifdef TARG_IA64
04532 if (IPFEC_Enable_Region_Formation && RGN_Formed ) {
04533 if(Regional_Cfg_Node(suc)->Is_Entry())
04534 return FALSE;
04535 if(Home_Region(b)->Is_No_Further_Opt() ||
04536 Home_Region(suc)->Is_No_Further_Opt())
04537 return FALSE;
04538 }
04539 #endif
04540
04541
04542 if (!Can_Append_Succ(b, suc, merged_pred, TRUE, CFLOW_Trace_Merge)) {
04543 return FALSE;
04544 }
04545
04546 #if defined(TARG_SL)
04547 if(BB_zdl_prolog(suc))
04548 Set_BB_zdl_prolog(b);
04549 #endif
04550
04551 Append_Succ(b, suc, in_cgprep, TRUE);
04552 if (CFLOW_Trace_Merge) {
04553 #pragma mips_frequency_hint NEVER
04554 fprintf(TFile, "Merge_With_Succ merged BB:%d into BB:%d\n", BB_id(suc), BB_id(b));
04555 }
04556
04557
04558
04559 Delete_BB(suc, CFLOW_Trace_Merge);
04560
04561 return TRUE;
04562 }
04563
04564
04565
04566
04567
04568
04569
04570
04571
04572
04573
04574
04575
04576 static BOOL
04577 Merge_Blocks ( BOOL in_cgprep )
04578 {
04579 BB *next_b;
04580 BB *b;
04581 BB *suc;
04582 BOOL merged = FALSE;
04583
04584
04585
04586 for (b = REGION_First_BB; b; b = next_b) {
04587 next_b = BB_next(b);
04588
04589
04590
04591 for (;;) {
04592 BB *pred;
04593
04594
04595
04596 if ( BBINFO_kind(b) != BBKIND_GOTO
04597 || BBINFO_nsuccs(b) == 0
04598 || BBINFO_succ_offset(b, 0) != 0) break;
04599
04600
04601
04602 suc = BBINFO_succ_bb(b, 0);
04603 if (suc == b) break;
04604
04605 #ifdef TARG_IA64
04606
04607
04608
04609
04610
04611 if (BB_profile_added(b)) break;
04612 #endif
04613 pred = BB_Unique_Predecessor(b);
04614
04615
04616
04617
04618 if (BB_Unique_Predecessor(suc)) {
04619
04620 #ifdef TARG_X8664
04621
04622 if( BB_savexmms_op(b) != NULL ){
04623 break;
04624 }
04625
04626 if (BB_first_OP_computes_got(b) ||
04627 BB_last_OP_computes_got(b)) {
04628 break;
04629 }
04630 #endif
04631
04632
04633
04634
04635 if (Merge_With_Succ(b, suc, pred, in_cgprep)) {
04636 #ifdef TARG_IA64
04637 Reset_BB_scheduled(b);
04638 #endif
04639 merged = TRUE;
04640 next_b = BB_next(b);
04641 continue;
04642 }
04643 }
04644
04645
04646
04647
04648 if (pred && Is_Empty_BB(b)) {
04649 if (Merge_With_Pred(b, pred)) {
04650 #ifdef TARG_IA64
04651 Reset_BB_scheduled(b);
04652 #endif
04653 merged = TRUE;
04654 }
04655 }
04656
04657 break;
04658 }
04659 }
04660
04661 return merged;
04662 }
04663
04664
04665
04666
04667
04668
04669
04670
04671
04672
04673
04674
04675
04676
04677
04678
04679
04680
04681
04682
04683 static void
04684 Print_Fall_Thrus(const char *msg)
04685 {
04686 BB *bb;
04687 INT count, ft_count;
04688
04689
04690
04691 count = ft_count = 0;
04692 for (bb = REGION_First_BB; bb; bb = BB_next(bb)) {
04693 ++count;
04694 if (Falls_Thru(bb, NULL)) ++ft_count;
04695 }
04696
04697
04698
04699 fprintf(TFile, "Fall-through BBs: %d of %d %s\n",
04700 ft_count, count, msg);
04701 }
04702
04703
04704
04705
04706
04707
04708
04709
04710
04711
04712
04713
04714
04715
04716
04717
04718
04719
04720
04721 static BOOL
04722 Reorder_Blocks(void)
04723 {
04724 INT cnt;
04725 BOOL more;
04726 BB *BBi;
04727 BOOL reordered;
04728 BB *succs[2];
04729 INT nsuccs;
04730 INT i;
04731
04732 cnt = MIN(PU_BB_Count, 25);
04733 reordered = FALSE;
04734 do {
04735 more = FALSE;
04736 for (BBi = REGION_First_BB; BBi; BBi = BB_next(BBi)) {
04737
04738
04739
04740 if (Falls_Thru(BBi, NULL)) continue;
04741
04742
04743
04744 nsuccs = BBINFO_nsuccs(BBi);
04745 switch (BBINFO_kind(BBi)) {
04746 case BBKIND_GOTO:
04747 if (nsuccs == 0) continue;
04748 succs[0] = BBINFO_succ_bb(BBi, 0);
04749 break;
04750
04751 case BBKIND_LOGIF:
04752 succs[0] = BBINFO_succ_bb(BBi, 0);
04753 succs[1] = BBINFO_succ_bb(BBi, 1);
04754 break;
04755
04756 default:
04757
04758
04759
04760 continue;
04761 }
04762
04763
04764
04765 i = 0;
04766 do {
04767 BB *BBk;
04768 BB *last_BBj;
04769 BB *BBj = succs[i];
04770
04771
04772
04773 if (BBj == BBi) continue;
04774
04775
04776
04777
04778 BBk = BB_prev(BBj);
04779 if (BBk && Falls_Thru(BBk, BBj)) {
04780
04781
04782
04783
04784
04785 if (!Branches_Around(BBk)) continue;
04786 }
04787
04788
04789
04790
04791
04792
04793 last_BBj = BBj;
04794 for (;;) {
04795 if (BB_rid(last_BBj) != BB_rid(BBi)) goto next_succ;
04796 if (BBINFO_eh_rgn(last_BBj) != BBINFO_eh_rgn(BBi)) goto next_succ;
04797 if (!Falls_Thru(last_BBj, NULL)) break;
04798 last_BBj = BB_next(last_BBj);
04799 }
04800
04801
04802
04803
04804
04805 if (last_BBj == BBi) continue;
04806
04807
04808
04809 more = TRUE;
04810 if (CFLOW_Trace_Reorder) {
04811 #pragma mips_frequency_hint NEVER
04812 BB *bp = BBj;
04813 char sep = ':';
04814 fprintf(TFile, "Moved BB");
04815 do {
04816 fprintf(TFile, "%c%d", sep, BB_id(bp));
04817 bp = BB_next(bp);
04818 sep = ',';
04819 } while (bp != BB_next(last_BBj));
04820 if (BBk) fprintf(TFile, " from after BB:%d", BB_id(BBk));
04821 fprintf(TFile, " to after BB:%d\n", BB_id(BBi));
04822 }
04823
04824
04825
04826 Chain_BBs(BB_prev(BBj), BB_next(last_BBj));
04827
04828
04829
04830 Chain_BBs(last_BBj, BB_next(BBi));
04831 Chain_BBs(BBi, BBj);
04832
04833
04834
04835
04836
04837
04838
04839
04840 BBi = last_BBj;
04841
04842 break;
04843
04844 next_succ:
04845 ;
04846 } while (++i != nsuccs);
04847 }
04848 reordered |= more;
04849 } while (more && --cnt > 0);
04850
04851 if (CFLOW_Trace_Reorder && cnt == 0) {
04852 #pragma mips_frequency_hint NEVER
04853 fprintf(TFile, "Circuit breaker tripped (%d) -- giving up\n",
04854 MIN(PU_BB_Count, 25));
04855 }
04856
04857 return reordered;
04858 }
04859
04860
04861
04862
04863
04864
04865
04866
04867
04868
04869
04870
04871
04872
04873
04874 static double heuristic_tolerance = 0.40;
04875 static double feedback_tolerance = 0.10;
04876 static double cold_threshold;
04877 static BB_SET *never_bbs;
04878
04879
04880
04881
04882 typedef struct edge {
04883 BB *pred;
04884 BB *succ;
04885 struct edge *preds;
04886 double freq;
04887 double weight;
04888 } EDGE;
04889
04890
04891
04892
04893
04894
04895
04896
04897
04898
04899
04900
04901 static INT
04902 Count_Succ_Edges(void)
04903 {
04904 BB *bb;
04905 INT count = 0;
04906
04907 for (bb = REGION_First_BB; bb; bb = BB_next(bb)) {
04908 count += BBINFO_nsuccs(bb);
04909 }
04910
04911 return count;
04912 }
04913
04914
04915
04916
04917
04918
04919
04920
04921
04922
04923
04924
04925 static INT
04926 Compare_Edges(const void *p1, const void *p2)
04927 {
04928
04929
04930
04931
04932 enum {
04933 sort_1_before_2 = -1,
04934 sort_1_after_2 = 1,
04935 sort_1_same_2 = 0
04936 };
04937 EDGE *e1 = (EDGE *)p1;
04938 EDGE *e2 = (EDGE *)p2;
04939 double weight1 = e1->weight;
04940 double weight2 = e2->weight;
04941
04942 if (weight1 > weight2) {
04943 return sort_1_before_2;
04944 } else if (weight1 < weight2) {
04945 return sort_1_after_2;
04946 } else {
04947 return sort_1_same_2;
04948 }
04949 }
04950
04951
04952
04953
04954
04955
04956
04957
04958
04959
04960
04961
04962 inline EDGE *
04963 New_Edge(
04964 EDGE *e,
04965 BB *pred,
04966 BB *succ,
04967 double prob,
04968 double weighted_prob,
04969 EDGE **bb_preds)
04970 {
04971 if ( never_bbs
04972 && (BB_SET_MemberP(never_bbs, pred) != BB_SET_MemberP(never_bbs, succ)))
04973 {
04974
04975
04976
04977
04978
04979 if (CFLOW_Trace_Freq_Order) {
04980 #pragma mips_frequency_hint NEVER
04981 fprintf(TFile, " Suppressing BB:%d -> BB:%d edge -- freq hint pragmas differ\n",
04982 BB_id(pred), BB_id(succ));
04983 }
04984 } else if (pred != succ) {
04985 const double pred_freq = BB_freq(pred);
04986 e->pred = pred;
04987 e->succ = succ;
04988 e->freq = pred_freq * prob;
04989 e->weight = pred_freq * weighted_prob;
04990 e->preds = bb_preds[BB_id(succ)];
04991 bb_preds[BB_id(succ)] = e;
04992 ++e;
04993 }
04994 return e;
04995 }
04996
04997
04998
04999
05000
05001
05002
05003
05004
05005
05006
05007
05008
05009
05010
05011
05012
05013
05014
05015
05016
05017
05018
05019
05020
05021
05022
05023
05024
05025
05026
05027
05028
05029
05030
05031
05032
05033
05034
05035
05036
05037
05038
05039
05040
05041
05042
05043
05044 static INT
05045 Init_Edges(EDGE *edges)
05046 {
05047 BB *bb;
05048 INT n_edges;
05049 EDGE *e;
05050 EDGE **bb_preds;
05051
05052 if (CFLOW_Trace_Freq_Order) {
05053 #pragma mips_frequency_hint NEVER
05054 fprintf(TFile, "\nInit_Edges:\n");
05055 }
05056
05057
05058
05059
05060 bb_preds = (EDGE **)alloca((PU_BB_Count + 2) * sizeof(EDGE *));
05061 BZERO(bb_preds, (PU_BB_Count + 2) * sizeof(EDGE *));
05062
05063
05064
05065
05066
05067 e = edges;
05068 for (bb = REGION_First_BB; bb; bb = BB_next(bb)) {
05069 BB *succ;
05070
05071 switch (BBINFO_kind(bb)) {
05072 case BBKIND_LOGIF:
05073 #if defined(TARG_SL)
05074 case BBKIND_ZDL_BODY:
05075 case BBKIND_FORK:
05076 #endif
05077 {
05078 double prob0 = BBINFO_succ_prob(bb, 0);
05079 double prob1 = BBINFO_succ_prob(bb, 1);
05080 double weight0 = prob0;
05081 double weight1 = prob1;
05082 BB *succ0 = BBINFO_succ_bb(bb, 0);
05083 BB *succ1 = BBINFO_succ_bb(bb, 1);
05084
05085
05086
05087
05088 if (succ0 != bb && succ1 != bb) {
05089 BOOL have_feedback = BB_freq_fb_based(succ0)
05090 || BB_freq_fb_based(succ1)
05091 || BB_freq_fb_based(bb);
05092 double tolerance = have_feedback ? feedback_tolerance
05093 : heuristic_tolerance;
05094 double delta = 0.50 * tolerance;
05095 if (prob0 >= 0.50 - delta && prob0 <= 0.50 + delta) {
05096 if (BB_next(bb) == succ0) {
05097 weight0 = 0.51;
05098 weight1 = 0.49;
05099 } else if (BB_next(bb) == succ1) {
05100 weight0 = 0.49;
05101 weight1 = 0.51;
05102 }
05103 }
05104 }
05105
05106 e = New_Edge(e, bb, succ0, prob0, weight0, bb_preds);
05107 e = New_Edge(e, bb, succ1, prob1, weight1, bb_preds);
05108 }
05109 break;
05110 case BBKIND_GOTO:
05111 case BBKIND_CALL:
05112 if (BBINFO_nsuccs(bb) != 0) {
05113 succ = BBINFO_succ_bb(bb, 0);
05114 e = New_Edge(e, bb, succ, 1.0, 1.0, bb_preds);
05115 }
05116 break;
05117 case BBKIND_VARGOTO:
05118 case BBKIND_INDGOTO:
05119
05120 case BBKIND_RETURN:
05121 case BBKIND_TAIL_CALL:
05122 case BBKIND_REGION_EXIT:
05123
05124 break;
05125 default:
05126 #pragma mips_frequency_hint NEVER
05127 FmtAssert(FALSE, ("unhandled BBKIND"));
05128
05129 }
05130 }
05131 n_edges = e - edges;
05132
05133
05134
05135
05136 for (bb = REGION_First_BB; bb; bb = BB_next(bb)) {
05137 INT n;
05138 double freq;
05139 double avg_prob;
05140 double delta;
05141 double tolerance;
05142 EDGE *biased;
05143 BOOL have_feedback;
05144 EDGE *preds = bb_preds[BB_id(bb)];
05145
05146
05147
05148 if (preds == NULL || preds->preds == NULL) continue;
05149
05150
05151
05152
05153
05154 have_feedback = BB_freq_fb_based(bb) != 0;
05155 freq = 0.0;
05156 for (n = 0, e = preds; e; ++n, e = e->preds) {
05157 have_feedback = have_feedback || BB_freq_fb_based(e->pred);
05158 freq += e->freq;
05159 }
05160
05161
05162
05163
05164
05165
05166 avg_prob = 1.0 / (double)n;
05167 tolerance = have_feedback ? feedback_tolerance
05168 : heuristic_tolerance;
05169 delta = avg_prob * tolerance;
05170
05171
05172
05173
05174 biased = NULL;
05175 for (e = preds; e; e = e->preds) {
05176 if (BB_next(e->pred) == e->succ) biased = e;
05177 if (freq != 0.0) {
05178 double prob = e->freq / freq;
05179 if (prob < avg_prob - delta) goto next_bb;
05180 if (prob > (100.0 - avg_prob) + delta) goto next_bb;
05181 if (prob > avg_prob + delta && prob < (100.0 - avg_prob) - delta) goto next_bb;
05182 }
05183 }
05184 if (biased == NULL) continue;
05185
05186
05187
05188
05189 for (e = preds; e; e = e->preds) {
05190 double prob;
05191 double factor;
05192
05193 if (e == biased) {
05194 factor = 1.0 + 0.01;
05195 } else {
05196 factor = 1.0 - (0.01 / (double)(n - 1));
05197 }
05198 prob = avg_prob * factor;
05199 e->weight = freq * prob;
05200 }
05201
05202 next_bb:
05203 ;
05204 }
05205
05206
05207
05208 qsort(edges, n_edges, sizeof(EDGE), Compare_Edges);
05209
05210 if (CFLOW_Trace_Freq_Order) {
05211 #pragma mips_frequency_hint NEVER
05212 INT i;
05213 for (i = 0; i < n_edges; ++i) {
05214 fprintf(TFile, " BB:%d -> BB:%d, weight=%g, freq=%g\n",
05215 BB_id(edges[i].pred), BB_id(edges[i].succ),
05216 edges[i].weight, edges[i].freq);
05217 }
05218 }
05219
05220 return n_edges;
05221 }
05222
05223
05224
05225
05226
05227 typedef struct bbchain {
05228 double weight;
05229 BB *head;
05230 BB *tail;
05231 struct bbchain *next;
05232 struct bbchain *prev;
05233 BOOL never;
05234 } BBCHAIN;
05235
05236 #ifdef TARG_SL
05237 static BB*
05238 Get_Zdl_Loop_Tail(BB * prolog)
05239 {
05240 FmtAssert(OP_code(BB_last_op(prolog))==TOP_loop, ("Get_Zdl_Loop_Tail::wrong zdl prolog"));
05241 FmtAssert(BB_in_succs(prolog, BB_next(prolog)), ("Get_Zdl_Loop_Tail::wrong zdl header"));
05242 BB *body = BB_next(prolog);
05243 BB *tail = BB_Other_Predecessor(body, prolog);
05244 FmtAssert(tail!=NULL, ("Get_Zdl_Loop_Tail::cannot find zdl tail"));
05245 }
05246 #endif
05247
05248
05249
05250
05251
05252
05253
05254
05255
05256
05257
05258
05259
05260
05261
05262
05263
05264 static BB_MAP
05265 Init_Chains(BBCHAIN *chains)
05266 {
05267 BB *bb;
05268 BB *next_bb;
05269 RID *first_rid = BB_rid(REGION_First_BB);
05270 BB_MAP chain_map = BB_MAP_Create();
05271 BBCHAIN *prev = NULL;
05272
05273
05274
05275 for (bb = REGION_First_BB; bb; bb = next_bb) {
05276 BB *tail = bb;
05277 BB_MAP_Set(chain_map, bb, chains);
05278
05279 #ifdef TARG_SL
05280
05281
05282 if (CG_enable_zero_delay_loop) {
05283 OP *op = BB_last_op(bb);
05284 if (op!=NULL && OP_code(op) == TOP_loop) {
05285 BB *zdl_tail=Get_Zdl_Loop_Tail(bb);
05286 BB *loop_bb = bb;
05287 while (loop_bb!=zdl_tail) {
05288 loop_bb = BB_next(loop_bb);
05289 BB_MAP_Set(chain_map, loop_bb, chains);
05290 }
05291 tail = zdl_tail;
05292 }
05293 }
05294 #endif
05295
05296
05297
05298
05299
05300
05301
05302
05303
05304
05305
05306
05307
05308 Is_True(BB_rid(bb) == first_rid,
05309 ("region nesting botched at BB:%d", BB_id(bb)));
05310 next_bb = BB_next(tail);
05311 while ( next_bb
05312 && ((BB_rid(next_bb) != first_rid)
05313 || (BBINFO_eh_rgn(tail) && BBINFO_eh_rgn(next_bb)))
05314 ) {
05315 do {
05316 tail = next_bb;
05317 BB_MAP_Set(chain_map, tail, chains);
05318 next_bb = BB_next(tail);
05319 } while (next_bb && BB_rid(tail) != first_rid);
05320 }
05321
05322
05323
05324 BB_prev(bb) = NULL;
05325 BB_next(tail) = NULL;
05326
05327 chains->head = bb;
05328 chains->tail = tail;
05329 chains->next = chains + 1;
05330 chains->prev = prev;
05331 chains->weight = 0.0;
05332 chains->never = never_bbs && BB_SET_MemberP(never_bbs, bb);
05333
05334 prev = chains;
05335 ++chains;
05336
05337 if (CFLOW_Trace_Freq_Order && bb != tail) {
05338 #pragma mips_frequency_hint NEVER
05339 BB *bbc;
05340 fprintf(TFile, " multi-BB chain created:");
05341 bbc = bb;
05342 do {
05343 fprintf(TFile, "%c%d", bbc == bb ? ' ' : '-', BB_id(bbc));
05344 } while (bbc = BB_next(bbc));
05345 fprintf(TFile, "\n");
05346 }
05347 }
05348 prev->next = NULL;
05349
05350 return chain_map;
05351 }
05352
05353
05354
05355
05356
05357
05358
05359
05360
05361
05362 inline BBCHAIN *
05363 BB_Chain(BB_MAP chain_map, BB *bb)
05364 {
05365 return (BBCHAIN *)BB_MAP_Get(chain_map, bb);
05366 }
05367
05368
05369
05370
05371
05372
05373
05374
05375
05376
05377 inline BBCHAIN *
05378 Remove_Chain(BBCHAIN *chains, BBCHAIN *chain)
05379 {
05380 BBCHAIN *prev = chain->prev;
05381 BBCHAIN *next = chain->next;
05382 if (prev) prev->next = next;
05383 if (next) next->prev = prev;
05384 if (chains == chain) chains = next;
05385
05386 return chains;
05387 }
05388
05389
05390
05391
05392
05393
05394
05395
05396
05397
05398
05399 static void
05400 Weight_Succ_Chains(BB_MAP chain_map, BBCHAIN *chain)
05401 {
05402 BB *bb;
05403
05404
05405
05406 bb = chain->head;
05407 do {
05408 INT i;
05409 INT nsuccs = BBINFO_nsuccs(bb);
05410 float bb_freq = BB_freq(bb);
05411
05412
05413
05414
05415 for (i = 0; i < nsuccs; ++i) {
05416 BB *succ = BBINFO_succ_bb(bb, i);
05417 BBCHAIN *succ_chain = BB_Chain(chain_map, succ);
05418 succ_chain->weight += bb_freq * BBINFO_succ_prob(bb, i);
05419 }
05420 } while (bb = BB_next(bb));
05421 }
05422
05423
05424
05425
05426
05427
05428
05429
05430
05431
05432 static void
05433 Emit_Cold_Threshold_Note(
05434 NOTE_ACTION action,
05435 NOTE_INFO *,
05436 FILE *file
05437 )
05438 {
05439 switch (action) {
05440 case NOTE_PRINT_TO_ANL_FILE:
05441 break;
05442 case NOTE_PRINT_TO_FILE:
05443 {
05444 const char *prefix = file == Asm_File ? ASM_CMNT_LINE : "";
05445 fprintf(file, "%s<cflow> Start of cold region\n", prefix);
05446 }
05447 break;
05448 case NOTE_PRINT_HANDLER_NAME_TO_FILE:
05449 fprintf(file,"Emit_Cold_Threshold_Note");
05450 break;
05451 default:
05452 #pragma mips_frequency_hint NEVER
05453 FmtAssert(FALSE,("Didn't recognize action"));
05454
05455 }
05456 }
05457
05458
05459
05460
05461
05462
05463
05464
05465
05466
05467
05468
05469
05470
05471
05472 static RID *
05473 Create_Cold_Region(BBCHAIN *cold)
05474 {
05475 BBCHAIN *ch;
05476 RID *r;
05477 RID *parent = BB_rid(REGION_First_BB);
05478
05479
05480
05481 r = RID_Create(New_Region_Id(), 0, NULL);
05482 RID_level(r) = RL_CG;
05483 RID_type(r) = RID_TYPE_cold;
05484 RID_bounds_exist(r) = REGION_BOUND_UNKNOWN;
05485 RID_has_return(r) = REGION_NO_RETURN;
05486 RID_num_exits(r) = 0;
05487 RID_is_glue_code(r) = FALSE;
05488 RID_parent(r) = parent;
05489 RID_cginfo(r) = NULL;
05490
05491 #if 0
05492 INT i;
05493 for ( i = SWP_replication_factor - 1; i >= 0; --i ) {
05494 INT32 rep_num = Rep_Index_To_Number(i);
05495 if ( Is_Exit_Replication(rep_num) ) ++RID_num_exits(r);
05496 }
05497 #endif
05498
05499 if ( parent ) RID_Add_kid(r, parent);
05500
05501
05502
05503
05504
05505 ch = cold;
05506 do {
05507 BB *bb;
05508 for (bb = ch->head; bb; bb = bb->next) {
05509 RID *bb_rid = BB_rid(bb);
05510 if (bb_rid == parent) {
05511 BB_rid(bb) = r;
05512 } else if (bb_rid && RID_parent(bb_rid) == parent) {
05513 RID_parent(bb_rid) = r;
05514 RID_Add_kid(bb_rid, r);
05515 }
05516 Set_BBINFO_cold(bb, TRUE);
05517 }
05518 } while (ch = ch->next);
05519
05520 return r;
05521 }
05522
05523
05524
05525
05526
05527
05528
05529
05530
05531
05532
05533
05534
05535
05536
05537
05538 static void
05539 Generate_Hot_Cold_Jump(
05540 BB *bb,
05541 INT isuc,
05542 BB_MAP jump_map,
05543 BB **jumps,
05544 RID *cold_rid)
05545 {
05546 BB *jump_bb;
05547 BB *suc = BBINFO_succ_bb(bb, isuc);
05548 INT64 offset = BBINFO_succ_offset(bb, isuc);
05549 OPS ops = OPS_EMPTY;
05550
05551
05552
05553
05554 if (BBINFO_kind(bb) == BBKIND_GOTO) {
05555 OP *br = BB_branch_op(bb);
05556 OP *delay_slot = (PROC_has_branch_delay_slot() && br) ? OP_next(br) : NULL;
05557 if (br) BB_Remove_Op(bb, br);
05558
05559 Exp_Local_Jump(suc, offset, &ops);
05560 if (delay_slot) {
05561 BB_Insert_Ops_Before(bb, delay_slot, &ops);
05562 } else {
05563 BB_Append_Ops(bb, &ops);
05564 }
05565 if (BB_branch_wn(bb) == NULL) {
05566 LABEL_IDX lab = Gen_Label_For_BB(suc);
05567 LABEL_IDX lnum = lab;
05568 WN *wn = WN_CreateGoto(lab, lnum);
05569 BB_branch_wn(bb) = wn;
05570 }
05571
05572
05573
05574 if (!CG_localize_tns) {
05575 GRA_LIVE_Compute_Liveness_For_BB(bb);
05576 }
05577
05578 DevWarn("replaced branch with jump in BB:%d", BB_id(bb));
05579 return;
05580 }
05581
05582
05583
05584
05585 Unlink_Pred_Succ(bb, suc);
05586
05587
05588
05589 jump_bb = (BB *)BB_MAP_Get(jump_map, suc);
05590 if (jump_bb == NULL) {
05591 WN *wn;
05592 BBINFO *bbinfo;
05593 LABEL_IDX lab = Gen_Label_For_BB(suc);
05594 LABEL_IDX lnum = lab;
05595
05596 jump_bb = Alloc_BB_Like(NULL);
05597 BB_rid(jump_bb) = BBINFO_cold(bb) ? cold_rid : BB_rid(REGION_First_BB);
05598 BB_freq(jump_bb) = 0.0;
05599 wn = WN_CreateGoto(lab, lnum);
05600 BB_branch_wn(jump_bb) = wn;
05601
05602 bbinfo = (BBINFO *)MEM_POOL_Alloc(&MEM_local_nz_pool, sizeof(BBINFO));
05603 bbinfo->kind = BBKIND_GOTO;
05604 bbinfo->eh_rgn = 0;
05605 bbinfo->cold = BBINFO_cold(bb);
05606 bbinfo->nsuccs = 1;
05607 bbinfo->succs[0].bb = suc;
05608 bbinfo->succs[0].offset = offset;
05609 bbinfo->succs[0].prob = 1.0;
05610 BB_MAP_Set(bb_info_map, jump_bb, bbinfo);
05611
05612 Link_Pred_Succ_with_Prob(jump_bb, suc, 1.0);
05613
05614 Exp_Local_Jump(suc, offset, &ops);
05615 BB_Append_Ops(jump_bb, &ops);
05616
05617 BB_MAP_Set(jump_map, suc, (void *)jump_bb);
05618
05619 Chain_BBs(jump_bb, *jumps);
05620 *jumps = jump_bb;
05621 DevWarn("created jump BB:%d", BB_id(jump_bb));
05622 }
05623
05624
05625
05626 Set_BBINFO_succ_bb(bb, isuc, jump_bb);
05627 Link_Pred_Succ_with_Prob(bb, jump_bb, BBINFO_succ_prob(bb, isuc));
05628 BB_freq(jump_bb) += BB_freq(bb) * BBINFO_succ_prob(bb, isuc);
05629
05630
05631
05632 if (!CG_localize_tns && BB_bbregs(jump_bb) == NULL) {
05633 GRA_LIVE_Compute_Liveness_For_BB(jump_bb);
05634 }
05635 DevWarn("redirected BB:%d to jump BB:%d", BB_id(bb), BB_id(jump_bb));
05636 }
05637
05638
05639
05640
05641
05642
05643
05644
05645
05646
05647
05648
05649 static void
05650 Patch_Hot_Cold_Jumps(
05651 BBCHAIN *chains,
05652 BB_MAP chain_map,
05653 BBCHAIN *cold,
05654 RID *cold_rid)
05655 {
05656 BBCHAIN *ch;
05657 BB_MAP jump_map;
05658 BB *jumps;
05659
05660 FmtAssert(chains != cold, ("empty hot region!"));
05661
05662
05663
05664 jump_map = BB_MAP_Create();
05665
05666 jumps = NULL;
05667 ch = chains;
05668 do {
05669 BB *bb;
05670 for (bb = ch->head; bb; bb = bb->next) {
05671 INT i;
05672
05673 if ( BBINFO_kind(bb) == BBKIND_VARGOTO
05674 || BBINFO_kind(bb) == BBKIND_INDGOTO) continue;
05675
05676 for (i = 0; i < BBINFO_nsuccs(bb); ++i) {
05677 BB *suc = BBINFO_succ_bb(bb,i);
05678 if (BBINFO_cold(bb) != BBINFO_cold(suc)) {
05679 Generate_Hot_Cold_Jump(bb, i, jump_map, &jumps, cold_rid);
05680 }
05681 }
05682 }
05683 } while (ch = ch->next);
05684
05685 BB_MAP_Delete(jump_map);
05686
05687
05688
05689
05690
05691
05692
05693
05694
05695 while (jumps) {
05696 BBLIST *pedge;
05697 BOOL best_pred_is_tail;
05698 BB *best_pred = NULL;
05699 float best_freq = -FLT_MAX;
05700 BB *bb = jumps;
05701 jumps = BB_next(jumps);
05702
05703 best_pred_is_tail = FALSE;
05704 FOR_ALL_BB_PREDS(bb, pedge) {
05705 BOOL pred_is_tail;
05706 BB *pred = BBLIST_item(pedge);
05707 BBLIST *sedge = BB_Find_Succ(pred, bb);
05708 float freq = BB_freq(pred) * BBLIST_prob(sedge);
05709 ch = BB_Chain(chain_map, pred);
05710 pred_is_tail = pred == ch->tail;
05711
05712 if ( (pred_is_tail == best_pred_is_tail && freq > best_freq)
05713 || (pred_is_tail && !best_pred_is_tail))
05714 {
05715 best_freq = freq;
05716 best_pred = pred;
05717 best_pred_is_tail = pred_is_tail;
05718 }
05719 }
05720
05721 ch = BB_Chain(chain_map, best_pred);
05722 Chain_BBs(bb, NULL);
05723 Chain_BBs(ch->tail, bb);
05724 ch->tail = bb;
05725 }
05726 }
05727
05728
05729
05730
05731
05732
05733
05734
05735
05736
05737
05738
05739 static BBCHAIN *
05740 Validate_Cold_Region(BBCHAIN *chains, BBCHAIN *cold_region)
05741 {
05742 mBB_NUM *bb_ord;
05743 BB_NUM n;
05744 BBCHAIN *ch;
05745
05746 #define BB_ORD(b) (bb_ord[BB_id(b)])
05747
05748
05749
05750
05751
05752
05753
05754
05755
05756 bb_ord = (mBB_NUM *)alloca((PU_BB_Count + 1) * sizeof(mBB_NUM));
05757 n = 0;
05758 ch = chains;
05759 do {
05760 BB *bb;
05761 for (bb = ch->head; bb; bb = BB_next(bb)) bb_ord[BB_id(bb)] = n++;
05762 } while (ch = ch->next);
05763
05764
05765
05766
05767
05768 ch = cold_region;
05769 do {
05770 BB *bb;
05771 BB_NUM cold_ord = BB_ORD(cold_region->head);
05772
05773 #ifdef TARG_SL
05774 BB *ch_head = ch->head;
05775 if (ch_head != NULL) {
05776 BBLIST *edge;
05777 FOR_ALL_BB_PREDS(ch_head, edge) {
05778 BB *pred = BBLIST_item(edge);
05779 if (OP_fork(BB_last_op(pred))) {
05780 BBCHAIN *new_cold = ch->next;
05781 if (CFLOW_Trace_Freq_Order) {
05782 #pragma mips_frequency_hint NEVER
05783 fprintf(TFile, " fork target caused cold region start"
05784 " to move from BB:%d to BB:%d\n",
05785 BB_id(cold_region->head),
05786 new_cold ? BB_id(new_cold->head) : -1);
05787 }
05788 cold_region = new_cold;
05789 goto next_chain;
05790 }
05791 }
05792 }
05793 #endif
05794
05795 for (bb = ch->head; bb; bb = BB_next(bb)) {
05796 BBLIST *edge;
05797
05798
05799
05800
05801
05802 if (BBINFO_eh_rgn(bb) || BB_handler(bb)) {
05803 BBCHAIN *new_cold = ch->next;
05804 if (CFLOW_Trace_Freq_Order) {
05805 #pragma mips_frequency_hint NEVER
05806 fprintf(TFile, " EH region or handler caused cold region start"
05807 " to move from BB:%d to BB:%d\n",
05808 BB_id(cold_region->head),
05809 new_cold ? BB_id(new_cold->head) : -1);
05810 }
05811 cold_region = new_cold;
05812 goto next_chain;
05813 }
05814
05815 #ifdef TARG_SL
05816 if (OP_fork(BB_last_op(bb))) {
05817 BBCHAIN *new_cold = ch->next;
05818 if (CFLOW_Trace_Freq_Order) {
05819 #pragma mips_frequency_hint NEVER
05820 fprintf(TFile, " fork instruction caused cold region start"
05821 " to move from BB:%d to BB:%d\n",
05822 BB_id(cold_region->head),
05823 new_cold ? BB_id(new_cold->head) : -1);
05824 }
05825 cold_region = new_cold;
05826 goto next_chain;
05827 }
05828
05829 #endif
05830
05831
05832
05833
05834
05835
05836 FOR_ALL_BB_SUCCS(bb, edge) {
05837 BB *suc = BBLIST_item(edge);
05838 if ( BB_rid(bb) != BB_rid(suc)
05839 && (BB_ORD(bb) < cold_ord) != (BB_ORD(suc) < cold_ord))
05840 {
05841 BBCHAIN *new_cold = ch->next;
05842 if (CFLOW_Trace_Freq_Order) {
05843 #pragma mips_frequency_hint NEVER
05844 fprintf(TFile, " glue block caused cold region start"
05845 " to move from BB:%d to BB:%d\n",
05846 BB_id(cold_region->head),
05847 new_cold ? BB_id(new_cold->head) : -1);
05848 }
05849 cold_region = new_cold;
05850 goto next_chain;
05851 }
05852 }
05853 FOR_ALL_BB_PREDS(bb, edge) {
05854 BB *pred = BBLIST_item(edge);
05855 if ( BB_rid(bb) != BB_rid(pred)
05856 && (BB_ORD(bb) < cold_ord) != (BB_ORD(pred) < cold_ord))
05857 {
05858 BBCHAIN *new_cold = ch->next;
05859 if (CFLOW_Trace_Freq_Order) {
05860 #pragma mips_frequency_hint NEVER
05861 fprintf(TFile, " glue block caused cold region start"
05862 " to move from BB:%d to BB:%d\n",
05863 BB_id(cold_region->head),
05864 new_cold ? BB_id(new_cold->head) : -1);
05865 }
05866 cold_region = new_cold;
05867 goto next_chain;
05868 }
05869 }
05870 }
05871 next_chain:
05872 ;
05873 } while (ch = ch->next);
05874
05875 return cold_region;
05876 }
05877
05878
05879
05880
05881
05882
05883
05884
05885
05886
05887
05888
05889
05890
05891
05892
05893
05894
05895
05896
05897
05898
05899
05900
05901 static BBCHAIN *
05902 Order_Chains(BBCHAIN *unordered, BB_MAP chain_map)
05903 {
05904 BBCHAIN *chain;
05905 BBCHAIN *ordered;
05906 BBCHAIN *last_ordered;
05907 BB *root;
05908
05909
05910
05911 if (Compiling_Proper_REGION) {
05912 root = CGRIN_entry(RID_Find_Cginfo(REGION_First_BB));
05913 } else if (BB_LIST_rest(Entry_BB_Head) == NULL) {
05914 root = BB_LIST_first(Entry_BB_Head);
05915 } else {
05916
05917
05918 root = REGION_First_BB;
05919 }
05920
05921
05922
05923
05924
05925 chain = BB_Chain(chain_map, root);
05926 unordered = Remove_Chain(unordered, chain);
05927 chain->prev = NULL;
05928 chain->next = NULL;
05929 ordered = chain;
05930 last_ordered = chain;
05931
05932
05933
05934
05935
05936 while (unordered) {
05937 BBCHAIN *ch;
05938 double max_weight;
05939
05940
05941
05942
05943 Weight_Succ_Chains(chain_map, last_ordered);
05944
05945
05946
05947
05948 max_weight = unordered->weight;
05949 chain = unordered;
05950 for (ch = unordered->next; ch; ch = ch->next) {
05951 if ( (ch->never == chain->never && ch->weight > max_weight)
05952 || (!ch->never && chain->never))
05953 {
05954 chain = ch;
05955 max_weight = ch->weight;
05956 }
05957 }
05958
05959
05960
05961
05962
05963 if (max_weight < 0.0) {
05964 if (CG_warn_bad_freqs) {
05965 #pragma mips_frequency_hint NEVER
05966 DevWarn("cflow (Order_Chains) found inconsistent freqs:\n"
05967 "\tmost likely, something before cflow is broken.\n"
05968 "\tcflow will cope but please submit a pv");
05969 }
05970 chain = unordered;
05971 }
05972
05973
05974
05975
05976 unordered = Remove_Chain(unordered, chain);
05977 chain->next = NULL;
05978 chain->prev = last_ordered;
05979 last_ordered->next = chain;
05980 last_ordered = chain;
05981 }
05982
05983
05984
05985
05986
05987 #if defined(TARG_SL)
05988 if (CFLOW_cold_threshold && (current_flags & CFLOW_COLD_REGION)) {
05989 #else
05990 if (CFLOW_cold_threshold) {
05991 #endif
05992 BBCHAIN *ch = last_ordered;
05993
05994
05995
05996
05997
05998
05999 do {
06000 BB *bb;
06001
06002 if (ch->never) break;
06003
06004 for (bb = ch->head; bb; bb = BB_next(bb)) {
06005 if (BB_freq(bb) > cold_threshold) {
06006 ch = ch->next;
06007 goto found_hot;
06008 }
06009 }
06010 } while (ch = ch->prev);
06011
06012 found_hot:
06013 ;
06014
06015
06016
06017 if (ch) {
06018
06019
06020
06021
06022
06023 ch = Validate_Cold_Region(ordered, ch);
06024 if (ch) {
06025 RID *cold_rid;
06026 BB *cold_bb = ch->head;
06027 NOTE_Add_To_BB(cold_bb, Emit_Cold_Threshold_Note, (NOTE_INFO *)NULL);
06028 cold_rid = Create_Cold_Region(ch);
06029 Patch_Hot_Cold_Jumps(ordered, chain_map, ch, cold_rid);
06030 }
06031 }
06032 }
06033
06034 return ordered;
06035 }
06036
06037
06038
06039
06040
06041
06042
06043
06044
06045
06046
06047
06048
06049
06050
06051
06052 static void
06053 Optimize_Cyclic_Chain(BBCHAIN *chain, BB_MAP chain_map)
06054 {
06055 float best_gain;
06056 BB *bb;
06057 BB *best_tail = chain->tail;
06058 RID *outer_rid = BB_rid(chain->head);
06059
06060
06061
06062
06063
06064
06065
06066
06067
06068 best_gain = -FLT_MAX;
06069 for (bb = chain->tail; bb; bb = BB_prev(bb)) {
06070 float tail_gain;
06071 BB *next;
06072
06073
06074
06075 next = bb == chain->tail ? chain->head : BB_next(bb);
06076
06077
06078
06079
06080 if (BBINFO_eh_rgn(bb) && BBINFO_eh_rgn(next)) continue;
06081
06082
06083
06084
06085 if (BB_rid(bb) != outer_rid || BB_rid(next) != outer_rid) continue;
06086
06087
06088
06089
06090
06091 switch (BBINFO_kind(bb)) {
06092 case BBKIND_LOGIF:
06093 {
06094 float p_fall;
06095 float p_taken;
06096 BB *targ;
06097 BBCHAIN *targ_chain;
06098 BOOL no_fall;
06099
06100
06101
06102
06103 targ = BBINFO_succ_bb(bb, 0);
06104 p_taken = BBINFO_succ_prob(bb, 0);
06105 if (targ == next) {
06106 p_taken = 1.0 - p_taken;
06107 targ = BBINFO_succ_bb(bb, 1);
06108 }
06109
06110
06111
06112
06113
06114
06115
06116
06117
06118
06119 targ_chain = BB_Chain(chain_map, targ);
06120 no_fall = targ_chain == chain || targ != targ_chain->head;
06121
06122
06123
06124
06125
06126 if (no_fall && p_taken < 0.5) p_taken = 1.0 - p_taken;
06127 p_fall = 1.0 - p_taken;
06128
06129
06130
06131
06132 tail_gain = (p_fall - p_taken) * br_fall_cost
06133 + (p_taken - p_fall) * br_taken_cost;
06134 if (no_fall) tail_gain -= p_taken * br_taken_cost;
06135 tail_gain *= BB_freq(bb);
06136 }
06137 break;
06138 case BBKIND_GOTO:
06139 case BBKIND_CALL:
06140
06141
06142
06143
06144 tail_gain = 0.0 - (br_taken_cost * BB_freq(bb));
06145 break;
06146 default:
06147
06148
06149
06150 tail_gain = 0.0;
06151 break;
06152 }
06153
06154
06155
06156
06157 if ( (tail_gain > best_gain)
06158 || ( tail_gain == best_gain
06159 && BB_loop_head_bb(next) == next
06160 && BB_loop_head_bb(bb) == next)
06161 ) {
06162 best_tail = bb;
06163 best_gain = tail_gain;
06164 }
06165 }
06166
06167
06168
06169 if (best_tail != chain->tail) {
06170 BB *best_head = BB_next(best_tail);
06171 BB *orig_head = chain->head;
06172 BB *orig_tail = chain->tail;
06173 if (CFLOW_Trace_Freq_Order) {
06174 #pragma mips_frequency_hint NEVER
06175 fprintf(TFile,
06176 " BB:%d would be a better head of cyclic chain than BB:%d\n",
06177 BB_id(best_head), BB_id(orig_head));
06178 }
06179 Chain_BBs(NULL, best_head);
06180 Chain_BBs(best_tail, NULL);
06181 Chain_BBs(orig_tail, orig_head);
06182 chain->head = best_head;
06183 chain->tail = best_tail;
06184 }
06185 }
06186
06187
06188
06189
06190
06191
06192
06193
06194
06195
06196 static BBCHAIN *
06197 Grow_Chains(BBCHAIN *chains, EDGE *edges, INT n_edges, BB_MAP chain_map)
06198 {
06199 INT i;
06200 #ifdef KEY
06201 INT j;
06202 #endif
06203
06204
06205
06206 for (i = 0; i < n_edges; ++i) {
06207 EDGE *e = edges + i;
06208 BB *pred = e->pred;
06209 BB *succ = e->succ;
06210 BBCHAIN *pchain = BB_Chain(chain_map, pred);
06211 BBCHAIN *schain = BB_Chain(chain_map, succ);
06212
06213 #ifdef KEY
06214 if (CFLOW_Enable_Freq_Order_On_Heuristics){
06215 if (e->freq == 0)
06216 continue;
06217 if (BB_id(pred) > BB_id(succ)) {
06218 for (j = i+1; j < n_edges; j++) {
06219 if (edges[j].pred == pred && edges[j].succ != succ && edges[j].freq > 0)
06220 break;
06221 }
06222 if (j != n_edges)
06223 continue;
06224 }
06225 }
06226 #endif
06227
06228
06229
06230
06231 if (pchain != schain && pchain->tail == pred && schain->head == succ) {
06232 INT j;
06233 INT nsuccs;
06234 BB *bb;
06235 BB *head = pchain->head;
06236 BB *tail = schain->tail;
06237
06238
06239
06240 Chain_BBs(pred, succ);
06241 pchain->tail = tail;
06242
06243
06244
06245 for (bb = schain->head; ; bb = BB_next(bb)) {
06246 BB_MAP_Set(chain_map, bb, pchain);
06247 if (bb == tail) break;
06248 }
06249
06250
06251
06252 chains = Remove_Chain(chains, schain);
06253
06254
06255
06256
06257 nsuccs = BBINFO_nsuccs(tail);
06258 for (j = 0; j < nsuccs; j++) {
06259 if ( BBINFO_succ_bb(tail, j) == head
06260 && BBINFO_succ_offset(tail, j) == 0
06261 ) {
06262 Optimize_Cyclic_Chain(pchain, chain_map);
06263 break;
06264 }
06265 }
06266 }
06267 }
06268
06269 return chains;
06270 }
06271
06272
06273
06274
06275
06276
06277
06278
06279
06280
06281 static void
06282 Combine_Chains(BBCHAIN *chains)
06283 {
06284 BBCHAIN *chain;
06285 BB *tail = NULL;
06286 BB *head = chains->head;
06287 for (chain = chains; chain; chain = chain->next) {
06288 Chain_BBs(tail, chain->head);
06289 tail = chain->tail;
06290 }
06291 Chain_BBs(tail, NULL);
06292
06293 if (Compiling_Proper_REGION) {
06294 RID *head_rid = BB_rid(head);
06295 CGRIN *cgrin = RID_cginfo(head_rid);
06296 FmtAssert(
06297 head_rid == BB_rid(REGION_First_BB),
06298 ("Combine_Chains: illegal region formed"));
06299
06300
06301
06302 CGRIN_first_bb(cgrin) = head;
06303 CGRIN_last_bb(cgrin) = tail;
06304 }
06305 REGION_First_BB = head;
06306 }
06307
06308
06309
06310
06311
06312
06313
06314
06315
06316
06317 static void
06318 Print_Chain_BBs(BBCHAIN *chain)
06319 {
06320 BB *bb;
06321 for (bb = chain->head; ; ) {
06322 fprintf(TFile, "%d", BB_id(bb));
06323 bb = BB_next(bb);
06324 if (!bb) break;
06325 fprintf(TFile, "-");
06326 }
06327 fprintf(TFile, "\n");
06328 }
06329
06330
06331
06332
06333
06334
06335
06336
06337
06338
06339 static void
06340 Print_Chains(BBCHAIN *chains)
06341 {
06342 BBCHAIN *chain;
06343 INT i;
06344 BBCHAIN *cold = NULL;
06345
06346 for (i = 0, chain = chains; chain; chain = chain->next, ++i) {
06347 if (cold == NULL && BBINFO_cold(chain->head)) {
06348 fprintf(TFile, " Start of cold region\n");
06349 }
06350 fprintf(TFile, " [%d]: weight=%g, ", i, chain->weight);
06351 Print_Chain_BBs(chain);
06352 }
06353 }
06354
06355
06356
06357
06358
06359
06360
06361
06362
06363
06364
06365
06366
06367 static double
06368 Dynamic_Branch_Cost(
06369 BB *first_bb,
06370 INT *p_n_stat_fall)
06371 {
06372 BB *bb;
06373 BB *bb_next;
06374 double n_taken = 0.0;
06375 double n_fall_thru = 0.0;
06376 INT n_stat_fall = 0;
06377
06378 for (bb = first_bb; bb; bb = bb_next) {
06379 double freq;
06380 BB *succ;
06381
06382 bb_next = BB_next(bb);
06383
06384 switch (BBINFO_kind(bb)) {
06385 case BBKIND_LOGIF:
06386 succ = BBINFO_succ_bb(bb, 0);
06387 freq = BB_freq(bb) * BBINFO_succ_prob(bb, 0);
06388 if (succ == bb_next) {
06389 n_fall_thru += freq;
06390 ++n_stat_fall;
06391 } else {
06392 n_taken += freq;
06393 }
06394 succ = BBINFO_succ_bb(bb, 1);
06395 freq = BB_freq(bb) * BBINFO_succ_prob(bb, 1);
06396 if (succ == bb_next) {
06397 n_fall_thru += freq;
06398 ++n_stat_fall;
06399 } else {
06400 n_taken += freq;
06401 }
06402 break;
06403 case BBKIND_GOTO:
06404 case BBKIND_CALL:
06405 succ = BBINFO_succ_bb(bb, 0);
06406 if (succ == bb_next) {
06407 ++n_stat_fall;
06408 } else {
06409 n_taken += BB_freq(bb);
06410 }
06411 break;
06412 case BBKIND_VARGOTO:
06413 case BBKIND_INDGOTO:
06414
06415
06416
06417
06418 break;
06419 case BBKIND_RETURN:
06420 case BBKIND_TAIL_CALL:
06421 case BBKIND_REGION_EXIT:
06422 #if defined(TARG_SL)
06423 case BBKIND_ZDL_BODY:
06424 case BBKIND_FORK:
06425 #endif
06426 break;
06427 default:
06428 #pragma mips_frequency_hint NEVER
06429 FmtAssert(FALSE, ("unhandled BBKIND"));
06430
06431 }
06432 }
06433
06434 if (p_n_stat_fall) *p_n_stat_fall = n_stat_fall;
06435 return n_taken * br_taken_cost + n_fall_thru * br_fall_cost;
06436 }
06437
06438
06439
06440
06441
06442
06443
06444
06445
06446
06447 static BOOL
06448 Freq_Order_Blocks(void)
06449 {
06450 double cost0, cost1;
06451 INT stat_fall0, stat_fall1;
06452 INT n_succs;
06453 EDGE *edges;
06454 INT n_edges;
06455 BBCHAIN *chains;
06456 BB_MAP chain_map;
06457
06458 #if 0
06459
06460
06461
06462 if (have_eh_regions) return FALSE;
06463 #endif
06464
06465
06466
06467 never_bbs = FREQ_Find_Never_BBs(&MEM_local_pool);
06468 if (CFLOW_Trace_Freq_Order) {
06469 #pragma mips_frequency_hint NEVER
06470 fprintf(TFile, "\nBBs 'never' executed as infered by hint pragmas: ");
06471 BB_SET_Print(never_bbs, TFile);
06472 fprintf(TFile, "\n");
06473 }
06474
06475
06476
06477 if (CFLOW_Trace_Freq_Order) {
06478 #pragma mips_frequency_hint NEVER
06479 cost0 = Dynamic_Branch_Cost(REGION_First_BB, &stat_fall0);
06480 }
06481
06482 #if defined(TARG_SL)
06483
06484 if ( !Compiling_Proper_REGION ) {
06485 for (BB* bb = REGION_First_BB; bb; bb=BB_next(bb)) {
06486 if(BBINFO_eh_rgn(bb) || BB_handler(bb)) continue;
06487 BB_rid(bb) = BB_rid(REGION_First_BB);
06488 }
06489 }
06490 #endif
06491
06492
06493 n_succs = Count_Succ_Edges();
06494 edges = (EDGE *)alloca(sizeof(EDGE) * n_succs);
06495
06496
06497
06498 n_edges = Init_Edges(edges);
06499
06500
06501
06502
06503 if (CFLOW_Trace_Freq_Order) {
06504 #pragma mips_frequency_hint NEVER
06505 fprintf(TFile, "\nInit_Chains:\n");
06506 }
06507 chains = (BBCHAIN *)alloca(sizeof(BBCHAIN) * (PU_BB_Count + 2));
06508 chain_map = Init_Chains(chains);
06509
06510
06511
06512 if (CFLOW_Trace_Freq_Order) {
06513 #pragma mips_frequency_hint NEVER
06514 fprintf(TFile, "\nGrow_Chains:\n");
06515 }
06516 chains = Grow_Chains(chains, edges, n_edges, chain_map);
06517
06518 if (CFLOW_Trace_Freq_Order) {
06519 #pragma mips_frequency_hint NEVER
06520 fprintf(TFile, "\nMerged chains:\n");
06521 Print_Chains(chains);
06522 }
06523
06524
06525
06526 chains = Order_Chains(chains, chain_map);
06527
06528 if (CFLOW_Trace_Freq_Order) {
06529 #pragma mips_frequency_hint NEVER
06530 fprintf(TFile, "\nOrdered chains:\n");
06531 Print_Chains(chains);
06532 }
06533
06534
06535
06536 Combine_Chains(chains);
06537
06538
06539
06540 if (CFLOW_Trace_Freq_Order) {
06541 #pragma mips_frequency_hint NEVER
06542 cost1 = Dynamic_Branch_Cost(REGION_First_BB, &stat_fall1);
06543 fprintf(TFile, "\nBranches %s: cost=%g, stat-fall=%d\n",
06544 "before ordering", cost0, stat_fall0);
06545 fprintf(TFile, "Branches %s: cost=%g, stat-fall=%d\n",
06546 "after ordering", cost1, stat_fall1);
06547 if (cost1 > cost0) {
06548 DevWarn("Dynamic branch cost increased: before=%g, after=%g",
06549 cost0, cost1);
06550 }
06551 if (stat_fall0 > stat_fall1) {
06552 DevWarn("Static branch fall-thrus decreased: before=%d, after=%d",
06553 stat_fall0, stat_fall1);
06554 }
06555 }
06556
06557 return TRUE;
06558 }
06559
06560
06561
06562
06563
06564
06565
06566
06567
06568
06569
06570
06571
06572 typedef struct clone_cand {
06573 struct clone_cand *next;
06574 BB *pred;
06575 #if DEBUG_CFLOW
06576 float gain;
06577 float cost;
06578 #endif
06579 float metric;
06580 INT metric_class;
06581 } CLONE_CAND;
06582
06583
06584
06585
06586
06587 static INT callee_saves[ISA_REGISTER_CLASS_MAX + 1];
06588
06589
06590
06591
06592
06593
06594
06595
06596
06597
06598
06599
06600
06601
06602
06603
06604
06605
06606
06607
06608
06609
06610
06611
06612
06613
06614
06615
06616
06617
06618
06619
06620
06621
06622 static void
06623 Estimate_Callee_Saves(void)
06624 {
06625 BB *bb;
06626 ISA_REGISTER_CLASS rc;
06627
06628
06629
06630
06631
06632 if (CG_localize_tns) return;
06633
06634 MEM_POOL_Push(&MEM_local_pool);
06635
06636 BZERO(callee_saves, sizeof(callee_saves));
06637 for (bb = REGION_First_BB; bb; bb = BB_next(bb)) {
06638 INT tn_count[ISA_REGISTER_CLASS_MAX + 1];
06639 TN *tn;
06640 GTN_SET *live_in;
06641 GTN_SET *live_out;
06642 GTN_SET *need_reg;
06643 BOOL is_call = (BBINFO_kind(bb) == BBKIND_CALL) && BBINFO_nsuccs(bb);
06644
06645
06646
06647 live_in = GTN_SET_Intersection(BB_live_in(bb),
06648 BB_defreach_in(bb),
06649 &MEM_local_pool);
06650 live_out = GTN_SET_Intersection(BB_live_out(bb),
06651 BB_defreach_out(bb),
06652 &MEM_local_pool);
06653 need_reg = GTN_SET_Union(live_in, live_out, &MEM_local_pool);
06654
06655
06656
06657
06658 BZERO(tn_count, sizeof(tn_count));
06659 for (tn = GTN_SET_Choose(need_reg);
06660 tn && tn != GTN_SET_CHOOSE_FAILURE;
06661 tn = GTN_SET_Choose_Next(need_reg, tn))
06662 {
06663 if (tn && !TN_is_save_reg(tn)) {
06664 rc = TN_register_class(tn);
06665 ++tn_count[rc];
06666 }
06667 }
06668
06669
06670
06671
06672 FOR_ALL_ISA_REGISTER_CLASS(rc) {
06673 INT count;
06674
06675
06676
06677
06678 count = tn_count[rc];
06679
06680
06681
06682
06683
06684 if (!is_call) {
06685 INT caller = REGISTER_SET_Size(REGISTER_CLASS_caller_saves(rc));
06686 count -= caller;
06687 }
06688
06689
06690
06691
06692 count = (count * 2 + 2) / 3;
06693
06694 if (count > callee_saves[rc]) callee_saves[rc] = count;
06695 }
06696 }
06697
06698 MEM_POOL_Pop(&MEM_local_pool);
06699
06700 if (CFLOW_Trace_Clone) {
06701 ISA_REGISTER_CLASS rc;
06702 #pragma mips_frequency_hint NEVER
06703 fprintf(TFile, "\nEstimate_Callee_Saves:\n");
06704 FOR_ALL_ISA_REGISTER_CLASS(rc) {
06705 INT count = callee_saves[rc];
06706 fprintf(TFile, " %s callee saves: %d\n", REGISTER_CLASS_name(rc), count);
06707 }
06708 }
06709 }
06710
06711
06712
06713
06714
06715
06716
06717
06718
06719
06720
06721
06722 static INT32
06723 Estimate_BB_Length(BB *bb)
06724 {
06725 INT32 cost = BB_length(bb);
06726
06727 if (!CG_localize_tns && (BB_exit(bb) || BB_entry(bb))) {
06728 INT callees_needed[ISA_REGISTER_CLASS_MAX + 1];
06729 OP *op;
06730 BCOPY(callee_saves, callees_needed, sizeof(callee_saves));
06731 FOR_ALL_BB_OPs(bb, op) {
06732 ISA_REGISTER_CLASS rc;
06733 TN *tn;
06734
06735 if (!OP_copy(op)) continue;
06736 if ( !TN_is_save_reg(tn = OP_result(op,0))
06737 && !TN_is_save_reg(tn = OP_opnd(op,OP_COPY_OPND))) continue;
06738
06739 rc = TN_register_class(tn);
06740 if (callees_needed[rc]) {
06741 --callees_needed[rc];
06742 } else {
06743 --cost;
06744 }
06745 }
06746 }
06747
06748 return cost;
06749 }
06750
06751
06752
06753
06754
06755
06756
06757
06758
06759
06760
06761
06762 static CG_SCHED_EST *
06763 Create_Sched_Est(BB *bb, MEM_POOL *pool)
06764 {
06765 CG_SCHED_EST *se;
06766 se = CG_SCHED_EST_Create(bb, pool, SCHED_EST_FOR_CLONING);
06767
06768 if (!CG_localize_tns && (BB_entry(bb) || BB_exit(bb))) {
06769 INT callees_needed[ISA_REGISTER_CLASS_MAX + 1];
06770 OP *op;
06771 BCOPY(callee_saves, callees_needed, sizeof(callee_saves));
06772 FOR_ALL_BB_OPs(bb, op) {
06773 ISA_REGISTER_CLASS rc;
06774 TN *tn;
06775
06776 if (!OP_copy(op)) continue;
06777 if ( !TN_is_save_reg(tn = OP_result(op,0))
06778 && !TN_is_save_reg(tn = OP_opnd(op,OP_COPY_OPND))) continue;
06779
06780 rc = TN_register_class(tn);
06781 if (callees_needed[rc]) {
06782 --callees_needed[rc];
06783 } else {
06784 CG_SCHED_EST_Ignore_Op(se, op);
06785 }
06786 }
06787 }
06788
06789 return se;
06790 }
06791
06792
06793
06794
06795
06796
06797
06798
06799
06800
06801
06802 static float
06803 Cloned_Gain(BB *pred, BB *suc)
06804 {
06805 float uncombined_cycles;
06806 float combined_cycles;
06807 float gain;
06808 CG_SCHED_EST *se_a;
06809 CG_SCHED_EST *se_b;
06810
06811
06812
06813
06814 Finalize_BB(pred);
06815
06816
06817
06818 MEM_POOL_Push(&MEM_local_nz_pool);
06819 se_a = Create_Sched_Est(pred, &MEM_local_nz_pool);
06820 se_b = Create_Sched_Est(suc, &MEM_local_nz_pool);
06821 uncombined_cycles = CG_SCHED_EST_Cycles(se_a)
06822 + CG_SCHED_EST_Cycles(se_b);
06823
06824
06825
06826
06827 if (BB_next(pred) != suc) {
06828 OP *br = BB_branch_op(pred);
06829 uncombined_cycles += CGTARG_Branch_Taken_Penalty();
06830 CG_SCHED_EST_Ignore_Op(se_a, br);
06831 }
06832 Is_True(uncombined_cycles != 0, ("uncombined_cycles == 0"));
06833
06834
06835
06836 CG_SCHED_EST_Append_Scheds(se_a, se_b);
06837 combined_cycles = CG_SCHED_EST_Cycles(se_a);
06838 CG_SCHED_EST_Delete(se_a);
06839 CG_SCHED_EST_Delete(se_b);
06840 MEM_POOL_Pop(&MEM_local_nz_pool);
06841
06842
06843
06844
06845
06846
06847 gain = (uncombined_cycles - combined_cycles) * BB_freq(pred);
06848
06849 return gain;
06850 }
06851
06852
06853
06854
06855
06856
06857
06858
06859
06860
06861
06862
06863
06864
06865
06866
06867 static INT
06868 Compare_Clone_Cands(const void *p1, const void *p2)
06869 {
06870
06871
06872
06873
06874
06875 enum {
06876 sort_1_before_2 = -1,
06877 sort_1_after_2 = 1,
06878 sort_1_same_2 = 0
06879 };
06880 CLONE_CAND *c1 = *(CLONE_CAND **)p1;
06881 CLONE_CAND *c2 = *(CLONE_CAND **)p2;
06882
06883 INT metric_class1 = c1->metric_class;
06884 INT metric_class2 = c2->metric_class;
06885 if (metric_class1 > metric_class2) {
06886 return sort_1_before_2;
06887 } else if (metric_class1 < metric_class2) {
06888 return sort_1_after_2;
06889 }
06890
06891 float metric1 = c1->metric;
06892 float metric2 = c2->metric;
06893 if (metric1 > metric2) {
06894 return sort_1_before_2;
06895 } else if (metric1 < metric2) {
06896 return sort_1_after_2;
06897 } else {
06898 return sort_1_same_2;
06899 }
06900 }
06901
06902
06903
06904
06905
06906
06907
06908
06909
06910
06911
06912
06913 static CLONE_CAND *
06914 Sort_Clone_Cands(CLONE_CAND *cands, INT n_cand)
06915 {
06916 CLONE_CAND **candvec;
06917 INT i;
06918 CLONE_CAND *cand;
06919
06920 if (n_cand <= 1) return cands;
06921
06922
06923
06924 candvec = (CLONE_CAND **)alloca(sizeof(CLONE_CAND *) * n_cand);
06925 for (cand = cands, i = 0; i < n_cand; cand = cand->next, ++i) {
06926 candvec[i] = cand;
06927 }
06928
06929
06930
06931 qsort(candvec, n_cand, sizeof(CLONE_CAND *), Compare_Clone_Cands);
06932
06933
06934
06935 for (i = 0; i < n_cand - 1; ++i) candvec[i]->next = candvec[i + 1];
06936 candvec[n_cand - 1]->next = NULL;
06937
06938 return candvec[0];
06939 }
06940
06941
06942
06943
06944
06945
06946
06947
06948
06949
06950
06951
06952 static BOOL
06953 Clone_Blocks ( BOOL in_cgprep )
06954 {
06955 INT i;
06956 BOOL changed;
06957 BB *bp;
06958 INT npred;
06959 INT allowance;
06960 CLONE_CAND *cand;
06961 CLONE_CAND *cands = NULL;
06962 INT n_cand = 0;
06963 INT total_inst_incr = 0;
06964 INT pu_size = 0;
06965
06966
06967
06968
06969
06970 Estimate_Callee_Saves();
06971
06972
06973
06974
06975
06976 for (bp = REGION_First_BB; bp; bp = BB_next(bp)) {
06977
06978 #ifdef TARG_IA64
06979 if(IPFEC_Enable_Region_Formation && RGN_Formed){
06980 if(Home_Region(bp)->Is_No_Further_Opt())
06981 continue;
06982 }
06983 #endif
06984 INT n_local_cand;
06985 BBLIST *edge;
06986 INT32 bb_length_est = Estimate_BB_Length(bp);
06987
06988
06989
06990 pu_size += bb_length_est;
06991
06992
06993
06994
06995
06996 switch (BBINFO_kind(bp)) {
06997 case BBKIND_RETURN:
06998 case BBKIND_VARGOTO:
06999 case BBKIND_INDGOTO:
07000 case BBKIND_TAIL_CALL:
07001 break;
07002 default:
07003 continue;
07004 }
07005
07006
07007
07008
07009 npred = 0;
07010 n_local_cand = 0;
07011 FOR_ALL_BB_PREDS(bp, edge) {
07012 BB *pred = BBLIST_item(edge);
07013 #ifdef TARG_IA64
07014 if(IPFEC_Enable_Region_Formation && RGN_Formed){
07015 if(Home_Region(pred)->Is_No_Further_Opt())
07016 continue;
07017 }
07018 #endif
07019 ++npred;
07020 if (BB_length(pred) && BBINFO_kind(pred) == BBKIND_GOTO) {
07021
07022
07023
07024
07025 if (BB_loop_head_bb(pred) != BB_loop_head_bb(bp)) continue;
07026
07027 if (!Can_Append_Succ(pred, bp, NULL, FALSE, CFLOW_Trace_Clone)) {
07028 continue;
07029 }
07030
07031
07032
07033 cand = (CLONE_CAND *)alloca(sizeof(CLONE_CAND));
07034 cand->pred = pred;
07035 cand->next = cands;
07036 cands = cand;
07037 ++n_local_cand;
07038 }
07039 }
07040
07041
07042
07043
07044 if (n_local_cand != 0) {
07045 float rebate;
07046
07047
07048
07049
07050
07051
07052
07053
07054
07055 rebate = (n_local_cand == npred)
07056 ? ((float)bb_length_est / (float)n_local_cand) : 0.0;
07057
07058
07059
07060 cand = cands;
07061 i = n_local_cand;
07062 do {
07063 INT metric_class;
07064 BB *pred = cand->pred;
07065 BOOL pred_had_branch = (BB_next(pred) != bp);
07066 float cost = bb_length_est - pred_had_branch - rebate;
07067 float gain = Cloned_Gain(pred, bp);
07068
07069 #if DEBUG_CFLOW
07070 cand->cost = cost + rebate;
07071 cand->gain = gain;
07072 #endif
07073
07074
07075
07076
07077
07078 metric_class = 2;
07079 if (gain == 0.0 && cost != 0.0) {
07080 float freq = BB_freq(pred);
07081 if (freq != 0.0) {
07082 gain = freq;
07083 metric_class = 1;
07084 } else {
07085 gain = 1.0;
07086 metric_class = 0;
07087 }
07088 }
07089
07090 cand->metric_class = metric_class;
07091 cand->metric = gain / cost;
07092 } while (cand = cand->next, --i);
07093
07094 n_cand += n_local_cand;
07095 }
07096 }
07097
07098
07099
07100 cands = Sort_Clone_Cands(cands, n_cand);
07101 if (CFLOW_Trace_Clone) {
07102 #pragma mips_frequency_hint NEVER
07103 fprintf(TFile, "\nSorted candidates:\n");
07104 for (cand = cands, i = 0; i < n_cand; cand = cand->next, ++i) {
07105 BB *pred = cand->pred;
07106 BB *suc = BBINFO_succ_bb(pred, 0);
07107 fprintf(TFile, " [%d]: BB:%d->BB:%d"
07108 #if DEBUG_CFLOW
07109 ", gain=%g, cost=%g"
07110 #endif
07111 ", class=%d, metric=%g\n",
07112 i, BB_id(pred), BB_id(suc),
07113 #if DEBUG_CFLOW
07114 cand->gain, cand->cost,
07115 #endif
07116 cand->metric_class, cand->metric);
07117 }
07118 }
07119
07120
07121
07122
07123
07124 allowance = (pu_size * CFLOW_clone_incr + 99) / 100;
07125 if (allowance < CFLOW_clone_min_incr) allowance = CFLOW_clone_min_incr;
07126 if (allowance > CFLOW_clone_max_incr) allowance = CFLOW_clone_max_incr;
07127
07128 if (CFLOW_Trace_Clone) {
07129 #pragma mips_frequency_hint NEVER
07130 fprintf(TFile, "\ninstruction allowance=%d (%d%% of PU size %d is %d)\n\n",
07131 allowance, CFLOW_clone_incr, pu_size,
07132 (pu_size * CFLOW_clone_incr + 99) / 100);
07133 }
07134
07135 changed = FALSE;
07136 for (cand = cands, i = 0; i < n_cand; cand = cand->next, ++i) {
07137 INT cost;
07138 BB *pred = cand->pred;
07139 BB *suc = BBINFO_succ_bb(pred, 0);
07140
07141 #ifdef TARG_IA64
07142 if(RGN_Formed && Home_Region(pred) != Home_Region(suc) &&
07143 BB_succs_len(suc) > 2)
07144 cost = CFLOW_clone_max_incr;
07145 else {
07146 cost = BB_Has_One_Pred(suc) ? 0 : Estimate_BB_Length(suc);
07147 cost -= (BB_next(pred) != suc);
07148 }
07149 #else
07150 cost = BB_Has_One_Pred(suc) ? 0 : Estimate_BB_Length(suc);
07151 cost -= (BB_next(pred) != suc);
07152 #endif
07153
07154 if (cost <= allowance) {
07155 Append_Succ(pred, suc, in_cgprep, BB_Has_One_Pred(suc));
07156 changed = TRUE;
07157 if (CFLOW_Trace_Clone) {
07158 #pragma mips_frequency_hint NEVER
07159 fprintf(TFile, "appended BB:%d to BB:%d\n", BB_id(suc), BB_id(pred));
07160 }
07161
07162
07163
07164
07165 if (!BB_preds(suc)) {
07166 Delete_BB(suc, CFLOW_Trace_Clone);
07167 }
07168
07169 allowance -= cost;
07170 total_inst_incr += cost;
07171 }
07172 }
07173
07174 if (changed && CFLOW_Trace_Clone) {
07175 #pragma mips_frequency_hint NEVER
07176 fprintf(TFile, "\ncloning added %d instruction%s (%3.2f%% of PU size %d)\n",
07177 total_inst_incr,
07178 total_inst_incr == 1 ? "" : "s",
07179 (total_inst_incr * 100.0F) / pu_size,
07180 pu_size);
07181 }
07182
07183 return changed;
07184 }
07185
07186 #ifdef TARG_IA64
07187 static void
07188 Adjust_Branch_Hint(void)
07189 {
07190 BB *bp;
07191 BB *next;
07192 for (bp = REGION_First_BB; bp; bp = next) {
07193 TN *enum_tn;
07194 OP *br_op;
07195 float fall_through_prob,target_prob;
07196 BB *fall_through;
07197 BB *target;
07198 next = BB_next(bp);
07199 br_op = BB_xfer_op(bp);
07200 if (br_op != NULL) {
07201 switch (OP_code(br_op)) {
07202 case TOP_br_cond:
07203 case TOP_br_r_cond:
07204 fall_through = BBINFO_succ_bb(bp, 1);
07205 fall_through_prob = BBINFO_succ_prob(bp, 1);
07206 target = BBINFO_succ_bb(bp, 0);
07207 target_prob = BBINFO_succ_prob(bp, 0);
07208 if (fall_through_prob > target_prob) {
07209 enum_tn = Gen_Enum_TN(ECV_bwh_dpnt);
07210 } else {
07211 enum_tn = Gen_Enum_TN(ECV_bwh_dptk);
07212 }
07213 Set_OP_opnd(br_op, 1, enum_tn);
07214 break;
07215 default:
07216 break;
07217 }
07218 }
07219 }
07220 }
07221
07222 #endif
07223
07224
07225
07226
07227
07228
07229
07230
07231
07232
07233
07234
07235
07236
07237
07238
07239
07240
07241
07242 void
07243 CFLOW_Optimize(INT32 flags, const char *phase_name)
07244 {
07245 BOOL change;
07246 const char *prev_phase;
07247 BOOL flow_change = FALSE;
07248
07249 if (!CFLOW_Enable) return;
07250
07251
07252
07253 if (phase_name == NULL || *phase_name == '\0') phase_name = "CFLOW";
07254 prev_phase = Get_Error_Phase();
07255 Set_Error_Phase(phase_name);
07256 Start_Timer(T_CFLOW_CU);
07257
07258
07259
07260 current_flags = flags & ~disabled_flags;
07261 #if defined(TARG_SL)
07262 if(((current_flags & CFLOW_COLD_REGION) && CFLOW_cold_threshold))
07263 current_flags |= CFLOW_FREQ_ORDER;
07264 #endif
07265
07266 if (CFLOW_Trace) {
07267 #pragma mips_frequency_hint NEVER
07268 fprintf(TFile, "\n%s"
07269 " %s -- before optimization\n"
07270 "(PU \"%s\")\n"
07271 "%s",
07272 DBar, phase_name, Cur_PU_Name, DBar);
07273
07274 fprintf(TFile, "\nFlags for current invocation: 0x%08x\n", current_flags);
07275 fprintf(TFile, " unreachable block removal:\t%s\n",
07276 (current_flags & CFLOW_UNREACHABLE) ? "enabled" : "disabled");
07277 fprintf(TFile, " branch optimization:\t\t%s\n",
07278 (current_flags & CFLOW_BRANCH) ? "enabled" : "disabled");
07279 fprintf(TFile, " block merging:\t\t%s\n",
07280 (current_flags & CFLOW_MERGE) ? "enabled" : "disabled");
07281 fprintf(TFile, " block reordering:\t\t%s\n",
07282 (current_flags & CFLOW_REORDER) ? "enabled" : "disabled");
07283 fprintf(TFile, " freq-based block reordering:\t%s\n",
07284 (current_flags & CFLOW_FREQ_ORDER) ? "enabled" : "disabled");
07285 fprintf(TFile, " block cloning:\t\t%s\n",
07286 (current_flags & CFLOW_CLONE) ? "enabled" : "disabled");
07287 fprintf(TFile, " optimize all br to bcond:\t%s\n",
07288 (current_flags & CFLOW_OPT_ALL_BR_TO_BCOND) ? "enabled" : "disabled");
07289 fprintf(TFile, " fill delay slots:\t\t%s\n",
07290 (current_flags & CFLOW_FILL_DELAY_SLOTS) ? "enabled" : "disabled");
07291 #if defined (TARG_SL)
07292 fprintf(TFile, " cold region:\t\t%s\n",
07293 (current_flags & CFLOW_COLD_REGION) ? "enabled" : "disabled");
07294 #endif
07295
07296 fprintf(TFile, "\n");
07297 Print_All_BBs();
07298 }
07299
07300
07301
07302 if (current_flags == 0) goto nothing;
07303
07304
07305
07306 freqs_computed = FREQ_Frequencies_Computed();
07307
07308
07309
07310 listvar_counts = NULL;
07311 deleted_bbs = NULL;
07312 eh_label_removed = FALSE;
07313
07314
07315
07316 MEM_POOL_Push(&MEM_local_nz_pool);
07317
07318
07319
07320 if (!Initialize_BB_Info()) goto done;
07321
07322
07323 Setup_HB_bb_map();
07324
07325 #if 0
07326
07327
07328 if ( PROC_has_branch_delay_slot()
07329 && current_flags & CFLOW_FILL_DELAY_SLOTS)
07330 {
07331 flow_change |= Normalize_Delay_Slots();
07332 }
07333 #endif
07334
07335 if (CFLOW_Trace_Detail) {
07336 #pragma mips_frequency_hint NEVER
07337 Print_Cflow_Graph("CFLOW_Optimize flow graph -- before optimization");
07338 }
07339
07340 if (current_flags & CFLOW_BRANCH) {
07341 if (CFLOW_Trace_Branch) {
07342 #pragma mips_frequency_hint NEVER
07343 fprintf(TFile, "\n%s CFLOW_Optimize: optimizing branches\n%s",
07344 DBar, DBar);
07345 }
07346 change = Optimize_Branches();
07347 if (CFLOW_Trace_Branch) {
07348 #pragma mips_frequency_hint NEVER
07349 if (change) {
07350 Print_Cflow_Graph("CFLOW_Optimize flow graph -- after optimizing branches");
07351 } else {
07352 fprintf(TFile, "No changes.\n");
07353 }
07354 }
07355 flow_change |= change;
07356 }
07357
07358 if (current_flags & CFLOW_UNREACHABLE) {
07359 if (CFLOW_Trace_Unreach) {
07360 #pragma mips_frequency_hint NEVER
07361 fprintf(TFile, "\n%s CFLOW_Optimize: delete unreachable blocks\n%s",
07362 DBar, DBar);
07363 }
07364 change = Delete_Unreachable_Blocks();
07365 if (CFLOW_Trace_Unreach) {
07366 #pragma mips_frequency_hint NEVER
07367 if (change) {
07368 Print_Cflow_Graph("CFLOW_Optimize flow graph -- after deleting unreachable blocks");
07369 } else {
07370 fprintf(TFile, "No changes.\n");
07371 }
07372 }
07373 flow_change |= change;
07374 }
07375
07376 if (current_flags & CFLOW_REORDER) {
07377 if (CFLOW_Trace_Reorder) {
07378 #pragma mips_frequency_hint NEVER
07379 fprintf(TFile, "\n%s CFLOW_Optimize: reorder blocks\n%s",
07380 DBar, DBar);
07381 Print_Fall_Thrus("before Reorder_Blocks");
07382 }
07383 change = Reorder_Blocks();
07384
07385 if (CFLOW_Trace_Reorder) {
07386 #pragma mips_frequency_hint NEVER
07387 if (change) {
07388 Print_Fall_Thrus("after Reorder_Blocks");
07389 Print_Cflow_Graph("CFLOW_Optimize flow graph -- after reordering blocks");
07390 } else {
07391 fprintf(TFile, "No changes.\n");
07392 }
07393 }
07394 flow_change |= change;
07395 }
07396
07397 if ((current_flags & CFLOW_FREQ_ORDER) && freqs_computed) {
07398 if (CFLOW_Trace_Freq_Order) {
07399 #pragma mips_frequency_hint NEVER
07400 fprintf(TFile, "\n%s CFLOW_Optimize: frequency-guided reordering of blocks\n%s",
07401 DBar, DBar);
07402 }
07403 change = Freq_Order_Blocks();
07404
07405 if (CFLOW_Trace_Freq_Order) {
07406 #pragma mips_frequency_hint NEVER
07407 if (change) {
07408 Print_Cflow_Graph("CFLOW_Optimize flow graph -- after frequency-guided reordering blocks");
07409 } else {
07410 fprintf(TFile, "No changes.\n");
07411 }
07412 }
07413 flow_change |= change;
07414 }
07415
07416 if (current_flags & CFLOW_MERGE) {
07417 if (CFLOW_Trace_Merge) {
07418 #pragma mips_frequency_hint NEVER
07419 fprintf(TFile, "\n%s CFLOW_Optimize: merge blocks\n%s",
07420 DBar, DBar);
07421 }
07422 change = Merge_Blocks(current_flags & CFLOW_IN_CGPREP);
07423
07424 if (CFLOW_Trace_Merge) {
07425 #pragma mips_frequency_hint NEVER
07426 if (change) {
07427 Print_Cflow_Graph("CFLOW_Optimize flow graph -- after merging blocks");
07428 } else {
07429 fprintf(TFile, "No changes.\n");
07430 }
07431 }
07432 flow_change |= change;
07433 }
07434
07435 if (freqs_computed && (current_flags & CFLOW_CLONE)) {
07436 if (CFLOW_Trace_Clone) {
07437 #pragma mips_frequency_hint NEVER
07438 fprintf(TFile, "\n%s CFLOW_Optimize: clone blocks\n%s",
07439 DBar, DBar);
07440 }
07441 change = Clone_Blocks(current_flags & CFLOW_IN_CGPREP);
07442
07443 if (CFLOW_Trace_Clone) {
07444 #pragma mips_frequency_hint NEVER
07445 if (change) {
07446 Print_Cflow_Graph("CFLOW_Optimize flow graph -- after cloning blocks");
07447 } else {
07448 fprintf(TFile, "No changes.\n");
07449 }
07450 }
07451 flow_change |= change;
07452 }
07453
07454
07455
07456 if (flow_change) Finalize_All_BBs();
07457
07458 #ifdef TARG_IA64
07459 if (strcmp(phase_name,"CFLOW (third pass)") == 0) {
07460 Adjust_Branch_Hint();
07461 }
07462 #endif
07463 if (CFLOW_Trace) {
07464 #pragma mips_frequency_hint NEVER
07465 fprintf(TFile, "\n%s"
07466 " %s -- after optimization\n"
07467 "(PU \"%s\")\n"
07468 "%s\n",
07469 DBar, phase_name, Cur_PU_Name, DBar);
07470 if (flow_change) {
07471 Print_All_BBs();
07472 } else {
07473 fprintf(TFile, "No changes.\n");
07474 }
07475 }
07476
07477 done:
07478 BB_MAP_Delete(bb_info_map);
07479 MEM_POOL_Pop(&MEM_local_nz_pool);
07480
07481 nothing:
07482 Check_for_Dump(TP_FLOWOPT, NULL);
07483 Stop_Timer(T_CFLOW_CU);
07484 Set_Error_Phase(prev_phase);
07485 }
07486
07487
07488
07489
07490
07491
07492
07493
07494
07495
07496 void
07497 CFLOW_Initialize(void)
07498 {
07499 INT32 flags;
07500 INT32 idummy;
07501 INT32 fixed, taken;
07502 double ddummy;
07503
07504 CGTARG_Compute_Branch_Parameters(&idummy, &fixed, &taken, &ddummy);
07505 br_taken_cost = fixed + taken;
07506 br_fall_cost = fixed;
07507
07508 #ifdef TARG_MIPS
07509
07510
07511
07512
07513
07514
07515
07516 if (OPT_Space || !CG_PU_Has_Feedback)
07517 {
07518 br_static_cost = 1e+07;
07519 if (OPT_Space)
07520 heuristic_tolerance = 1.0;
07521 }
07522 else
07523 {
07524 br_static_cost = 100;
07525 }
07526 #else
07527 br_static_cost = 0;
07528 #endif
07529
07530 if (Get_Trace(TP_FLOWOPT, 0xffffffff)) {
07531 #pragma mips_frequency_hint NEVER
07532 CFLOW_Trace = Get_Trace(TP_FLOWOPT, TRACE_CFLOW);
07533 CFLOW_Trace_Detail = Get_Trace(TP_FLOWOPT, TRACE_DETAIL);
07534 CFLOW_Trace_Reorder = Get_Trace(TP_FLOWOPT, TRACE_REORDER);
07535 CFLOW_Trace_Branch = Get_Trace(TP_FLOWOPT, TRACE_BRANCH);
07536 CFLOW_Trace_Unreach = Get_Trace(TP_FLOWOPT, TRACE_UNREACH);
07537 CFLOW_Trace_Merge = Get_Trace(TP_FLOWOPT, TRACE_MERGE);
07538 CFLOW_Trace_Clone = Get_Trace(TP_FLOWOPT, TRACE_CLONE);
07539 CFLOW_Trace_Freq_Order = Get_Trace(TP_FLOWOPT, TRACE_FREQ_ORDER);
07540 CFLOW_Trace_Freq = Get_Trace(TP_FLOWOPT, TRACE_FREQ);
07541 CFLOW_Trace_Dom = Get_Trace(TP_FLOWOPT, TRACE_DOM);
07542 #ifdef TARG_IA64
07543 CFLOW_Trace_Empty_BB_Elim = Get_Trace(TP_FLOWOPT, TRACE_Empty_BB_Elim);
07544 #endif
07545
07546 CFLOW_Trace_Branch |= CFLOW_Trace_Detail;
07547 CFLOW_Trace_Unreach |= CFLOW_Trace_Detail;
07548 CFLOW_Trace_Merge |= CFLOW_Trace_Detail;
07549 CFLOW_Trace_Reorder |= CFLOW_Trace_Detail;
07550 CFLOW_Trace_Clone |= CFLOW_Trace_Detail;
07551 CFLOW_Trace_Freq_Order |= CFLOW_Trace_Detail;
07552 #ifdef TARG_IA64
07553 CFLOW_Trace_Empty_BB_Elim |= CFLOW_Trace_Detail;
07554 #endif
07555 }
07556
07557 if (CFLOW_heuristic_tolerance && CFLOW_heuristic_tolerance[0] != '\0') {
07558 double d = atof(CFLOW_heuristic_tolerance);
07559 if (d >= 0.0 && d <= 1.0) {
07560 heuristic_tolerance = d;
07561 } else {
07562 DevWarn("cflow heuristic tolerance (%s) must be between 0 and 1",
07563 CFLOW_heuristic_tolerance);
07564 }
07565 }
07566
07567 if (CFLOW_feedback_tolerance && CFLOW_feedback_tolerance[0] != '\0') {
07568 double d = atof(CFLOW_feedback_tolerance);
07569 if (d >= 0.0 && d <= 1.0) {
07570 feedback_tolerance = d;
07571 } else {
07572 DevWarn("cflow feedback tolerance (%s) must be between 0 and 1",
07573 CFLOW_feedback_tolerance);
07574 }
07575 }
07576
07577 if (CFLOW_cold_threshold && CFLOW_cold_threshold[0] != '\0') {
07578 double d = atof(CFLOW_cold_threshold);
07579 if (d >= 0.0) {
07580 cold_threshold = d;
07581 } else {
07582 DevWarn("cflow cold region threshold (%s) must be non-negative",
07583 CFLOW_cold_threshold);
07584 }
07585 } else {
07586 cold_threshold = Gen_PIC_Shared ? 0.005 : 0.01;
07587 }
07588
07589 flags = 0;
07590 if (!CFLOW_Enable_Unreachable) flags |= CFLOW_UNREACHABLE;
07591 if (!CFLOW_Enable_Branch) flags |= CFLOW_BRANCH;
07592 if (!CFLOW_Enable_Merge) flags |= CFLOW_MERGE;
07593 if (!CFLOW_Enable_Reorder) flags |= CFLOW_REORDER;
07594 if (!CFLOW_Enable_Clone) flags |= CFLOW_CLONE;
07595 if (!CFLOW_Enable_Freq_Order) flags |= CFLOW_FREQ_ORDER;
07596 if (!CFLOW_opt_all_br_to_bcond) flags |= CFLOW_OPT_ALL_BR_TO_BCOND;
07597 disabled_flags = flags;
07598 }
07599
07600 #ifdef TARG_IA64
07601 void
07602 CFLOW_Process(void)
07603 {BB *bp;
07604 for (bp = REGION_First_BB; bp; bp = BB_next(bp)) {
07605
07606 if (IPFEC_Enable_Region_Formation && RGN_Formed) {
07607 if(Home_Region(bp)->Is_No_Further_Opt())
07608 continue;
07609 }
07610 if (BB_length(bp)==0){
07611 BBLIST *list;
07612 if (BB_preds_len(bp)==1){
07613 list=BB_preds(bp);
07614 BB *pred=BBLIST_item(list);
07615 BBLIST *lists;
07616
07617 for (lists = BB_succs(bp); lists != NULL;) {
07618 BB *succ = BBLIST_item(lists);
07619 lists = BBLIST_next(lists);
07620 BBLIST *blsucc = BB_Find_Succ(bp, succ);
07621 float prob=BBLIST_prob(blsucc);
07622 RGN_Link_Pred_Succ_With_Prob(pred,succ,prob);
07623 RGN_Unlink_Pred_Succ(bp,succ);
07624 }
07625 RGN_Unlink_Pred_Succ(pred,bp);
07626 }else if (BB_succs_len(bp)==1){
07627 list=BB_succs(bp);
07628 BB *succ=BBLIST_item(list);
07629 BBLIST *lists;
07630
07631 for (lists = BB_preds(bp); lists != NULL;) {
07632 BB *pred = BBLIST_item(lists);
07633 lists = BBLIST_next(lists);
07634 BBLIST *blsucc = BB_Find_Succ(pred,bp);
07635 float prob=BBLIST_prob(blsucc);
07636 RGN_Link_Pred_Succ_With_Prob(pred,succ,prob);
07637 RGN_Unlink_Pred_Succ(pred,bp);
07638 }
07639 RGN_Unlink_Pred_Succ(bp,succ);
07640 }
07641 }
07642 }
07643 for (bp = REGION_First_BB; bp; bp = BB_next(bp)) {
07644
07645 if (IPFEC_Enable_Region_Formation && RGN_Formed) {
07646 if(Home_Region(bp)->Is_No_Further_Opt())
07647 continue;
07648 }
07649 if (BB_length(bp)==1 && BB_xfer_op(bp)){
07650 BBLIST *list;
07651 OP *op=BB_xfer_op(bp);
07652 if (OP_opnd(op,0)==True_TN && !(BB_has_label(bp))){
07653 if (BB_succs_len(bp)>1) Is_True(bp,("br BB has 2 succ"));
07654 if (BB_succs_len(bp)==1){
07655 list=BB_succs(bp);
07656 BB *succ=BBLIST_item(list);
07657 BBLIST *lists;
07658
07659 for (lists = BB_preds(bp); lists != NULL;) {
07660 BB *pred = BBLIST_item(lists);
07661 lists = BBLIST_next(lists);
07662 BBLIST *blsucc = BB_Find_Succ(pred,bp);
07663 float prob=BBLIST_prob(blsucc);
07664 RGN_Link_Pred_Succ_With_Prob(pred,succ,prob);
07665 RGN_Unlink_Pred_Succ(pred,bp);
07666 }
07667 RGN_Unlink_Pred_Succ(bp,succ);
07668 }
07669 }
07670 }
07671 }
07672 }
07673
07674
07675
07676
07677
07678
07679
07680
07681
07682
07683
07684
07685
07686 static BOOL
07687 Initialize_BB_Info_For_Delete(void)
07688 {
07689 BB *bb;
07690
07691 bb_info_map = BB_MAP_Create();
07692 for (bb = REGION_First_BB; bb; bb = BB_next(bb)) {
07693 BBINFO *bbinfo;
07694 INT bbinfo_size;
07695 BBKIND bbkind = BB_kind(bb);
07696
07697
07698 if (bbkind == BBKIND_UNKNOWN) {
07699 if (BB_Last_chk_op(bb)) {
07700 bbkind = BBKIND_LOGIF;
07701 }
07702 }
07703
07704
07705 bbinfo_size = sizeof(BBINFO);
07706 bbinfo = (BBINFO *)MEM_POOL_Alloc(&MEM_local_nz_pool, bbinfo_size);
07707 BB_MAP_Set(bb_info_map, bb, bbinfo);
07708
07709 bbinfo->kind = bbkind;
07710
07711 switch (bbkind) {
07712 case BBKIND_GOTO:
07713 bbinfo->nsuccs = BB_succs(bb) ? 1 : 0;
07714 if (BB_succs(bb)) {
07715 TN *lab_tn;
07716 BB *target = BBLIST_item(BB_succs(bb));
07717
07718 bbinfo->succs[0].bb = target;
07719 bbinfo->succs[0].offset = 0;
07720 bbinfo->succs[0].prob = 1.0;
07721 }
07722 continue;
07723
07724 case BBKIND_LOGIF:
07725 case BBKIND_CHK:
07726 {
07727 INT tfirst;
07728 INT tcount;
07729 TN *lab_tn;
07730 BB *target;
07731 BBLIST *target_edge;
07732 BBLIST *fall_through_edge;
07733 OP *br = BB_branch_op(bb);
07734 if ((br == NULL)|| (OP_noop(br)) )
07735 {
07736 br = BB_Last_chk_op(bb);
07737 }
07738
07739
07740
07741 target_edge = BB_succs(bb);
07742 fall_through_edge = BBLIST_next(target_edge);
07743 target = BBLIST_item(target_edge);
07744 if (fall_through_edge == NULL) {
07745 fall_through_edge = target_edge;
07746 } else if (target == BB_next(bb)) {
07747 target_edge = fall_through_edge;
07748 fall_through_edge = BB_succs(bb);
07749 target = BBLIST_item(target_edge);
07750 }
07751
07752 bbinfo->nsuccs = 2;
07753
07754 bbinfo->succs[0].bb = target;
07755 bbinfo->succs[0].offset = 0;
07756 bbinfo->succs[0].prob = BBLIST_prob(target_edge);
07757
07758 bbinfo->succs[1].bb = BB_next(bb);
07759 bbinfo->succs[1].offset = 0;
07760 bbinfo->succs[1].prob = BBLIST_prob(fall_through_edge);
07761
07762 CGTARG_Branch_Info(br, &tfirst, &tcount);
07763 Is_True(tcount == 1, ("unexpected number of branch targets in BB:%d",
07764 BB_id(bb)));
07765 lab_tn = OP_opnd(br, tfirst);
07766 continue;
07767 }
07768
07769 }
07770
07771 }
07772
07773 return TRUE;
07774 }
07775
07776
07777
07778
07779
07780
07781
07782
07783
07784
07785
07786
07787
07788 void
07789 CFLOW_Delete_Empty_BB(void)
07790 {
07791 BB *bp ,*tgt_succ;
07792 BB *left_tgt, *right_tgt;
07793 INT tgt_num;
07794 LABEL_IDX tgt_label;
07795 float prob;
07796 BB *next_bb;
07797 MEM_POOL_Push(&MEM_local_nz_pool);
07798 if (!Initialize_BB_Info_For_Delete()) {
07799 BB_MAP_Delete(bb_info_map);
07800 MEM_POOL_Pop(&MEM_local_nz_pool);
07801 return;
07802 }
07803 for (bp = REGION_First_BB ; bp!=NULL ; bp= next_bb) {
07804 next_bb =BB_next(bp) ;
07805 if ( BBINFO_kind(bp) == BBKIND_GOTO && !BB_length(bp) ) {
07806 BBLIST *prev_bbs, *next_bbs;
07807 BB *prev_bb;
07808 BOOL can_do ;
07809 LABEL_IDX old_label, tgt_lable;
07810
07811
07812
07813
07814
07815 if (BB_Has_Exc_Label(bp)
07816 || BB_Has_Addr_Taken_Label(bp)
07817 || BB_Has_Outer_Block_Label(bp))
07818 continue;
07819
07820
07821
07822
07823
07824
07825 if (BBINFO_nsuccs(bp) == 0 && next_bb == NULL) {
07826 BOOL is_removeable = TRUE;
07827 for ( prev_bbs = BB_preds(bp); prev_bbs != NULL; prev_bbs = next_bbs) {
07828 next_bbs = BBLIST_next(prev_bbs);
07829 BB *prev_bb = BBLIST_item(prev_bbs);
07830 switch BBINFO_kind(prev_bb) {
07831 case BBKIND_GOTO :
07832 case BBKIND_LOGIF:
07833 is_removeable = FALSE;
07834 break;
07835
07836 default:
07837 continue;
07838 }
07839 }
07840 if (is_removeable) {
07841 Delete_BB(bp, CFLOW_Trace_Empty_BB_Elim);
07842 }
07843 continue;
07844 }
07845
07846 Is_True (BBINFO_nsuccs(bp), ("GOTO BB: %d has no succ bb", BB_id(bp)));
07847 Is_True (BBINFO_succ_bb(bp, 0) != bp, ("GOTO BB: %d is a loop~!", BB_id(bp)));
07848
07849 old_label = Gen_Label_For_BB(bp);
07850 tgt_succ = BBINFO_succ_bb(bp, 0);
07851
07852
07853
07854
07855 tgt_label = Gen_Label_For_BB(tgt_succ);
07856 if (CFLOW_Trace_Empty_BB_Elim) {
07857 fprintf(TFile, "The label %s of empty BB: %d will be copied "
07858 "to BB labeled with %s\n", LABEL_name(old_label),
07859 BB_id(bp), LABEL_name(tgt_label));
07860 }
07861
07862
07863 for ( prev_bbs = BB_preds(bp); prev_bbs != NULL; prev_bbs = next_bbs ) {
07864 can_do = TRUE;
07865 next_bbs = BBLIST_next(prev_bbs);
07866 BB *prev_bb = BBLIST_item(prev_bbs) ;
07867
07868 switch BBINFO_kind(prev_bb) {
07869
07870 case BBKIND_GOTO :
07871 tgt_num = 0;
07872 break;
07873
07874 case BBKIND_LOGIF:
07875 if ((left_tgt = BBINFO_succ_bb(prev_bb, 0)) == bp) {
07876 tgt_num = 0;
07877 }
07878 if ((right_tgt = BBINFO_succ_bb(prev_bb, 1)) == bp) {
07879 tgt_num = 1;
07880 }
07881 break;
07882
07883
07884 default:
07885
07886 can_do = FALSE;
07887 continue;
07888
07889 }
07890
07891
07892
07893
07894 if (can_do) {
07895
07896
07897
07898
07899
07900
07901 prob = BBINFO_succ_prob(prev_bb,tgt_num);
07902 Unlink_Pred_Succ(prev_bb, bp);
07903 Link_Pred_Succ_with_Prob(prev_bb, tgt_succ, prob, FALSE, TRUE);
07904 }
07905 }
07906
07907
07908
07909 BB_Copy_All_Annotations (tgt_succ, bp);
07910 Delete_BB(bp, CFLOW_Trace_Empty_BB_Elim);
07911 }
07912 }
07913 BB_MAP_Delete(bb_info_map);
07914 MEM_POOL_Pop(&MEM_local_nz_pool);
07915 }
07916 #endif
07917
07918 #if defined(KEY) && (defined(TARG_MIPS) && !defined(TARG_SL))
07919
07920
07921
07922
07923 static void
07924 Build_Long_Goto(BB *targ_bb, OPS *ops)
07925 {
07926
07927
07928
07929
07930
07931
07932
07933
07934 TN *tmp_reg = Build_Dedicated_TN(ISA_REGISTER_CLASS_integer, 3, 8);
07935 LABEL_IDX label_idx = Gen_Label_For_BB(targ_bb);
07936
07937
07938
07939 ST *st = New_ST(CURRENT_SYMTAB);
07940 ST_Init(st, Save_Str(LABEL_name(label_idx)), CLASS_NAME,
07941 SCLASS_UNKNOWN, EXPORT_LOCAL, MTYPE_To_TY(Pointer_Mtype));
07942
07943 Build_OP(TOP_daddiu, SP_TN, SP_TN, Gen_Literal_TN(-8, 0), ops);
07944 Build_OP(TOP_sd, tmp_reg, SP_TN, Gen_Literal_TN(0, 0), ops);
07945
07946 if (MTYPE_byte_size(Pointer_Mtype) == 8) {
07947
07948
07949 TN *target_tn = Gen_Symbol_TN(st, 0, TN_RELOC_GOT_DISP);
07950 Build_OP(TOP_ld, tmp_reg, GP_TN, target_tn, ops);
07951 } else {
07952 TN *target_hi_tn = Gen_Symbol_TN(st, 0, TN_RELOC_HIGH16);
07953 TN *target_lo_tn = Gen_Symbol_TN(st, 0, TN_RELOC_LOW16);
07954 Build_OP(TOP_lui, tmp_reg, target_hi_tn, ops);
07955 Build_OP(TOP_addiu, tmp_reg, tmp_reg, target_lo_tn, ops);
07956 }
07957
07958 Build_OP(TOP_daddiu, SP_TN, SP_TN, Gen_Literal_TN(8, 0), ops);
07959 Build_OP(TOP_jr, tmp_reg, ops);
07960 Build_OP(TOP_ld, tmp_reg, SP_TN, Gen_Literal_TN(-8, 0), ops);
07961 }
07962
07963
07964
07965
07966 void
07967 CFLOW_Fixup_Long_Branches()
07968 {
07969 BB *bb;
07970 UINT32 *bb_position, ops_count;
07971 BB_NUM old_PU_BB_Count = PU_BB_Count;
07972
07973
07974
07975 int size = (PU_BB_Count + 1) * sizeof(UINT32);
07976 bb_position = (UINT32 *) alloca(size);
07977 memset(bb_position, 0, size);
07978 ops_count = 0;
07979 for (bb = REGION_First_BB; bb; bb = BB_next(bb)) {
07980 Is_True(BB_id(bb) <= PU_BB_Count, ("CFLOW_Fixup_Long_Branches: bad BB id"));
07981 bb_position[BB_id(bb)] = ops_count;
07982 ops_count += BB_length(bb);
07983 }
07984
07985
07986 for (bb = REGION_First_BB; bb; bb = BB_next(bb)) {
07987
07988 if (BB_id(bb) > old_PU_BB_Count)
07989 continue;
07990
07991
07992
07993 if (!BB_succs(bb))
07994 continue;
07995
07996
07997
07998 BBKIND bb_kind = BB_kind(bb);
07999 if (bb_kind == BBKIND_GOTO ||
08000 bb_kind == BBKIND_LOGIF) {
08001
08002 UINT32 branch_position =
08003 bb_position[BB_id(BB_next(bb) ? BB_next(bb) : bb)];
08004
08005
08006 BB *succ0 = BBLIST_item(BB_succs(bb));
08007 BB *succ1 = NULL;
08008 BB *targ_bb = NULL;
08009 BB *old_fall_thru_bb = NULL;
08010
08011
08012 if (bb_kind == BBKIND_GOTO) {
08013 targ_bb = succ0;
08014 } else {
08015 if (BBLIST_next(BB_succs(bb)) == NULL)
08016 continue;
08017 succ1 = BBLIST_item(BBLIST_next(BB_succs(bb)));
08018 if (BB_next(bb) == succ0) {
08019 targ_bb = succ1;
08020 old_fall_thru_bb = succ0;
08021 } else {
08022 targ_bb = succ0;
08023 old_fall_thru_bb = succ1;
08024 }
08025
08026 Is_True(old_fall_thru_bb == BB_next(bb),
08027 ("CFLOW_Fixup_Long_Branches: fall thru BB is not the next BB"));
08028 }
08029
08030 UINT32 targ_position = bb_position[BB_id(targ_bb)];
08031
08032
08033 INT64 disp = (INT64) targ_position - (INT64) branch_position;
08034 disp *= 4;
08035
08036 #if defined(TARG_SL) || !defined(TARG_MIPS)
08037 if (CG_hw_round > 0 || CG_hw_stall > 0) {
08038 disp = (INT64) (disp * 1.2);
08039 } else {
08040 disp = (INT64) (disp * 1.1);
08041 }
08042 #endif
08043
08044 if (!CGTARG_Can_Fit_Displacement_In_Branch_Instruction(disp)) {
08045 if (bb_kind == BBKIND_GOTO) {
08046 OPS ops = OPS_EMPTY;
08047 OP *branch_op = BB_branch_op(bb);
08048 OP *next_op = OP_next(branch_op);
08049
08050 if (next_op &&
08051 OP_code(next_op) == TOP_nop) {
08052 BB_Remove_Op(bb, next_op);
08053 }
08054 BB_Remove_Op(bb, branch_op);
08055 Build_Long_Goto(targ_bb, &ops);
08056 BB_Append_Ops(bb, &ops);
08057
08058 if (!CG_localize_tns) {
08059 GRA_LIVE_Compute_Liveness_For_BB(bb);
08060 }
08061 } else {
08062
08063
08064 OPS ops = OPS_EMPTY;
08065 BBLIST *sedge = BB_Find_Succ(bb, targ_bb);
08066 float goto_prob = BBLIST_prob(sedge);
08067 BOOL goto_prob_fb = BBLIST_prob_fb_based(sedge);
08068 RID *rid = BB_rid(bb);
08069 BOOL region_is_scheduled = rid && RID_level(rid) >= RL_CGSCHED;
08070 BOOL fill_delay_slots = (current_flags & CFLOW_FILL_DELAY_SLOTS) != 0;
08071
08072 BB *goto_bb = Alloc_BB_Like(bb);
08073 BB_freq(goto_bb) = BB_freq(bb) * goto_prob;
08074 Insert_BB(goto_bb, bb);
08075 Build_Long_Goto(targ_bb, &ops);
08076
08077 if (BB_freq_fb_based(bb) && goto_prob_fb) {
08078 BBLIST *edge = BB_Find_Succ(goto_bb, targ_bb);
08079 Set_BB_freq_fb_based(goto_bb);
08080 Set_BBLIST_prob_fb_based(edge);
08081 }
08082
08083 if (PROC_has_branch_delay_slot()
08084 && (fill_delay_slots || region_is_scheduled)) {
08085 Set_BB_scheduled(goto_bb);
08086 }
08087 BB_Append_Ops(goto_bb, &ops);
08088
08089 Unlink_Pred_Succ(bb, targ_bb);
08090 Link_Pred_Succ_with_Prob(bb, goto_bb, goto_prob);
08091 if (goto_prob_fb) {
08092 BBLIST *edge = BB_Find_Succ(bb, goto_bb);
08093 Set_BBLIST_prob_fb_based(edge);
08094 }
08095
08096 INT tfirst;
08097 INT tcount;
08098 LABEL_IDX lab;
08099 TN *lab_tn;
08100 OP *branch_op = BB_branch_op(bb);
08101 CGTARG_Branch_Info(branch_op, &tfirst, &tcount);
08102 lab = Gen_Label_For_BB(old_fall_thru_bb);
08103 lab_tn = Gen_Label_TN(lab, 0);
08104 Set_OP_opnd(branch_op, tfirst, lab_tn);
08105 Negate_Logif_BB(bb);
08106
08107 if (PROC_has_branch_delay_slot()) {
08108
08109
08110
08111 OP *delay_op = OP_next(branch_op);
08112 if (delay_op != NULL && !OP_noop(delay_op) && OP_likely(branch_op)) {
08113 BB_Move_Op_To_Start(goto_bb, bb, delay_op);
08114 delay_op = NULL;
08115 }
08116
08117
08118
08119
08120
08121 if (delay_op == NULL && (fill_delay_slots || region_is_scheduled)) {
08122 OPS ops = OPS_EMPTY;
08123 Exp_Noop(&ops);
08124 Set_BB_scheduled(bb);
08125 BB_Append_Ops(bb, &ops);
08126 }
08127
08128 }
08129
08130 if (!CG_localize_tns) {
08131 GRA_LIVE_Compute_Liveness_For_BB(goto_bb);
08132 GRA_LIVE_Compute_Liveness_For_BB(bb);
08133 }
08134 }
08135 }
08136 }
08137 }
08138 }
08139
08140
08141 #endif // KEY and TARG_MIPS
08142