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 #include <math.h>
00041
00042 #include "defs.h"
00043 #include "config.h"
00044 #include "mempool.h"
00045 #include "tracing.h"
00046 #include "timing.h"
00047 #include "cgir.h"
00048 #include "cg.h"
00049 #include "cg_flags.h"
00050 #include "cgtarget.h"
00051 #include "ttype.h"
00052 #include "bitset.h"
00053 #include "bb_set.h"
00054 #include "freq.h"
00055 #include "whirl2ops.h"
00056 #include "dominate.h"
00057 #include "findloops.h"
00058 #include "cg_sched_est.h"
00059 #include "opt_points_to.h"
00060 #include "opt_alias_mgr.h"
00061
00062 #include "hb.h"
00063 #include "hb_path.h"
00064 #include "hb_trace.h"
00065
00066 static float call_hazard_multiplier;
00067 static float memory_hazard_multiplier;
00068 static float min_path_priority_ratio;
00069 static float base_probability_contribution;
00070 static float max_sched_growth;
00071 static float max_sched_growth_sf;
00072
00073 #define HB_MAX_PATHS 256
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089 static void
00090 Verify_HB(
00091 BB *bb,
00092 BB_SET **processed_bbs,
00093 BB_SET *hb_bbs)
00094 {
00095 BBLIST *edge;
00096 BB *last_succ = NULL;
00097 FOR_ALL_BB_SUCCS(bb, edge) {
00098 BB *succ = BBLIST_item(edge);
00099 if (BB_SET_MemberP(hb_bbs, succ)) {
00100 last_succ = succ;
00101 }
00102 }
00103 if (last_succ == NULL) {
00104 *processed_bbs = BS_Union1D(*processed_bbs, BB_id(bb), &MEM_HB_pool);
00105 return;
00106 }
00107
00108 FOR_ALL_BB_SUCCS(bb, edge) {
00109 BB *succ = BBLIST_item(edge);
00110 BOOL skip_succ = FALSE;
00111 if (BB_SET_MemberP(hb_bbs, succ)) {
00112 if (succ == last_succ) {
00113
00114
00115 *processed_bbs = BS_Union1D(*processed_bbs, BB_id(bb), &MEM_HB_pool);
00116 }
00117
00118
00119
00120 BBLIST *pbl;
00121 FOR_ALL_BB_PREDS(succ, pbl) {
00122 BB *pred = BBLIST_item(pbl);
00123 if (BB_SET_MemberP(hb_bbs, pred) &&
00124 (!((bb == pred)) &&
00125 !BB_SET_MemberP(*processed_bbs, pred))) {
00126 skip_succ = TRUE;
00127 break;
00128 }
00129 }
00130
00131 if (!skip_succ) Verify_HB(succ, processed_bbs, hb_bbs);
00132 }
00133 }
00134
00135 }
00136
00138 static BOOL
00139 Enumerate_Paths(HB* hb, BB* bb, float probability, std::list<HB_PATH*>& ret_list,
00140 BB *stopping_point, BB_SET *visited,
00141 MEM_POOL* pool)
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00162 {
00163 BB* succ;
00164 INT exit_count = 0;
00165 INT num_succ = 0;
00166 BBLIST* bl;
00167
00168 if (BB_SET_MemberP(visited, bb)) {
00169
00170 return FALSE;
00171 }
00172 visited = BB_SET_Union1D(visited, bb, pool);
00173
00174 if (bb != stopping_point) {
00175 FOR_ALL_BB_SUCCS(bb, bl) {
00176 succ = BBLIST_item(bl);
00177
00178
00179
00180
00181
00182 if (succ != HB_Entry(hb) && HB_Contains_Block(hb, succ)) {
00183 std::list<HB_PATH*> kids_paths;
00184 if (Enumerate_Paths(hb, succ, BBLIST_prob(bl), kids_paths, stopping_point, visited, pool)) {
00185 ret_list.splice(ret_list.end(), kids_paths);
00186
00187 if (ret_list.size() > HB_MAX_PATHS) {
00188 return FALSE;
00189 }
00190 } else {
00191
00192 return FALSE;
00193 }
00194 } else {
00195 exit_count++;
00196 }
00197 num_succ++;
00198 }
00199 }
00200
00201
00202 visited = BB_SET_Difference1D(visited,bb);
00203
00204
00205
00206
00207 if (exit_count > 0 || num_succ == 0) {
00208 HB_PATH* path = HB_PATH_Alloc(&MEM_local_pool);
00209 ret_list.push_front(path);
00210 }
00211
00212
00213
00214
00215
00216
00217 for(std::list<HB_PATH*>::iterator paths = ret_list.begin();
00218 paths != ret_list.end();
00219 paths++) {
00220 HB_PATH_Add_Block(*paths, bb, &MEM_local_pool);
00221 HB_PATH_Probability_Set(*paths,HB_PATH_Probability(*paths) * probability);
00222 }
00223
00224 return TRUE;
00225 }
00226
00228 static void
00229 Calculate_Path_Data(HB *hb, HB_PATH* path, BB_MAP bb_sched_est,
00230 BB_MAP bb_mem_hazard, INT& max_sched_height,
00231 INT* max_num_ops)
00233
00234
00235
00236
00237
00239 {
00240 BB* bb;
00241 INT num_ops = 0;
00242 INT num_cb_ops = 0;
00243 INT num_ucb_ops = 0;
00244
00245 BB_SET * entry_pdom_set = BB_pdom_set(HB_Entry(hb));
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257 FOR_ALL_BB_SET_members(HB_PATH_Blocks(path), bb) {
00258 INT mem_hazard = BB_MAP32_Get(bb_mem_hazard, bb);
00259
00260 if (!mem_hazard) {
00261
00262
00263
00264
00265
00266
00267
00268 mem_hazard = 1;
00269 for (OP* op = BB_first_op(bb); op != NULL; op = OP_next(op)) {
00270 if (OP_store(op)) {
00271 if (Alias_Manager) {
00272 WN* wn = Get_WN_From_Memory_OP(op);
00273 if (wn && Valid_alias(Alias_Manager, wn) &&
00274 Points_to(Alias_Manager, wn)->Base_kind() == BASE_IS_UNKNOWN) {
00275 mem_hazard = -1;
00276 }
00277 } else {
00278 mem_hazard = -1;
00279 }
00280 }
00281 if (OP_cond(op)) num_cb_ops++;
00282 else if (OP_uncond(op)) num_ucb_ops++;
00283 }
00284
00285 BB_MAP32_Set(bb_mem_hazard, bb, mem_hazard);
00286 }
00287
00288 num_ops += BB_length(bb);
00289
00290 if (!BB_SET_MemberP(entry_pdom_set,bb)) {
00291 if (BB_call(bb) &&
00292 call_hazard_multiplier < HB_PATH_Hazard_Multiplier(path)) {
00293 HB_PATH_Hazard_Multiplier_Set(path, call_hazard_multiplier);
00294 }
00295 if ((mem_hazard < 0) &&
00296 (memory_hazard_multiplier < HB_PATH_Hazard_Multiplier(path))) {
00297 HB_PATH_Hazard_Multiplier_Set(path, memory_hazard_multiplier);
00298 }
00299 }
00300 }
00301
00302 CG_SCHED_EST* est = CG_SCHED_EST_Path_Create(HB_PATH_Blocks(path),
00303 bb_sched_est,
00304 &MEM_local_pool,
00305 SCHED_EST_FOR_HB);
00306 HB_PATH_Sched_Est_Set(path, est);
00307
00308 if (num_ops > *max_num_ops) {
00309 *max_num_ops = num_ops;
00310 }
00311 if (HB_PATH_Schedule_Height(path) > max_sched_height) {
00312 max_sched_height = HB_PATH_Schedule_Height(path);
00313 }
00314
00315 HB_PATH_Num_Ops_Set(path, num_ops);
00316 HB_PATH_Num_CB_Ops_Set(path, num_cb_ops);
00317 HB_PATH_Num_UCB_Ops_Set(path, num_ucb_ops);
00318
00319 }
00320
00322 static void
00323 Calculate_Path_Priorities(std::list<HB_PATH*>& hb_paths, INT max_sched_height,
00324 INT* max_num_ops, BOOL profitable_ifc)
00326
00327
00328
00330 {
00331 std::list<HB_PATH*>::iterator hbp;
00332 float max_priority = 0.0;
00333 INT max_priority_sched_height = 0;
00334 double branch_cost, factor;
00335 INT32 branchfixed, mispredict, branchtaken;
00336
00337 CGTARG_Compute_Branch_Parameters(&mispredict, &branchfixed, &branchtaken, &factor);
00338
00339 for (hbp = hb_paths.begin(); hbp != hb_paths.end(); hbp++) {
00340 HB_PATH* path = *hbp;
00341 float sched_ratio;
00342 float op_ratio;
00343 float priority;
00344
00345
00346 branch_cost = HB_PATH_Probability(path) *
00347 ((HB_PATH_Num_CBranch_Ops(path) * mispredict)
00348 + ((HB_PATH_Num_CBranch_Ops(path) + HB_PATH_Num_UCBranch_Ops(path)) *
00349 branchfixed));
00350
00351 float cur_sched_height = (float) HB_PATH_Schedule_Height(path);
00352 cur_sched_height = cur_sched_height - branch_cost;
00353 if (cur_sched_height < 0) cur_sched_height = 0;
00354
00355 sched_ratio = 1.0 -
00356 (cur_sched_height / (float) max_sched_height);
00357 op_ratio = 1.0 - ((float) HB_PATH_Num_Ops(path) / (float) *max_num_ops);
00358 priority = (HB_PATH_Probability(path) * HB_PATH_Hazard_Multiplier(path)) *
00359 (sched_ratio + op_ratio + base_probability_contribution);
00360 HB_PATH_Priority_Set(path, priority);
00361 if (priority > max_priority) {
00362 max_priority_sched_height = HB_PATH_Schedule_Height(path);
00363 }
00364 }
00365
00366
00367
00368
00369
00370
00371
00372
00373 if (max_priority > 0.0 &&
00374 ((HB_static_freq_heuristics && !CG_PU_Has_Feedback) || profitable_ifc)) {
00375 for (hbp = hb_paths.begin(); hbp != hb_paths.end(); hbp++) {
00376 HB_PATH* path = *hbp;
00377 if (HB_PATH_Schedule_Height(path) != max_priority_sched_height) {
00378 float sched_ratio = (float) HB_PATH_Schedule_Height(path) /
00379 (float) max_priority_sched_height;
00380 float priority_multiplier = 1.0 - fabsf(1.0 - sched_ratio);
00381
00382 float new_priority = HB_PATH_Priority(path) * priority_multiplier;
00383 HB_PATH_Priority_Set(path, new_priority);
00384 }
00385 }
00386 }
00387
00388
00389
00390
00391 hb_paths.sort(HB_PATH_Priority_Compare());
00392 }
00393
00395 static INT
00396 Maximum_Sched_Height_Increase(HB_PATH* max_path, BOOL tolerate_increase)
00398
00399
00400
00401
00403 {
00404 INT sched_height = HB_PATH_Schedule_Height(max_path);
00405 if (tolerate_increase) {
00406 float f_sched_height = (float)sched_height;
00407 if (HB_static_freq_heuristics && !CG_PU_Has_Feedback) {
00408 return (INT)(f_sched_height * max_sched_growth_sf);
00409 }
00410 return (INT)(f_sched_height * max_sched_growth);
00411 }
00412 return sched_height;
00413 }
00414
00416 static BOOL
00417 Path_Resources_Available(HB* hb, HB_PATH* path, HB_PATH* max_path,
00418 CG_SCHED_EST* hb_est, BOOL tolerate_increase)
00420
00421
00422
00423
00424
00426 {
00427 CG_SCHED_EST* tmp_est;
00428 INT sum_cycles;
00429
00430 MEM_POOL_Push(&MEM_local_pool);
00431
00432 tmp_est = CG_SCHED_EST_Clone(hb_est, &MEM_local_pool);
00433 CG_SCHED_EST_Append_Scheds(tmp_est, HB_PATH_Sched_Est(path));
00434 sum_cycles = CG_SCHED_EST_Resource_Cycles(tmp_est);
00435 CG_SCHED_EST_Delete(tmp_est);
00436
00437 MEM_POOL_Pop(&MEM_local_pool);
00438
00439 if (sum_cycles > Maximum_Sched_Height_Increase(max_path,
00440 tolerate_increase)) {
00441 return FALSE;
00442 }
00443 return TRUE;
00444 }
00445
00446
00448 static BB_SET *
00449 Select_Blocks(HB* hb, std::list<HB_PATH*>& hb_paths, BOOL profitable_ifc)
00451
00452
00453
00454
00455
00457 {
00458 std::list<HB_PATH*>::iterator path;
00459 float last_priority;
00460 BB_MAP bb_sched_est = BB_MAP_Create();
00461 BB_MAP bb_mem_hazard = BB_MAP32_Create();
00462 INT max_sched_height = 0;
00463 INT max_num_ops = 0;
00464 HB_PATH* max_path;
00465 BB_SET* selected_blocks;
00466
00467 CG_SCHED_EST* hb_est = CG_SCHED_EST_Create_Empty(&MEM_local_pool,
00468 SCHED_EST_FOR_HB);
00469
00470
00471
00472 CG_SCHED_EST_use_locs = FALSE;
00473
00474
00475
00476
00477
00478 for (path = hb_paths.begin(); path != hb_paths.end(); path++) {
00479 Calculate_Path_Data(hb, *path, bb_sched_est, bb_mem_hazard,
00480 max_sched_height, &max_num_ops);
00481 }
00482
00483
00484
00485
00486
00487 Calculate_Path_Priorities(hb_paths, max_sched_height, &max_num_ops,
00488 profitable_ifc);
00489
00490
00491
00492
00493
00494 path = hb_paths.begin();
00495 max_path = *path;
00496 selected_blocks = NULL;
00497
00498 if (HB_PATH_Priority(max_path) < HB_minimum_priority) {
00499 if (HB_Trace(HB_TRACE_SELECT)) {
00500 fprintf(HB_TFile,
00501 "<HB> Hyperblock discarded. Max path priority too low:\n");
00502 HB_PATH_Trace(max_path);
00503 }
00504 } else if (HB_PATH_Num_Ops(max_path) > 2 * CG_maxinss) {
00505 if (HB_Trace(HB_TRACE_SELECT)) {
00506 fprintf(HB_TFile,
00507 "<HB> Hyperblock discarded. No. of instructions in hyperblock (%d) exceed 2 * CG_maxinss (%d) threshold :\n", HB_PATH_Num_Ops(max_path), 2 * CG_maxinss );
00508 HB_PATH_Trace(max_path);
00509 }
00510 }
00511 else {
00512 selected_blocks = BB_SET_Copy(HB_PATH_Blocks(max_path),&MEM_local_pool);
00513 last_priority = HB_PATH_Priority(max_path);
00514 if (HB_Trace(HB_TRACE_SELECT)) {
00515 HB_PATH_Trace(*path);
00516 fprintf(HB_TFile, "<HB> Maximum priority path.\n\n");
00517 }
00518
00519 BOOL tolerate_increase = TRUE;
00520 for (++path; path != hb_paths.end(); path++) {
00521 if (HB_Trace(HB_TRACE_SELECT)) {
00522 HB_PATH_Trace(*path);
00523 }
00524
00525
00526
00527
00528
00529 if (HB_PATH_Priority(*path) < (last_priority * min_path_priority_ratio)){
00530 if (HB_Trace(HB_TRACE_SELECT)) {
00531 fprintf(HB_TFile,
00532 "<HB> Selection terminated. Priority too low.\n\n");
00533 }
00534 tolerate_increase = FALSE;
00535 }
00536
00537
00538
00539
00540
00541 if (HB_PATH_Schedule_Height(*path) >
00542 Maximum_Sched_Height_Increase(max_path, tolerate_increase)) {
00543 if (HB_Trace(HB_TRACE_SELECT)) {
00544 fprintf(HB_TFile,
00545 "<HB> Not Selected. Schedule height too large.\n\n");
00546 }
00547 continue;
00548 }
00549
00550 if (!Path_Resources_Available(hb, *path, max_path, hb_est,
00551 tolerate_increase)) {
00552 if (HB_Trace(HB_TRACE_SELECT)) {
00553 fprintf(HB_TFile,"<HB> Not Selected. Resources Unavailable\n\n");
00554 }
00555 continue;
00556 }
00557
00558
00559
00560
00561 selected_blocks =
00562 BB_SET_UnionD(selected_blocks, HB_PATH_Blocks(*path), &MEM_local_pool);
00563 last_priority = HB_PATH_Priority(*path);
00564 CG_SCHED_EST_Append_Scheds(hb_est, HB_PATH_Sched_Est(*path));
00565 if (HB_Trace(HB_TRACE_SELECT)) {
00566 fprintf(HB_TFile,"<HB> Selected");
00567 BB_SET_Print(selected_blocks,HB_TFile);
00568 fprintf(HB_TFile,"\n\n");
00569 }
00570 }
00571
00572
00573
00574
00575
00576 if (profitable_ifc &&
00577 (!selected_blocks || !BB_SET_EqualP(HB_Blocks(hb), selected_blocks))) {
00578 if (HB_Trace(HB_TRACE_SELECT)) {
00579 fprintf(HB_TFile, "<HB> Hyperblock discarded. All blocks in hammock not selected.\n");
00580 }
00581 selected_blocks = NULL;
00582 } else if (BS_Size(selected_blocks) < 2) {
00583
00584
00585
00586
00587 if (HB_Trace(HB_TRACE_SELECT)) {
00588 fprintf(HB_TFile,
00589 "<HB> Hyperblock discarded. Too few blocks included.\n");
00590 }
00591 selected_blocks = NULL;
00592 } else if (HB_Trace(HB_TRACE_SELECT)) {
00593 fprintf(HB_TFile, "<HB> Selected hyperblock schedule estimate: %d\n",
00594 CG_SCHED_EST_Resource_Cycles(hb_est));
00595 }
00596 }
00597
00598
00599 for (path = hb_paths.begin(); path != hb_paths.end(); path++) {
00600 CG_SCHED_EST_Delete(HB_PATH_Sched_Est(*path));
00601 }
00602
00603 BB *bb;
00604 FOR_ALL_BB_SET_members(HB_Blocks(hb),bb) {
00605 if (BB_MAP_Get(bb_sched_est,bb)) {
00606 CG_SCHED_EST_Delete((CG_SCHED_EST *) BB_MAP_Get(bb_sched_est,bb));
00607 }
00608 }
00609
00610 CG_SCHED_EST_Delete(hb_est);
00611 BB_MAP_Delete(bb_sched_est);
00612 BB_MAP_Delete(bb_mem_hazard);
00613
00614 return selected_blocks;
00615 }
00616
00618 BOOL
00619 HB_Block_Select(HB* candidate, BOOL profitable_ifc)
00621
00622
00625 {
00626 BOOL retval;
00627 vector<BB *> join_list;
00628 INT i;
00629 BB *bb_j;
00630 BB_SET *current_blocks;
00631 BB_SET *visited_blocks;
00632 BB_SET *selected_blocks;
00633 BBLIST *succs;
00634 std::list<HB_PATH*> hb_paths;
00635 BB_SET *hb_blocks = HB_Blocks(candidate);
00636
00637
00638 if (CG_skip_local_hbf) {
00639 BOOL skip;
00640 i = BB_id(HB_Entry(candidate));
00641 skip = (i < CG_local_skip_before ||
00642 i > CG_local_skip_after ||
00643 i == CG_local_skip_equal);
00644 if (skip) DevWarn("skip hyperblock at BB %d", i);
00645 else DevWarn("process hyperblock at BB %d", i);
00646 if (skip) return FALSE;
00647 }
00648
00649
00650
00651
00652 min_path_priority_ratio = atof(HB_min_path_priority_ratio);
00653 call_hazard_multiplier = atof(HB_call_hazard_multiplier);
00654 call_hazard_multiplier = 1.;
00655 memory_hazard_multiplier = atof(HB_memory_hazard_multiplier);
00656 base_probability_contribution = atof(HB_base_probability_contribution);
00657 max_sched_growth = atof(HB_max_sched_growth);
00658 max_sched_growth_sf = max_sched_growth;
00659
00660
00661
00662
00663
00664 if (profitable_ifc) {
00665 memory_hazard_multiplier = 0.0;
00666 call_hazard_multiplier = 0.0;
00667 max_sched_growth /= 2.0;
00668 if (max_sched_growth < 1.0) {
00669 max_sched_growth = 1.0;
00670 }
00671 max_sched_growth_sf /= 2.0;
00672 if (max_sched_growth_sf < 1.0) {
00673 max_sched_growth_sf = 1.0;
00674 }
00675 min_path_priority_ratio *= 2.0;
00676 }
00677
00678
00679
00680
00681 if (HB_Flags_Check(candidate, HB_LOOP_FLAG)) {
00682
00683
00684
00685 return TRUE;
00686 }
00687
00688 BB *cur_bb;
00689 BB_SET *processed_bbs;
00690 BB_SET *hb_bbs = HB_Blocks(candidate);
00691
00692 processed_bbs = BB_SET_Create_Empty(BS_Size(hb_bbs), &MEM_local_pool);
00693
00694
00695
00696
00697 Verify_HB(HB_Entry(candidate), &processed_bbs, hb_bbs);
00698 if (!BS_EqualP(processed_bbs, hb_bbs)) {
00699 if (HB_Trace(HB_TRACE_SELECT)) {
00700 fprintf(HB_TFile, "<HB> Not Selected. Loop found.\n Blocks in proposed HB: ");
00701 BS_Print(hb_bbs,TFile); fprintf(TFile,"\n Blocks before loop: ");
00702 BS_Print(processed_bbs,TFile); fprintf(TFile,"\n");
00703 }
00704 return FALSE;
00705 }
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718 #ifdef KEY
00719
00720
00721
00722 BB *bb_succ;
00723 BOOL no_hammock = FALSE;
00724 #endif
00725 for (bb_j = HB_Entry(candidate); bb_j && HB_Contains_Block(candidate, bb_j); ) {
00726 if (BB_SET_MemberP(BB_pdom_set(HB_Entry(candidate)),bb_j)) {
00727 join_list.push_back(bb_j);
00728 }
00729 #ifdef KEY
00730 if (!no_hammock) {
00731 FOR_ALL_BB_SUCCS(bb_j, succs) {
00732 bb_succ = BBLIST_item(succs);
00733 if (HB_Contains_Block(candidate, bb_succ) &&
00734 BB_branch_op(bb_j) &&
00735 BB_branch_op(bb_succ) &&
00736 OP_cond(BB_branch_op(bb_j)) &&
00737 OP_cond(BB_branch_op(bb_succ))) {
00738 no_hammock = TRUE;
00739 break;
00740 }
00741 }
00742 }
00743 #endif
00744 succs = BB_succs(bb_j);
00745 if (succs) {
00746 bb_j = BBLIST_item(succs);
00747
00748 if (bb_j == HB_Entry(candidate)) bb_j = NULL;
00749 } else {
00750 bb_j = NULL;
00751 }
00752 }
00753
00754
00755
00756
00757 if (!HB_Exit(candidate)) {
00758 join_list.push_back(NULL);
00759 }
00760
00761 MEM_POOL_Push(&MEM_local_pool);
00762 current_blocks = BB_SET_Create_Empty(PU_BB_Count+2, &MEM_local_pool);
00763 visited_blocks = BB_SET_Create_Empty(PU_BB_Count+2, &MEM_local_pool);
00764 retval = TRUE;
00765
00766 #ifdef KEY
00767 if (join_list.size() > 1 && !no_hammock)
00768 hammock_region = TRUE;
00769 #endif
00770 for (i=0; i<join_list.size()-1; i++) {
00771 hb_paths.clear();
00772 if (!Enumerate_Paths(candidate,
00773 join_list[i],
00774 1.0,
00775 hb_paths,
00776 join_list[i+1],
00777 visited_blocks,
00778 &MEM_local_pool)) {
00779
00780 retval = FALSE;
00781 if (HB_Trace(HB_TRACE_SELECT)) {
00782 fprintf(HB_TFile, "<HB> === Block rejected, loop found or block too complex\n");
00783 }
00784 break;
00785 }
00786 if (HB_Trace(HB_TRACE_SELECT)) {
00787 #ifdef KEY
00788 fprintf(HB_TFile, "<HB> examining %ld paths\n", (long) hb_paths.size());
00789 #else
00790 fprintf(HB_TFile, "<HB> examining %d paths\n", hb_paths.size());
00791 #endif
00792 }
00793 if (hb_paths.size() > HB_MAX_PATHS) {
00794 if (HB_Trace(HB_TRACE_SELECT)) {
00795 fprintf(HB_TFile, "<HB> === Block rejected, too complex\n");
00796 }
00797 retval = FALSE;
00798 break;
00799 }
00800 selected_blocks = Select_Blocks(candidate, hb_paths, profitable_ifc);
00801 if (selected_blocks && BB_SET_MemberP(selected_blocks,join_list[i])) {
00802 current_blocks = BB_SET_UnionD(current_blocks,selected_blocks,&MEM_local_pool);
00803 } else {
00804
00805 retval = FALSE;
00806 break;
00807 }
00808 }
00809
00810
00811
00812
00813 if (retval) {
00814 HB_Blocks_Copy(candidate,current_blocks);
00815 if (HB_Trace(HB_TRACE_SELECT)) {
00816 fprintf(HB_TFile, "<HB> === Block selection complete, using ");
00817 candidate->Print();
00818 }
00819 }
00820
00821 MEM_POOL_Pop(&MEM_local_pool);
00822
00823 return retval;
00824
00825 }
00826