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 #include <vector>
00030 #include <algorithm>
00031 using namespace std;
00032
00033 #include "tracing.h"
00034 #include "id_map.h"
00035 using idmap::ID_MAP;
00036
00037 #include "be_util.h"
00038 #include "bb_node_set.h"
00039 #include "opt_alias_rule.h"
00040 #include "opt_main.h"
00041 #include "opt_lmv.h"
00042
00043 const INT LMV_HEURISTIC::_low_trip_count = 40;
00044 const float _dup_loop_freq_ratio = 0.1f;
00045
00046 extern void Rename_CODEMAP(COMP_UNIT *);
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077 typedef struct {
00078 INT ptr_id;
00079 INT weight;
00080 } PTR_INFO ;
00081
00082 struct less_weight {
00083 bool operator() (PTR_INFO info1, PTR_INFO info2)
00084 { return info1.weight < info2.weight; }
00085 };
00086
00087 BOOL
00088 LMV_HEURISTIC::Figureout_assumed_noalias_mem_ranges
00089 (MEM_ACCESS_VECT& mem_grp1, MEM_ACCESS_VECT& mem_grp2,
00090 MEM_RANGE* r1, MEM_RANGE* r2) {
00091
00092 r1->Init ();
00093 r2->Init ();
00094
00095 MA_PTR_MGR& ptr_mgr = _maa->_ptr_mgr;
00096 if (ptr_mgr.Ptr_sum() < 2) {
00097
00098
00099 return FALSE;
00100 }
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113 PTR_INFO* ptr_info = TYPE_MEM_POOL_ALLOC_N(PTR_INFO, _mp,
00114 ptr_mgr.Next_ptr_id()+1);
00115
00116 MA_PTR_VECT& vect = ptr_mgr.All_ptrs ();
00117 INT idx = 0;
00118 INT total_weight = 0;
00119 for (MA_PTR_VECT_ITER iter = vect.begin ();
00120 iter != vect.end(); iter++, idx++) {
00121 MA_POINTER* ptr = *iter;
00122 ptr_info[idx].ptr_id = ptr->Id();
00123 ptr_info[idx].weight = ptr->Ld_cnt() + ptr->St_cnt();
00124 total_weight += ptr->Ld_cnt() + ptr->St_cnt();
00125 }
00126 sort (ptr_info, ptr_info+idx-1, less_weight());
00127
00128 MA_POINTER* p1 = ptr_mgr.Get_pointer (ptr_info[0].ptr_id);
00129 MA_POINTER* p2 = ptr_mgr.Get_pointer (ptr_info[1].ptr_id);
00130
00131 MEM_ACCESS_VECT& v1 = p1->All_mem_access();
00132 MEM_ACCESS_VECT& v2 = p2->All_mem_access();
00133 if (!_alias_rule->Aliased_Memop (v1[0]->Points_to(_opt_stab),
00134 v2[0]->Points_to(_opt_stab), (TY_IDX)0, (TY_IDX)0)) {
00135 return FALSE;
00136 }
00137
00138
00139 MA_OFFSET ofst1, ofst2;
00140 ofst1.Set_fixed_ofst (0);
00141 ofst2.Set_fixed_ofst (0);
00142
00143 INT sz1, sz2;
00144 sz1 = sz2 = 0;
00145
00146 for (MEM_ACCESS_VECT_ITER iter = v1.begin (); iter != v1.end (); iter++) {
00147 ofst1.Union (&(*iter)->Ofst(), _loopinfo);
00148 sz1 = MAX(sz1, (*iter)->Byte_size());
00149 }
00150
00151 r1->Set_base_ptr (p1);
00152 r1->Set_access_range (&ofst1, _loopinfo, sz1);
00153 if (!r1->Access_range().low.Is_const () || !r1->Access_range().high.Is_const ())
00154 return FALSE;
00155
00156 for (MEM_ACCESS_VECT_ITER iter = v2.begin (); iter != v2.end (); iter++) {
00157 ofst2.Union (&(*iter)->Ofst(), _loopinfo);
00158 sz2 = MAX(sz2, (*iter)->Byte_size());
00159 }
00160 r2->Set_base_ptr (p2);
00161 r2->Set_access_range (&ofst2, _loopinfo, sz2);
00162 if (!r2->Access_range().low.Is_const () || !r2->Access_range().high.Is_const ())
00163 return FALSE;
00164
00165 mem_grp1 = v1;
00166 mem_grp2 = v2;
00167
00168 return TRUE;
00169 }
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179 LOOP_MULTIVER::LOOP_MULTIVER (COMP_UNIT* comp_unit):
00180 MEM_POOL_Constructor (&_mp, "loop multiversioning", TRUE),
00181 _candidates (&_mp)
00182 {
00183 _comp_unit = comp_unit;
00184 _htable = comp_unit->Htable();
00185 _opt_stab = comp_unit->Opt_stab();
00186 _cfg = _opt_stab->Cfg();
00187 _tracing = Get_Trace (TP_WOPT2, LOOP_MULTVER_FLAG);
00188 _blk_num = _stmt_num = _expr_num = _ld_num = _st_num = 0;
00189 _alias_rule = _opt_stab->Rule ();
00190 _local_mp = MEM_local_pool_ptr;
00191
00192 _visited_cr = BS_Create_Empty (1024, &_mp);
00193
00194 }
00195
00196 #define MAX_BB_NUM (32)
00197 #define MAX_STMT_NUM (128)
00198 #define MAX_EXPR_NUM (400)
00199
00200
00201
00202
00203 BOOL
00204 LOOP_MULTIVER::Exceed_threshold (void) {
00205 return _blk_num > MAX_BB_NUM || _stmt_num > MAX_STMT_NUM || _expr_num > MAX_EXPR_NUM;
00206 }
00207
00208
00209
00210
00211
00212
00213
00214 INT
00215 LOOP_MULTIVER::Estimate_latency (const CODEREP* cr, BOOL lhs) {
00216
00217 switch (cr->Kind()) {
00218 case CK_LDA:
00219 case CK_CONST:
00220 case CK_RCONST:
00221 return 1;
00222
00223 case CK_VAR:
00224 {
00225 ST* st = _opt_stab->Aux_stab_entry (cr->Aux_id())->St ();
00226 if (ST_class(st) == CLASS_PREG)
00227 return 1;
00228 }
00229 return lhs ? 2 : 4;
00230
00231 case CK_IVAR:
00232 return lhs ? 4 : 8;
00233
00234 case CK_DELETED:
00235 return 0;
00236
00237 case CK_OP:
00238 break;
00239
00240 default:
00241 Is_True (FALSE, ("Unexpected CODEREP kind"));
00242 }
00243
00244
00245 INT lat = 0;
00246 switch (cr->Opr()) {
00247 case OPR_MOD:
00248 case OPR_DIV: lat = 32; break;
00249 case OPR_DIVREM : lat = 40; break;
00250 case OPR_MPY:
00251 case OPR_FLOOR:
00252 case OPR_CEIL:
00253 return 40;
00254 case OPR_MLOAD:
00255 case OPR_MSTORE:
00256 return 12;
00257 }
00258
00259 return 2;
00260 }
00261
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00278
00279 void
00280 LOOP_MULTIVER::Evaluate_cr_rec (const CODEREP* cr, BOOL is_read) {
00281
00282 if (!BS_MemberP (_visited_cr, cr->Coderep_id())) {
00283 _visited_cr = BS_Union1D (_visited_cr, cr->Coderep_id(), &_mp);
00284 } else {
00285
00286 return;
00287 }
00288
00289 switch (cr->Kind()) {
00290 case CK_LDA: _expr_num ++; break;
00291 case CK_CONST: break;
00292 case CK_RCONST:
00293 {
00294 TYPE_ID dty = cr->Dtyp();
00295 if (MTYPE_is_float(dty) || MTYPE_is_complex(dty)) {
00296 _expr_num ++;
00297 }
00298 }
00299 break;
00300
00301 case CK_VAR:
00302 {
00303 ST* st = _opt_stab->Aux_stab_entry (cr->Aux_id())->St ();
00304 if (ST_class(st) != CLASS_PREG) {
00305 _expr_num ++;
00306 if (is_read) _ld_num ++ ; else _st_num ++;
00307 }
00308 }
00309 break;
00310
00311 case CK_IVAR:
00312 {
00313 if (is_read) _ld_num ++ ; else _st_num ++;
00314 _expr_num ++;
00315 Evaluate_cr_rec (is_read ? cr->Ilod_base() : cr->Istr_base(), TRUE);
00316 }
00317 break;
00318
00319 case CK_OP:
00320 _expr_num ++;
00321 for (INT i = 0; i < cr->Kid_count() ; i++) {
00322 Evaluate_cr_rec (cr->Opnd(i), TRUE);
00323 }
00324 break;
00325
00326 case CK_DELETED:
00327 break;
00328 }
00329 }
00330
00331 BOOL
00332 LOOP_MULTIVER::Evaluate_stmt (const STMTREP* stmt) {
00333 switch (stmt->Opr()) {
00334 case OPR_CALL:
00335 case OPR_ICALL:
00336 case OPR_INTRINSIC_CALL:
00337 case OPC_BACKWARD_BARRIER:
00338 case OPC_FORWARD_BARRIER:
00339 return FALSE;
00340
00341 default:
00342 if (OPCODE_is_black_box (stmt->Op())) {
00343 return FALSE;
00344 }
00345 }
00346
00347 if (stmt->Rhs()) Evaluate_cr_rec (stmt->Rhs(), TRUE);
00348 if (stmt->Lhs()) Evaluate_cr_rec (stmt->Lhs(), FALSE);
00349 ++ _stmt_num;
00350
00351 return TRUE;
00352 }
00353
00354
00356
00357
00358
00359
00361
00362 CODEREP*
00363 LOOP_MULTIVER::Gen_add_expr (CODEREP* ptr, INT ofst) {
00364
00365 if (ofst == 0) return ptr;
00366
00367 CODEREP* tmp_cr = Alloc_stack_cr(2+IVAR_EXTRA_NODE_CNT);
00368 CODEREP* ofst_cr;
00369
00370 tmp_cr->Init_const (ofst > 0 ? MTYPE_U4 : MTYPE_I4, (INT64)ofst);
00371 ofst_cr = _htable->Hash_Const (tmp_cr);
00372
00373 OPCODE opcode = (MTYPE_byte_size(ptr->Dtyp()) == 8) ? OPC_U8ADD : OPC_U4ADD;
00374 tmp_cr->Init_op(opcode, 2);
00375 tmp_cr->Set_opnd(0, ptr);
00376 tmp_cr->Set_opnd(1, ofst_cr);
00377
00378 ptr->IncUsecnt();
00379 return _htable->Hash_Op (tmp_cr);
00380 }
00381
00383
00384
00385
00386
00387
00388
00389
00391
00392 CODEREP*
00393 LOOP_MULTIVER::Gen_test_cond (LMV_CANDIDATE* cand) {
00394
00395 const MEM_RANGE& r1 = cand->Mem_range_1 ();
00396 const MEM_RANGE& r2 = cand->Mem_range_2 ();
00397
00398 const ADDR_LINEAR_EXPR_RANGE ar1 = r1.Access_range();
00399 const ADDR_LINEAR_EXPR_RANGE ar2 = r2.Access_range();
00400
00401
00402 Is_True (ar1.low.Is_const () && ar1.high.Is_const() &&
00403 ar2.low.Is_const() && ar2.high.Is_const(),
00404 ("currently cannot handle non-constant range"));
00405
00406
00407 if (r1.Base_is_symbol() || r2.Base_is_symbol()) {
00408 return NULL;
00409 }
00410
00411 MA_POINTER *p1, *p2;
00412 p1 = r1.Base_ptr ();
00413 p2 = r2.Base_ptr ();
00414
00415 if (p1->Kind () != MA_PTR_PREG && p1->Kind() != MA_PTR_SYM ||
00416 p2->Kind () != MA_PTR_PREG && p2->Kind() != MA_PTR_SYM) {
00417 return NULL;
00418 }
00419
00420 CODEREP* ptr1 = p1->Coderep();
00421 CODEREP* ptr2 = p2->Coderep();
00422 if (!cand->Loop()->Invariant_cr (ptr1) ||
00423 !cand->Loop()->Invariant_cr (ptr2)) {
00424
00425 return NULL;
00426 }
00427
00428 CODEREP *ptr1_low = Gen_add_expr (ptr1, ar1.low.Const_val());
00429 CODEREP *ptr1_high = Gen_add_expr (ptr1, ar1.high.Const_val());
00430 CODEREP *ptr2_low = Gen_add_expr (ptr2, ar2.low.Const_val());
00431 CODEREP *ptr2_high = Gen_add_expr (ptr2, ar2.high.Const_val());
00432
00433
00434 CODEREP* tmp_cr = Alloc_stack_cr(2);
00435 BOOL use_8_bytes = (MTYPE_byte_size(ptr1_low->Dtyp()) == 8);
00436
00437 CODEREP* cr_1;
00438 tmp_cr->Init_op (use_8_bytes ? OPC_I4U8LE : OPC_I4U4LE, 2);
00439 tmp_cr->Set_opnd (0, ptr1_high);
00440 tmp_cr->Set_opnd (1, ptr2_low);
00441 cr_1 = _htable->Hash_Op (tmp_cr);
00442
00443 CODEREP* cr_2;
00444 tmp_cr->Init_op (use_8_bytes ? OPC_I4U8LE : OPC_I4U4LE, 2);
00445 tmp_cr->Set_opnd (0, ptr2_high);
00446 tmp_cr->Set_opnd (1, ptr1_low);
00447 cr_2 = _htable->Hash_Op (tmp_cr);
00448
00449 tmp_cr->Init_op (OPC_I4CIOR, 2);
00450 tmp_cr->Set_opnd (0, cr_1);
00451 tmp_cr->Set_opnd (1, cr_2);
00452
00453 CODEREP* cr = _htable->Hash_Op (tmp_cr);
00454 if (_tracing) {
00455 fprintf (TFile, "The precondition predicate (kid of true-branch) is:\n");
00456 cr->Print (0, TFile);
00457 }
00458 return cr;
00459 }
00460
00462
00463
00464
00465
00467
00468 BOOL
00469 LOOP_MULTIVER::Not_applicable (BB_LOOP* loop) {
00470
00471 if (loop->Child()) {
00472 if (_tracing) {
00473 fprintf (TFile, "Not innermost loop, give up\n");
00474 }
00475 return TRUE;
00476 }
00477
00478 if (loop->Parent ()) {
00479 if (_tracing) {
00480
00481 fprintf (TFile, "Currently, it is not ready for loop-nest");
00482 }
00483 return TRUE;
00484 }
00485
00486
00487 if (loop->Is_flag_set(LOOP_IS_MP) || loop->Is_flag_set(LOOP_IS_PDO)) {
00488 if (_tracing) {
00489 fprintf (TFile, "Don't try to outsmart OpenMP pragma\n");
00490 }
00491 return TRUE;
00492 }
00493
00494
00495 if (!_cfg->LMV_eligible_for_multiversioning(loop, _tracing))
00496 return TRUE;
00497
00498 return FALSE;
00499 }
00500
00502
00503
00504
00506
00507 BOOL
00508 LOOP_MULTIVER::Pass_initial_screen (const BB_LOOP* loop) {
00509
00510
00511 CODEREP* iv;
00512 if (_agg_mode && (iv = loop->Iv()) && iv->Kind() == CK_CONST &&
00513 iv->Const_val () < LMV_HEURISTIC::Low_trip_count_threshold ()) {
00514 fprintf (TFile, "The trip count is %d smaller than the threshold %d\n",
00515 (INT)iv->Const_val(), (INT)LMV_HEURISTIC::Low_trip_count_threshold ());
00516 return FALSE;
00517 }
00518
00519 BB_NODE_SET_ITER iter;
00520 BB_NODE* blk;
00521
00522 _visited_cr = BS_ClearD (_visited_cr);
00523
00524
00525
00526
00527 _blk_num = 0;
00528 BB_NODE_SET* loop_body = loop->True_body_set();
00529 FOR_ALL_ELEM (blk, iter, Init(loop_body)) {
00530 if (blk->Hascall()) {
00531 if (_tracing) {
00532 fprintf (TFile,
00533 "give up due to call in block %d\n",
00534 blk->Id());
00535 }
00536 return FALSE;
00537 }
00538
00539 _blk_num ++;
00540
00541 if (_blk_num > MAX_BB_NUM) {
00542 if (_tracing) {
00543 fprintf (TFile, "block number exceed threshold %d\n", MAX_BB_NUM);
00544 }
00545 return FALSE;
00546 }
00547
00548 if (!blk->Clonable (TRUE)) {
00549 if (_tracing) {
00550 fprintf (TFile, "block %d is not clonable\n", blk->Id());
00551 }
00552 return FALSE;
00553 }
00554
00555 if (blk->Hascall()) {
00556
00557 if (_tracing) {
00558 fprintf (TFile, "give up due to call\n");
00559 }
00560 return FALSE;
00561 }
00562
00563 switch (blk->Kind()) {
00564 case BB_VARGOTO:
00565 case BB_IO:
00566 case BB_SUMMARY:
00567 if (_tracing) {
00568 fprintf (TFile, "Don't know how to deal with BB:%d of kind %d",
00569 blk->Id(), blk->Kind());
00570 }
00571 return FALSE;
00572
00573 case BB_ENTRY:
00574 case BB_EXIT:
00575 case BB_REGIONSTART:
00576 case BB_REGIONEXIT:
00577 Is_True (FALSE, ("BB:%d of kind %d should excluded by BB_NODE::Clonable",
00578 blk->Id(), blk->Kind()));
00579 return FALSE;
00580 }
00581 }
00582
00583
00584
00585
00586 FOR_ALL_ELEM (blk, iter, Init(loop->True_body_set())) {
00587
00588 STMTREP_CONST_ITER stmt_iter (blk->Stmtlist());
00589 const STMTREP* stmt;
00590 INT wrap_cnt = 0;
00591 FOR_ALL_NODE (stmt, stmt_iter, Init()) {
00592 if (!Evaluate_stmt (stmt)) {
00593 if (_tracing) {
00594 fprintf (TFile,
00595 "unable to conduction loop multiversioning due to this statement:\n");
00596 stmt->Print(TFile);
00597 }
00598 }
00599
00600 if (wrap_cnt ++ > 128) {
00601
00602
00603 wrap_cnt = 0;
00604 if (Exceed_threshold ()) {
00605 if (_tracing) {
00606 fprintf (TFile, "give up because the size exceed threshold");
00607 fprintf (TFile,
00608 "block:%d, statement:%d, expression:%d, load:%d, store:%d\n",
00609 _blk_num, _stmt_num, _expr_num, _ld_num, _st_num);
00610 }
00611 return FALSE;
00612 }
00613 }
00614 }
00615
00616 if (Exceed_threshold ()) {
00617 if (_tracing) {
00618 fprintf (TFile, "give up because the size exceed threshold");
00619 fprintf (TFile,
00620 "block:%d, statement:%d, expression:%d, load:%d, store:%d\n",
00621 _blk_num, _stmt_num, _expr_num, _ld_num, _st_num);
00622 }
00623 return FALSE;
00624 }
00625 }
00626
00627 return TRUE;
00628 }
00629
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00644
00645 void
00646 LOOP_MULTIVER::Identify_candidate (BB_LOOP* loop) {
00647
00648 MEM_POOL_Popper lmp (_local_mp);
00649
00650 LMV_LOOP_INFO* loopinfo = CXX_NEW(LMV_LOOP_INFO(loop, &_mp), &_mp);
00651
00652 MEM_ACCESS_ANALYZER* maa =
00653 CXX_NEW (MEM_ACCESS_ANALYZER(_opt_stab, loopinfo, &_mp, _tracing), &_mp);
00654 maa->Analyze_mem_access ();
00655
00656 LMV_HEURISTIC heur(_local_mp, this, loopinfo, _opt_stab, maa,
00657 _alias_rule, _tracing);
00658
00659 MEM_RANGE r1, r2;
00660 MEM_ACCESS_VECT mem_grp1 (_local_mp);
00661 MEM_ACCESS_VECT mem_grp2 (_local_mp);
00662
00663 if (heur.Figureout_assumed_noalias_mem_ranges
00664 (mem_grp1, mem_grp2, &r1, &r2)) {
00665
00666 LMV_CANDIDATE* cand = CXX_NEW (LMV_CANDIDATE(&_mp), &_mp);
00667 cand->Set_mem_access_analyzer (maa);
00668 cand->Set_range (r1, r2);
00669 cand->Set_loop (loop);
00670 cand->Set_mem_group (mem_grp1, mem_grp2);
00671 _candidates.push_back (cand);
00672 }
00673 }
00674
00676
00677
00678
00679
00681
00682 void
00683 LOOP_MULTIVER::Identify_candidates (void) {
00684
00685 BB_LOOP* loop_list = _cfg->Analyze_loops();
00686
00687 BB_LOOP_ITER loop_iter(loop_list);
00688 BB_LOOP* loop;
00689
00690
00691 FOR_ALL_NODE (loop, loop_iter, Init()) {
00692
00693 if (Not_applicable (loop) || !Pass_initial_screen (loop)) {
00694
00695 continue;
00696 }
00697
00698 Identify_candidate (loop);
00699 }
00700
00701 if (_tracing) {
00702 fprintf (TFile, "End Loop Multiversioning\n%s\n", DBar);
00703 }
00704 }
00705
00707
00708
00709
00711
00712 void
00713 LOOP_MULTIVER::Sort_candidates (void) {
00714
00715 }
00716
00717 void
00718 LOOP_MULTIVER::Annotate_alias_group_helper
00719 (const MEM_ACCESS_VECT& memops, LMV_ALIAS_GROUP alias_grp) {
00720
00721 MEMOP_ANNOT_CR_SR_MGR* annot_mgr = _opt_stab->Cr_sr_annot_mgr();
00722 MEMOP_ANNOT_ITEM annot;
00723 annot.Set_LMV_alias_group (alias_grp);
00724
00725 for (MEM_ACCESS_VECT_CITER iter = memops.begin ();
00726 iter != memops.end(); iter++) {
00727 const MEM_ACCESS* access = *iter;
00728 Is_True (access->Is_read() || access->Is_write(),
00729 ("neither read nor write"));
00730 CODEREP* cr = access->Coderep ();
00731 POINTS_TO* pt = cr->Points_to (_opt_stab);
00732 pt->Set_LMV_alias_group (alias_grp);
00733
00734 if (access->Is_write()) {
00735 annot_mgr->Add_annot (access->Stmtrep(), annot);
00736 }
00737 }
00738 }
00739
00740 void
00741 LOOP_MULTIVER::Annotate_alias_group (LMV_CANDIDATE* cand) {
00742
00743 const MEM_ACCESS_VECT& memops1 = cand->Mem_op_group1 ();
00744 LMV_ALIAS_GROUP alias_grp1 =
00745 Gen_LMV_alias_group (cand->Loop()->Header()->Id(), 1);
00746 Annotate_alias_group_helper (memops1, alias_grp1);
00747
00748 const MEM_ACCESS_VECT& memops2 = cand->Mem_op_group2 ();
00749 LMV_ALIAS_GROUP alias_grp2 =
00750 Gen_LMV_alias_group (cand->Loop()->Header()->Id(), 2);
00751 Annotate_alias_group_helper (memops2, alias_grp2);
00752 }
00753
00755
00756
00757
00758
00760
00761 void
00762 LOOP_MULTIVER::Perform_transformation (LMV_CANDIDATE* cand) {
00763
00764 CODEREP* precond = Gen_test_cond (cand);
00765 if (!precond) {
00766
00767 return;
00768 }
00769
00770
00771
00772
00773
00774
00775
00776
00777 LMV_CFG_ADAPTOR adaptor(&_mp, _cfg, _tracing, cand->Loop(), precond);
00778 _cfg->LMV_clone_loop (&adaptor);
00779
00780 Annotate_alias_group (cand);
00781 }
00782
00784
00785
00786
00788
00789 void
00790 LOOP_MULTIVER::Perform_loop_multiversioning (void) {
00791
00792 if (_tracing) {
00793 fprintf (TFile,
00794 "Begin Loop Multiversioning for PU:%d %s\n%s\n",
00795 Current_PU_Count(),
00796 ST_name(Get_Current_PU_ST ()), DBar);
00797
00798 fprintf (TFile, "The CFG before loop multiversioning\n");
00799 _opt_stab->Cfg()->Print (TFile, TRUE, (IDTYPE)-1);
00800 fprintf (TFile, "The end of CFG before loop multiversioning\n\n");
00801 }
00802
00803 Identify_candidates ();
00804 if (_candidates.size () == 0) return ;
00805
00806 for (LMV_CAND_VECT_ITER iter = _candidates.begin ();
00807 iter != _candidates.end(); iter++) {
00808 LMV_CANDIDATE* cand = *iter;
00809 Perform_transformation (cand);
00810 }
00811
00812
00813 _cfg->Invalidate_loops();
00814 _cfg->Invalidate_and_update_aux_info();
00815 _cfg->Analyze_loops();
00816
00817 if (_tracing) {
00818 fprintf (TFile, "\n%s\t\tAfter loop multiversioning\n%s", DBar, DBar);
00819 _cfg->Print (TFile, TRUE, (IDTYPE)-1);
00820 fprintf (TFile,
00821 "End Loop Multiversioning for PU:%d %s\n%s\n",
00822 Current_PU_Count(),
00823 ST_name(Get_Current_PU_ST ()), DBar);
00824 }
00825
00826 Rename_CODEMAP(_comp_unit);
00827 }
00828
00829
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846 BOOL
00847 CFG::LMV_eligible_for_multiversioning (const BB_LOOP* loop, BOOL trace) {
00848
00849
00850
00851 INT count = 0;
00852 BB_LIST_ITER pred_iter;
00853 BB_NODE* pred;
00854 FOR_ALL_ELEM (pred, pred_iter, Init(loop->Header()->Pred())) {
00855 if (!Is_backedge (pred, loop->Header())) {
00856 count++;
00857 }
00858 }
00859 if (count != 1) {
00860 if (trace) {
00861 fprintf (TFile, "No unique preheader\n");
00862 }
00863 return FALSE;
00864 }
00865
00866
00867 if (loop->Preheader() == NULL || loop->Merge() == NULL) {
00868 if (trace) {
00869 fprintf (TFile,
00870 "No preheader or merge blocks or they are not set properly \n");
00871 };
00872 return FALSE;
00873 }
00874
00875
00876
00877
00878
00879
00880
00881 BB_NODE* phdr = loop->Preheader();
00882 BB_NODE* next_blk = phdr->Next();
00883 BB_NODE_SET* loop_body = loop->True_body_set ();
00884 BOOL there_is_hole = FALSE;
00885
00886 if (phdr->Next() != loop->Header()) {
00887 there_is_hole = TRUE;
00888 }
00889
00890 INT cnt = 0;
00891 do {
00892 if (loop_body->MemberP(next_blk)) {
00893 cnt ++;
00894 next_blk = next_blk->Next();
00895 } else {
00896 if (next_blk != loop->Merge()) {
00897 there_is_hole = TRUE;
00898 }
00899 break;
00900 }
00901 } while (next_blk);
00902
00903
00904
00905
00906
00907
00908
00909
00910
00911 if (there_is_hole || cnt != loop_body->Size()) {
00912 if (trace) {
00913 fprintf (TFile, "The loop body blocks are not adjacent along prev/next link");
00914 }
00915 return FALSE;
00916 }
00917
00918
00919
00920 FOR_ALL_ELEM (pred, pred_iter, Init(loop->Merge()->Pred())) {
00921 if (!loop_body->MemberP (pred)) {
00922 if (trace) {
00923 fprintf (TFile,
00924 "One of merge-blk's predecessor BB:%d is not in loop body", pred->Id());
00925 }
00926 return FALSE;
00927 }
00928 }
00929
00930
00931
00932
00933
00934
00935
00936 if (!phdr->Clonable (TRUE)) {
00937 if (trace) {
00938 fprintf (TFile, "Preheader BB:%d is not clonable\n",phdr->Id ());
00939 }
00940 return FALSE;
00941 }
00942
00943
00944
00945
00946 BB_NODE* blk;
00947 BB_NODE_SET_ITER iter;
00948 FOR_ALL_ELEM (blk, iter, Init(loop_body)) {
00949
00950 BB_NODE* succ;
00951 BB_LIST_ITER succ_iter;
00952 FOR_ALL_ELEM (succ, succ_iter, Init(blk->Succ())) {
00953
00954 if (!loop_body->MemberP (succ) && succ != loop->Merge()) {
00955 STMTREP* br = blk->Branch_stmtrep();
00956 if (!br || br->Op () != OPC_GOTO) {
00957 if (trace) {
00958 fprintf (TFile,
00959 "No explicit goto statment between loop body block BB:%d and BB:%d\n",
00960 blk->Id(), succ->Id());
00961 }
00962 return FALSE;
00963 }
00964 }
00965
00966 }
00967
00968 }
00969
00970 return TRUE;
00971 }
00972
00973
00975
00976
00977
00978
00980
00981 BB_NODE*
00982 CFG::LMV_clone_block (const BB_NODE* src, LMV_CFG_ADAPTOR* adaptor) {
00983
00984 BB_NODE* clone = Create_and_allocate_bb (src->Kind());
00985 Clone_bb (src->Id(), clone->Id());
00986 clone->Set_loopdepth (src->Loopdepth());
00987 clone->Set_rid_id (src->Rid_id());
00988 clone->Set_flag (src->Flag());
00989 clone->Set_kind (src->Kind());
00990
00991
00992
00993 clone->Set_phi_list (CXX_NEW(PHI_LIST(clone), Mem_pool()));
00994 clone->Set_linenum (src->Linenum());
00995 clone->Set_freq (src->Freq());
00996
00997
00998 adaptor->Map_cloned_bb (src, clone);
00999
01000 if (src->Labnam() != 0) {
01001 clone->Add_label (this);
01002 adaptor->Map_cloned_label (src->Labnam(), clone->Labnam());
01003 }
01004
01005 return clone;
01006 }
01007
01008
01009
01010 BB_NODE*
01011 CFG::LMV_create_alike_block (BB_KIND kind, BB_NODE* model) {
01012
01013 BB_NODE* new_bb = Create_and_allocate_bb (kind);
01014 new_bb->Set_loopdepth (model->Loopdepth());
01015 new_bb->Set_rid_id (model->Rid_id());
01016 new_bb->Set_flag (model->Flag());
01017
01018
01019
01020 new_bb->Set_phi_list (CXX_NEW(PHI_LIST(new_bb), Mem_pool()));
01021 new_bb->Set_linenum (model->Linenum());
01022 new_bb->Set_freq (model->Freq());
01023
01024 return new_bb;
01025 }
01026
01028
01029
01030
01032
01033 void
01034 CFG::LMV_clone_pred_succ_relationship (LMV_CFG_ADAPTOR* adaptor) {
01035
01036 BB_LOOP* src_loop = adaptor->Src_loop();
01037
01038 BB_NODE* src_blk;
01039 BB_NODE_SET_ITER bb_iter;
01040 FOR_ALL_ELEM (src_blk, bb_iter, Init(src_loop->True_body_set ())) {
01041
01042 BB_NODE* clone = adaptor->Get_cloned_bb (src_blk);
01043
01044 BB_LIST_ITER pred_iter;
01045 BB_NODE* pred;
01046 FOR_ALL_ELEM (pred, pred_iter, Init(src_blk->Pred())) {
01047 BB_NODE* t = adaptor->Get_cloned_bb (pred);
01048 if (t) {
01049 Connect_predsucc (t, clone);
01050 } else {
01051 Is_True (pred == adaptor->Src_loop()->Preheader(),
01052 ("Block BB:%d is not cloned", pred->Id()));
01053 }
01054 }
01055 }
01056
01057
01058 Connect_predsucc (adaptor->Cloned_loop_preheader (),
01059 adaptor->Cloned_loop_header ());
01060
01061
01062 BB_NODE* new_merge = adaptor->Cloned_loop_merge ();
01063
01064 BB_LIST_ITER pred_iter;
01065 BB_NODE* pred;
01066 FOR_ALL_ELEM (pred, pred_iter, Init(src_loop->Merge()->Pred())) {
01067 BB_NODE* cloned_pred = adaptor->Get_cloned_bb (pred);
01068 Connect_predsucc (cloned_pred, new_merge);
01069 }
01070 }
01071
01073
01074
01075
01076
01077
01078
01080
01081 void
01082 CFG::LMV_clone_loop_body (LMV_CFG_ADAPTOR* adaptor) {
01083
01084
01085
01086
01087
01088
01089
01090 BB_NODE* src_blk = adaptor->Src_loop()->Header();
01091 BB_NODE* clone_blk;
01092 BB_NODE* prev_clone_blk = NULL;
01093 BB_NODE_SET* src_loop_body = adaptor->Src_loop()->True_body_set();
01094 INT clone_cnt = 0;
01095 do {
01096 clone_blk = LMV_clone_block (src_blk, adaptor);
01097 src_blk = src_blk->Next();
01098 ++ clone_cnt;
01099 if (prev_clone_blk) {
01100
01101 prev_clone_blk->Set_next (clone_blk);
01102 clone_blk->Set_prev (prev_clone_blk);
01103 }
01104 prev_clone_blk = clone_blk;
01105 } while (src_blk && src_loop_body->MemberP (src_blk));
01106
01107
01108
01109
01110
01111 Is_True (clone_cnt == src_loop_body->Size(),
01112 ("Some blocks in the source loop body are not cloned which suggest "
01113 "there is a hole in the loop body blocks in the prev/next link"));
01114
01115 adaptor->Set_pred_next_lst_header (adaptor->Cloned_loop_header());
01116 adaptor->Set_pred_next_lst_tail (clone_blk);
01117
01118 if (!adaptor->Trace()) {
01119 return;
01120 } else {
01121 fprintf (TFile,
01122 "The map of loop body blocks are (in format <src,dup>):\n");
01123 BB_NODE* t;
01124 BB_NODE_SET_ITER iter;
01125 FOR_ALL_ELEM (t, iter, Init(src_loop_body)) {
01126 fprintf (TFile, "<%d,%d>,", t->Id(), adaptor->Get_cloned_bb(t)->Id());
01127 }
01128
01129 fprintf (TFile, "\nPrev/next of src loop: ");
01130 for (t = adaptor->Src_loop()->Header();
01131 t && src_loop_body->MemberP(t); t = t->Next()) {
01132 fprintf (TFile, "%d,", t->Id());
01133 }
01134
01135 fprintf (TFile, "\nPrev/next of cloned loop: ");
01136 for (t = adaptor->Pred_next_lst_header (); t; t = t->Next()) {
01137 fprintf (TFile, "%d,", t->Id());
01138 }
01139 fprintf (TFile, "\n");
01140 }
01141 }
01142
01144
01145
01146
01147
01148
01149
01150
01151
01152
01154
01155 void
01156 CFG::LMV_update_internal_labels (LMV_CFG_ADAPTOR* adaptor) {
01157
01158 BB_LOOP* src_loop = adaptor->Src_loop();
01159 BB_NODE_SET_ITER bbs_iter;
01160 BB_NODE* bb;
01161 FOR_ALL_ELEM(bb, bbs_iter, Init(src_loop->True_body_set())) {
01162 STMTREP* br = bb->Branch_stmtrep();
01163 if (!br) continue;
01164 INT lab = br->Label_number();
01165 if (lab == 0) continue;
01166
01167 INT new_lab = adaptor->Get_cloned_label (lab);
01168 if (new_lab) {
01169 STMTREP* new_br = adaptor->Get_cloned_bb (bb)->Branch_stmtrep();
01170 new_br->Set_label_number (new_lab);
01171 }
01172 }
01173
01174 #ifdef Is_True_On
01175
01176
01177
01178 FOR_ALL_ELEM(bb, bbs_iter, Init(src_loop->True_body_set())) {
01179 INT lab = bb->Labnam();
01180 if (lab) {
01181 INT l = adaptor->Get_cloned_bb (bb)->Labnam ();
01182 Is_True (l && l == adaptor->Get_cloned_label (lab),
01183 ("Lab %d is either not cloned or not mapped properly", lab));
01184 }
01185 }
01186 #endif // Is_True_On
01187
01188
01189
01190 BB_LIST_ITER bb_iter;
01191 FOR_ALL_ELEM (bb, bb_iter, Init(src_loop->Merge()->Pred())) {
01192
01193
01194
01195
01196 Is_True (src_loop->True_body_set()->MemberP (bb),
01197 ("All predecessors are supposed to be the block of loop body"));
01198
01199 BB_NODE* clone_pred = adaptor->Get_cloned_bb (bb);
01200 STMTREP* br = clone_pred->Branch_stmtrep();
01201 if (br || br->Label_number() == src_loop->Merge()->Labnam()) {
01202 INT t = adaptor->Cloned_loop_merge()->Labnam();
01203 Is_True (t != 0,
01204 ("Label of new merge block BB:%d of source loop BB:%d is not "
01205 "set properly",
01206 adaptor->Cloned_loop_merge()->Id(),
01207 src_loop->Header()->Id()));
01208 br->Set_label_number (t);
01209 }
01210 }
01211 }
01212
01214
01215
01216
01217
01219
01220 BB_LOOP*
01221 CFG::LMV_clone_BB_LOOP (LMV_CFG_ADAPTOR* adaptor) {
01222
01223 BB_LOOP* src_loop = adaptor->Src_loop();
01224 WN* idx = src_loop->Index();
01225 BB_NODE* start = src_loop->Start ();
01226 BB_NODE* end = src_loop->End ();
01227 BB_NODE* body = src_loop->Body ();
01228 BB_NODE* step = src_loop->Step ();
01229
01230 if (start) start = adaptor->Get_cloned_bb (start);
01231 if (end) end = adaptor->Get_cloned_bb (end);
01232 if (body) body = adaptor->Get_cloned_bb (body);
01233 if (step) step = adaptor->Get_cloned_bb (step);
01234
01235 BB_LOOP* dup_loop = CXX_NEW (BB_LOOP(idx, start, end, body, step,
01236 adaptor->Cloned_loop_merge()),
01237 Mem_pool());
01238
01239 BB_NODE_SET* t = CXX_NEW (BB_NODE_SET(Last_bb_id(), this, Mem_pool(),
01240 BBNS_EMPTY), Mem_pool());
01241 dup_loop->Set_true_body_set (t);
01242
01243 dup_loop->Set_parent (src_loop->Parent());
01244 dup_loop->Set_loopstmt (src_loop->Loopstmt());
01245 dup_loop->Set_wn_trip_count (src_loop->Wn_trip_count());
01246 dup_loop->Set_flag (src_loop->Flags());
01247 dup_loop->Set_orig_wn (src_loop->Orig_wn());
01248
01249 if (src_loop->Promoted_do()) { dup_loop->Set_promoted_do(); }
01250 if (src_loop->Well_formed()) { dup_loop->Set_well_formed(); }
01251 if (src_loop->Has_entry_guard()) { dup_loop->Set_has_entry_guard(); }
01252 if (src_loop->Valid_doloop()) { dup_loop->Set_valid_doloop(); }
01253
01254 dup_loop->Set_header (adaptor->Cloned_loop_header ());
01255 dup_loop->Set_preheader (adaptor->Cloned_loop_preheader ());
01256 dup_loop->Set_size_estimate (src_loop->Size_estimate());
01257
01258
01259 BB_NODE_SET_ITER bb_iter;
01260 BB_NODE* bb;
01261 FOR_ALL_ELEM(bb, bb_iter, Init(src_loop->True_body_set ())) {
01262 if (bb->Loop()) {
01263 BB_NODE* blk = adaptor->Get_cloned_bb (bb);
01264 blk->Set_loop (dup_loop);
01265 }
01266 }
01267
01268 return dup_loop;
01269 }
01270
01271 void
01272 CFG::LMV_clone_BB_IFINFO (LMV_CFG_ADAPTOR* adaptor) {
01273
01274 BB_NODE* bb;
01275 BB_NODE_SET_ITER iter;
01276 FOR_ALL_ELEM (bb, iter, Init(adaptor->Src_loop()->True_body_set())) {
01277
01278 if (bb->Kind() != BB_LOGIF) { continue ; }
01279
01280 BB_IFINFO* ifinfo = bb->Ifinfo();
01281 BB_NODE *cond_blk, *then_blk, *else_blk, *merge_blk;
01282 cond_blk = adaptor->Get_cloned_bb (ifinfo->Cond());
01283 then_blk = adaptor->Get_cloned_bb (ifinfo->Then());
01284 else_blk = adaptor->Get_cloned_bb (ifinfo->Else());
01285 merge_blk = adaptor->Get_cloned_bb (ifinfo->Merge());
01286
01287 Is_True (cond_blk && then_blk && else_blk && merge_blk,
01288 ("Fail to construct BB_IFINFO"));
01289
01290 BB_IFINFO* cloned_ifinfo = CXX_NEW (BB_IFINFO(ifinfo->Thenloc(),
01291 ifinfo->Elseloc(),
01292 cond_blk,
01293 then_blk,
01294 else_blk,
01295 merge_blk),
01296 Mem_pool());
01297 adaptor->Get_cloned_bb (bb)->Set_ifinfo (cloned_ifinfo);
01298 }
01299 }
01300
01302
01303
01304
01305
01306
01307
01308
01309
01310
01311
01312
01313
01314
01315
01316
01317
01318
01319
01320
01321
01322
01323
01324
01325
01326
01327
01328
01329
01330
01332
01333 void
01334 CFG::LMV_gen_precondioning_stuff (LMV_CFG_ADAPTOR* adaptor) {
01335
01336 BB_LOOP* src_loop = adaptor->Src_loop();
01337
01338
01339
01340 BB_NODE* orig_merge = src_loop->Merge();
01341 BB_NODE* new_merge = Create_and_allocate_bb (BB_GOTO);
01342
01343 orig_merge->Insert_Before (new_merge);
01344
01345 BB_LIST_ITER pred_iter;
01346 BB_NODE* t;
01347 FOR_ALL_ELEM (t, pred_iter, Init(orig_merge->Pred())) {
01348 t->Replace_succ (orig_merge, new_merge);
01349 }
01350 new_merge->Set_pred (orig_merge->Pred());
01351 orig_merge->Set_pred (NULL);
01352 Connect_predsucc (new_merge, orig_merge);
01353
01354
01355
01356 INT lab = orig_merge->Labnam();
01357 if (lab) {
01358 new_merge->Add_label (this);
01359 INT new_lab = new_merge->Labnam();
01360 FOR_ALL_ELEM (t, pred_iter, Init(new_merge->Pred())) {
01361 STMTREP* br = t->Branch_stmtrep();
01362 if (br && br->Label_number () == lab) {
01363 br->Set_label_number (new_lab);
01364 }
01365 }
01366 }
01367
01368
01369
01370 orig_merge->Set_ifmerge ();
01371
01372
01373
01374 BB_NODE* orig_phdr = src_loop->Preheader();
01375 BB_NODE* precond = Create_and_allocate_bb (BB_LOGIF);
01376
01377
01378
01379 orig_phdr->Insert_Before (precond);
01380
01381
01382 BB_NODE* pred;
01383 FOR_ALL_ELEM (pred, pred_iter, Init(orig_phdr->Pred())) {
01384 pred->Replace_succ (orig_phdr, precond);
01385 }
01386 precond->Set_pred (orig_phdr->Pred ());
01387 orig_phdr->Set_pred (NULL);
01388 Connect_predsucc (precond, orig_phdr);
01389
01390
01391
01392
01393
01394
01395
01396 STMTREP* br = CXX_NEW(STMTREP(OPC_FALSEBR), Mem_pool());
01397 br->Set_rhs (adaptor->Predicate());
01398 t = adaptor->Cloned_loop_preheader();
01399 if (t->Labnam() == 0) { t->Add_label (this); }
01400 br->Set_label_number (t->Labnam());
01401 precond->Append_stmtrep (br);
01402
01403
01404
01405
01406
01407
01408
01409
01410 BB_IFINFO* ifinfo =
01411 CXX_NEW (BB_IFINFO(0, 0,
01412 precond,
01413 orig_phdr,
01414 adaptor->Cloned_loop_preheader(),
01415 orig_merge),
01416 Mem_pool());
01417 precond->Set_ifinfo (ifinfo);
01418
01419
01420 Connect_predsucc (precond, adaptor->Cloned_loop_preheader());
01421
01422
01423 src_loop->Set_merge (new_merge);
01424
01425
01426
01427 Connect_predsucc (adaptor->Cloned_loop_merge(), orig_merge);
01428
01429
01430
01431
01432
01433
01434
01435
01436
01437
01438
01439
01440
01441 new_merge->Set_next (adaptor->Cloned_loop_preheader ());
01442 adaptor->Cloned_loop_preheader()->Set_prev (new_merge);
01443 orig_merge->Set_prev (adaptor->Cloned_loop_merge ());
01444 adaptor->Cloned_loop_merge ()->Set_next (orig_merge);
01445
01446 if (adaptor->Trace()) {
01447 fprintf (TFile, "Preconditioning block is BB:%d\n", precond->Id());
01448 fprintf (TFile, "New merge for source loop is BB:%d\n", new_merge->Id());
01449 }
01450 }
01451
01452 void
01453 CFG::LMV_clone_loop (LMV_CFG_ADAPTOR* adaptor) {
01454
01455 if (adaptor->Trace()) {
01456 fprintf (TFile,
01457 "Duplicating loop (BB:%d)\nthe map between original and new blocks"
01458 " are (in format <orig,new>):\n", adaptor->Src_loop()->Header()->Id());
01459 }
01460
01461 BB_LOOP* src_loop = adaptor->Src_loop ();
01462
01463
01464
01465 LMV_clone_loop_body (adaptor);
01466
01467
01468
01469 BB_NODE* new_phdr = LMV_create_alike_block (BB_GOTO, src_loop->Preheader());
01470 Clone_bb (src_loop->Preheader()->Id(), new_phdr->Id());
01471 adaptor->Set_cloned_loop_preheader (new_phdr);
01472
01473
01474 BB_NODE* t = adaptor->Pred_next_lst_header ();
01475 t->Insert_Before (new_phdr);
01476 adaptor->Set_pred_next_lst_header (new_phdr);
01477
01478
01479
01480 BB_NODE* new_merge = LMV_create_alike_block (BB_GOTO, src_loop->Merge());
01481 new_merge->Set_flag (0);
01482 adaptor->Set_cloned_loop_merge (new_merge);
01483 if (src_loop->Merge()->Labnam()) {
01484 new_merge->Add_label (this);
01485 }
01486
01487
01488 t = adaptor->Pred_next_lst_tail ();
01489 t->Insert_After (new_merge);
01490 adaptor->Set_pred_next_lst_tail (new_merge);
01491
01492 if (adaptor->Trace()) {
01493 fprintf (TFile,
01494 "Preheader and merge block of cloned loop is BB:%d and BB:%d\n",
01495 new_phdr->Id(), new_merge->Id());
01496 }
01497
01498
01499
01500 LMV_clone_pred_succ_relationship (adaptor);
01501
01502
01503
01504 LMV_update_internal_labels (adaptor);
01505
01506
01507
01508 BB_LOOP* dup_BB_LOOP = LMV_clone_BB_LOOP (adaptor);
01509 adaptor->Set_cloned_loop (dup_BB_LOOP);
01510
01511
01512 LMV_clone_BB_IFINFO (adaptor);
01513
01514
01515
01516 LMV_gen_precondioning_stuff (adaptor);
01517 }