00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078 #include <vector>
00079 #include <list>
00080
00081 #include "tracing.h"
00082 #include "error.h"
00083
00084 #include "mempool_allocator.h"
00085 #include "cxx_memory.h"
00086
00087 #include "op.h"
00088 #include "bb.h"
00089 #include "bb_set.h"
00090
00091 #include "gtn_universe.h"
00092 #include "gtn_set.h"
00093 #include "register.h"
00094 #include "gra_live.h"
00095
00096 #include "dominate.h"
00097 #include "cgtarget.h"
00098 #include "cg_dep_graph.h"
00099 #include "cg_loop.h"
00100
00101 #include "gcm_licm.h"
00102 #include "gcm.h"
00103 #include "tag.h"
00104
00105
00106 typedef mempool_allocator<OP*> OP_ALLOC;
00107 typedef std::vector<OP*,OP_ALLOC> OP_Vector;
00108 typedef OP_Vector::iterator OP_Vector_Iter;
00109
00110
00111 typedef mempool_allocator<BB*> BB_ALLOC;
00112 typedef std::list<BB*,OP_ALLOC> BB_Lst;
00113 typedef BB_Lst::iterator BB_Lst_Iter;
00114
00115
00116
00117
00118 class LI_TN_INFO {
00119 private:
00120 OP_Vector _def_list;
00121 OP_Vector _use_list;
00122 INT32 _inloop_def_num;
00123 INT32 _inloop_use_num;
00124 mBOOL _loop_invar;
00125
00126 public:
00127
00128 LI_TN_INFO (MEM_POOL* mp):
00129 _def_list(mp), _use_list(mp), _loop_invar(FALSE),
00130 _inloop_def_num(0), _inloop_use_num(0) {};
00131 ~LI_TN_INFO (void) {} ;
00132
00133 void Add_Def_OP (OP* o) { _def_list.push_back (o); }
00134 void Add_Use_OP (OP* o) { _use_list.push_back (o); }
00135
00136 const OP_Vector* Defs (void) const { return &_def_list; }
00137 const OP_Vector* Uses (void) const { return &_use_list; }
00138
00139 BOOL Is_Loop_Invar (void) const { return _loop_invar; }
00140 void Set_Loop_Invar (void) { _loop_invar = TRUE; }
00141 void Reset_Loop_Invar (void) { _loop_invar = FALSE;}
00142
00143 INT32 Inloop_Def_Num (void) const { return _inloop_def_num; }
00144 INT32 Dec_Inloop_Def_Num (void) { return --_inloop_def_num; }
00145 INT32 Inc_Inloop_Def_Num (void) { return ++_inloop_def_num; }
00146
00147 INT32 Inloop_Use_Num (void) const { return _inloop_use_num; }
00148 INT32 Dec_Inloop_Use_Num (void) { return --_inloop_use_num; }
00149 INT32 Inc_Inloop_Use_Num (void) { return ++_inloop_use_num; }
00150 };
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162 class LOOP_TOPO_ITER {
00163 private:
00164 MEM_POOL* _mp;
00165 BB_SET* _visit;
00166 LOOP_DESCR* _loop;
00167 BB* _cur;
00168 BB_Lst _seq;
00169
00170 public:
00171 LOOP_TOPO_ITER (LOOP_DESCR* l, MEM_POOL* mp);
00172 ~LOOP_TOPO_ITER (void) {};
00173 BOOL end (void) const { return _seq.empty (); }
00174
00175 LOOP_TOPO_ITER& operator++ (void);
00176
00177
00178 BB* operator*(void) const { return _cur; }
00179 };
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192 class LI_OP_INFO_MGR;
00193 class LI_OP_INFO {
00194 friend class LI_OP_INFO_MGR;
00195 private:
00196 mBOOL _def_loop_invar;
00197 INT16 _level;
00198
00199
00200
00201 void Set_Level (INT32 l) { _level = (INT16)l; }
00202
00203 public:
00204 LI_OP_INFO (void): _def_loop_invar(FALSE), _level(0) {};
00205 ~LI_OP_INFO (void) {};
00206 BOOL Def_Loop_Invar (void) const { return _def_loop_invar; }
00207 void Set_Def_Loop_Invar (void) { _def_loop_invar = TRUE; }
00208 void Reset_Def_Loop_Invar (void) { _def_loop_invar = FALSE;}
00209
00210 INT32 Level (void) const { return (INT32)_level; }
00211 BOOL Invalid_Level (void) const { return _level == -1; }
00212 };
00213
00214 class LI_OP_INFO_MGR {
00215 private:
00216 MEM_POOL* _mp;
00217 LOOP_DESCR* _loop;
00218
00219 INT16 _bb_num;
00220 INT16 _op_num;
00221 INT16 _max_level;
00222
00223 typedef struct bb_map_bb_pair{
00224 BB_OP_MAP op_info;
00225 BB* bb;
00226 } BB_MAP_BB_PAIR;
00227 BB_MAP_BB_PAIR* _info;
00228
00229
00230 inline const BB_MAP_BB_PAIR* Idx (BB* b) const;
00231
00232 void Init_OP_Level (void);
00233
00234 public:
00235 LI_OP_INFO_MGR (LOOP_DESCR* l, MEM_POOL* mp);
00236 ~LI_OP_INFO_MGR (void) {} ;
00237
00238 LI_OP_INFO* Get (OP*) const;
00239 void Set (OP*, LI_OP_INFO*);
00240
00241 INT32 BB_Num (void) const { return (INT32)_bb_num; }
00242 INT32 OP_Num (void) const { return (INT32)_op_num; }
00243 INT32 Max_Level (void) const { return (INT32)_max_level;}
00244
00245 BOOL It_is_Tiny_Loop (void) const {return _op_num <= 8;}
00246 BOOL It_is_Small_Loop (void) const {return _op_num<16 && _op_num >=8;}
00247 BOOL It_is_Mediate_Sized_Loop (void) const
00248 { return _op_num < 32 && _op_num >= 16; }
00249 BOOL It_is_Large_Loop (void) const { return _op_num >= 32; }
00250 BOOL It_is_Huge_Loop (void) const { return _op_num >= 128; }
00251 BOOL Very_Hot_Loop (void) const {
00252 BB* b = LOOP_DESCR_loophead(_loop);
00253 return BB_freq(b) > 1000000;
00254 }
00255 };
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268 void
00269 LI_OP_INFO_MGR :: Init_OP_Level (void) {
00270
00271
00272
00273 INT32 start_level = 0;
00274 BB* header = LOOP_DESCR_loophead (_loop);
00275
00276 for (LOOP_TOPO_ITER iter(_loop, _mp); !iter.end (); ++iter) {
00277 BB* cur_bb = *iter;
00278
00279
00280
00281 if (cur_bb != header) {
00282 BBLIST* P;
00283 FOR_ALL_BB_PREDS (cur_bb,P) {
00284 BB* pred = BBLIST_item(P);
00285 if (BB_loop_head_bb (pred) != header) {
00286
00287 continue;
00288 }
00289
00290 OP* last = BB_last_op (pred);
00291 if (last) {
00292 INT32 l = Get(last)->Level ();
00293 start_level = MAX(start_level, l);
00294 }
00295 }
00296 }
00297
00298 OP* op;
00299 FOR_ALL_BB_OPs (cur_bb, op) {
00300 LI_OP_INFO* oi = Get(op);
00301 oi->Set_Level (start_level++);
00302 }
00303
00304 }
00305 }
00306
00307 LI_OP_INFO_MGR :: LI_OP_INFO_MGR (LOOP_DESCR* l, MEM_POOL* mp):
00308 _loop (l), _mp(mp) {
00309
00310 BB_SET* bbs = LOOP_DESCR_bbset (l);
00311 BB* bb;
00312 _bb_num = 0 ;
00313 _op_num = 0;
00314
00315
00316
00317 FOR_ALL_BB_SET_members (bbs, bb) {
00318 _bb_num ++; _op_num += BB_length(bb);
00319 }
00320
00321
00322
00323 _info = TYPE_MEM_POOL_ALLOC_N (BB_MAP_BB_PAIR, _mp, _bb_num);
00324 INT i = 0;
00325 FOR_ALL_BB_SET_members (bbs, bb) {
00326 _info[i].op_info = BB_OP_MAP_Create (bb, _mp);
00327 _info[i].bb = bb;
00328
00329 OP* o;
00330 FOR_ALL_BB_OPs (bb, o) {
00331 LI_OP_INFO* oi = CXX_NEW (LI_OP_INFO, _mp);
00332 BB_OP_MAP_Set (_info[i].op_info, o, oi);
00333 }
00334
00335 i ++;
00336 }
00337
00338
00339
00340
00341
00342
00343 for (INT i1 = _bb_num - 2; i1 >= 0; i1 --) {
00344 for (INT i2 = i1; i2 >= 0 ; i2 --) {
00345 if (BB_id(_info[i2+1].bb) < BB_id(_info[i2].bb)) {
00346
00347 BB_MAP_BB_PAIR t = _info[i2];
00348 _info[i2] = _info[i2+1]; _info[i2] = t;
00349 }
00350 }
00351 }
00352
00353 Init_OP_Level ();
00354 }
00355
00356
00357
00358
00359
00360
00361
00362
00363 inline const LI_OP_INFO_MGR::BB_MAP_BB_PAIR*
00364 LI_OP_INFO_MGR :: Idx (BB* b) const {
00365
00366 mBB_NUM id = BB_id (b);
00367 INT32 low=1, high=_bb_num, mid;
00368
00369 do {
00370 mid = (low + high)/2;
00371 mBB_NUM t = BB_id (_info[mid-1].bb);
00372
00373 if (t == id) return _info+mid-1;
00374 if (t < id) { low = mid + 1; continue; }
00375 high = mid - 1;
00376 } while (low <= high);
00377
00378 Is_True (FALSE, ("No BB_MAP_BB_PAIR associated with BB:%d", id));
00379 return NULL;
00380 }
00381
00382
00383
00384
00385
00386
00387
00388 LI_OP_INFO*
00389 LI_OP_INFO_MGR :: Get (OP* op) const {
00390
00391 const BB_MAP_BB_PAIR* t = Idx (OP_bb(op));
00392 return (LI_OP_INFO*) BB_OP_MAP_Get (t->op_info, op);
00393 }
00394
00395
00396
00397
00398
00399
00400
00401 void
00402 LI_OP_INFO_MGR :: Set (OP* op, LI_OP_INFO* info) {
00403 const BB_MAP_BB_PAIR* t = Idx (OP_bb(op));
00404 BB_OP_MAP_Set (t->op_info, op, info);
00405 }
00406
00407 LOOP_TOPO_ITER :: LOOP_TOPO_ITER (LOOP_DESCR* l, MEM_POOL* mp) : _mp(mp) {
00408 _loop = l;
00409
00410 _cur = LOOP_DESCR_loophead(l);
00411 _seq.push_back (_cur);
00412 _visit = BB_SET_Create_Empty (252, _mp);
00413 }
00414
00415
00416 LOOP_TOPO_ITER&
00417 LOOP_TOPO_ITER :: operator++ (void) {
00418
00419 if (end ()) { _cur = NULL; return *this; }
00420
00421 Is_True (_cur == *_seq.begin (),
00422 ("currently visited (BB:%d) is not the first element of visit-sequence",
00423 BB_id(_cur)));
00424
00425 BB_SET* body = LOOP_DESCR_bbset(_loop);
00426 BB* head = LOOP_DESCR_loophead(_loop);
00427
00428 _visit = BB_SET_Union1D (_visit, _cur, _mp);
00429 _seq.pop_front ();
00430
00431 BBLIST *s,*p;
00432 FOR_ALL_BB_SUCCS(_cur, s) {
00433
00434 BB* succ = BBLIST_item(s);
00435 if (!BB_SET_MemberP (body,succ)) { continue; }
00436 if (BB_SET_MemberP (_visit,succ)){ continue; }
00437
00438 BOOL all_pred_visited = TRUE;
00439 if (succ != head) {
00440
00441 FOR_ALL_BB_PREDS (succ, p) {
00442 BB* pred = BBLIST_item (p);
00443 if (!BB_SET_MemberP (_visit, pred)) {
00444 all_pred_visited = FALSE; break;
00445 }
00446 }
00447 }
00448
00449 if (all_pred_visited) { _seq.push_back (succ); }
00450 }
00451
00452 _cur = *_seq.begin ();
00453
00454 return *this;
00455 }
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468 class LOOP_INVAR_CODE_MOTION : public CXX_MEM_POOL {
00469
00470
00471
00472
00473 private:
00474 LOOP_DESCR* _loop;
00475 BB* _prolog;
00476 MEM_POOL* _mp;
00477
00478 TN_SET* _def_within_loop;
00479 GTN_SET* _liveout_defs;
00480
00481 hTN_MAP _tn_info;
00482 LI_OP_INFO_MGR _op_info;
00483 OP_Vector _loop_invar_defs;
00484
00485
00486 BB_Lst _loop_exits;
00487
00488 OP_Vector _ld_ops,
00489 _store_ops,
00490 _call_ops;
00491
00492 BOOL _ugly_loop;
00493 BOOL _ignore_tn_dep;
00494 BOOL _trace;
00495
00496 BOOL It_Is_Constant_TN (TN* t) const {
00497 return TN_is_const_reg(t) ||
00498 TN_is_constant (t) ||
00499 t == GP_TN ||
00500 t == Zero_TN; }
00501
00502 BOOL It_Is_Loop_Invar_TN (TN* t) const {
00503 LI_TN_INFO* i = (LI_TN_INFO*)hTN_MAP_Get (_tn_info,t);
00504 return i->Is_Loop_Invar ();
00505 }
00506
00507 LI_OP_INFO* Get_OP_Info (OP* o) const { return _op_info.Get (o); }
00508
00509 void Sanity_Check (void);
00510
00511 void Calc_Defs_Within_Loop_Body (void);
00512 void Calc_Liveout_Defs (void);
00513 void Collect_TN_Def_Use_Info (void);
00514 void Collect_Ld_St_Call (void);
00515 void Find_Out_All_Exits (void);
00516 void Misc_Init (void);
00517 BOOL Init (void);
00518 BB* Loop_Is_Zdl();
00519 BB* Find_Prolog();
00520
00521 void Mark_Dep_OPs_As_Non_Loop_Invar (OP* op);
00522
00523 void Identify_Loop_Invariants (void);
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544 BOOL TN_is_Loop_Constant (TN* tn);
00545 BOOL All_Reaching_Def_are_Outside_Of_Loop (OP *, INT opnd_idx);
00546 BOOL Unique_Reaching_Def_Inside_Loop (OP*, INT opdn_idx);
00547 BOOL Register_Para_Passing (OP* op);
00548 BOOL Alias_With_Call(OP*, OP* call);
00549 BOOL It_is_Fake_Loop_Invar (OP*);
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568 BOOL Def_Dominate_All_Use (OP*);
00569 BOOL Dom_All_Loop_Exits (BB* );
00570 inline BOOL Live_Out_Of_Loop (OP* ) const;
00571 BOOL Illegal_Or_Nonprofitable (OP* );
00572 void Perform_Code_Motion (OP* );
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586 BOOL Ignore_Ugly_Loop();
00587 BOOL Ignore_Loop_With_Few_Interation (void);
00588 BOOL Code_Motion_Is_Profitable (OP*);
00589
00590 public:
00591 LOOP_INVAR_CODE_MOTION (LOOP_DESCR* l, BOOL ign_tn_dep);
00592 ~LOOP_INVAR_CODE_MOTION (void) {}
00593
00594 INT32 Perform_Code_Motion (void);
00595
00596
00597
00598 BOOL Loop_Has_Call (void) const { return Is_Call_Loop(_loop);}
00599 const LOOP_DESCR* Loop (void) const { return _loop;}
00600
00601 void Dump (FILE* f=stderr);
00602 #ifdef Is_True_On
00603
00604
00605
00606 void gdb_dump (void);
00607 #endif
00608 };
00609
00610
00611
00612
00613
00614
00615
00616
00617 BOOL LOOP_INVAR_CODE_MOTION::Ignore_Ugly_Loop()
00618 {
00619 if( _ugly_loop )
00620 return TRUE;
00621
00622 if( !_prolog )
00623 return TRUE;
00624
00625 BB *head = LOOP_DESCR_loophead( _loop );
00626 if( !head )
00627 return TRUE;
00628
00629 return FALSE;
00630 }
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640 void
00641 LOOP_INVAR_CODE_MOTION :: Calc_Defs_Within_Loop_Body (void) {
00642
00643 BB_SET* bbs = LOOP_DESCR_bbset (_loop);
00644 BB* bb;
00645
00646 FOR_ALL_BB_SET_members (bbs, bb) {
00647 OP* op;
00648
00649 FOR_ALL_BB_OPs (bb, op) {
00650 for (INT i = OP_results (op) - 1; i >= 0; i--) {
00651 TN* res = OP_result(op, i);
00652 _def_within_loop = TN_SET_Union1D (_def_within_loop,res, _mp);
00653
00654 }
00655 }
00656 }
00657 }
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669 void
00670 LOOP_INVAR_CODE_MOTION :: Calc_Liveout_Defs (void) {
00671
00672 BB_SET* body = LOOP_DESCR_bbset (_loop);
00673
00674 for (BB_Lst_Iter iter = _loop_exits.begin ();
00675 iter != _loop_exits.end (); iter++) {
00676
00677 BB* exit_blk = *iter;
00678 BBLIST* s;
00679
00680 FOR_ALL_BB_SUCCS (exit_blk, s) {
00681 BB* succ = BBLIST_item (s);
00682 if (BB_SET_MemberP (body, succ)) { continue ; }
00683
00684 _liveout_defs =
00685 GTN_SET_UnionD (_liveout_defs, BB_live_in (succ), _mp);
00686
00687 }
00688 }
00689 }
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700 void
00701 LOOP_INVAR_CODE_MOTION :: Collect_TN_Def_Use_Info (void) {
00702
00703 BB_SET* bbs = LOOP_DESCR_bbset(_loop);
00704 BB* bb;
00705
00706 FOR_ALL_BB_SET_members (bbs, bb) {
00707
00708 OP* op;
00709 FOR_ALL_BB_OPs (bb, op) {
00710
00711
00712 for (INT i = 0 ; i < OP_results(op); i++) {
00713
00714 TN* res = OP_result(op,i);
00715 if (It_Is_Constant_TN (res)) { continue; }
00716
00717 LI_TN_INFO* info;
00718 info = (LI_TN_INFO*)hTN_MAP_Get (_tn_info, res);
00719
00720 if (!info) {
00721 info = CXX_NEW(LI_TN_INFO(_mp), _mp);
00722 hTN_MAP_Set (_tn_info, res, (void*)info);
00723 }
00724
00725 info->Add_Def_OP (op);
00726 info->Inc_Inloop_Def_Num ();
00727
00728 }
00729
00730
00731
00732 for (INT i = 0; i < OP_opnds(op); i++) {
00733
00734 TN* opnd = OP_opnd(op,i);
00735 if (It_Is_Constant_TN (opnd)) { continue; }
00736
00737 LI_TN_INFO* info;
00738 info = (LI_TN_INFO*)hTN_MAP_Get (_tn_info, opnd);
00739
00740 if (!info) {
00741 info = CXX_NEW (LI_TN_INFO(_mp), _mp);
00742 hTN_MAP_Set (_tn_info, opnd, (void*)info);
00743 }
00744
00745 info->Add_Use_OP (op);
00746 info->Inc_Inloop_Use_Num ();
00747
00748 }
00749 }
00750 }
00751 }
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761 void
00762 LOOP_INVAR_CODE_MOTION :: Collect_Ld_St_Call (void) {
00763
00764 BB_SET* bbs = LOOP_DESCR_bbset(_loop);
00765 BB* bb;
00766
00767 FOR_ALL_BB_SET_members (bbs, bb) {
00768 OP* op;
00769 FOR_ALL_BB_OPs (bb,op) {
00770
00771 extern BOOL OP_like_store(OP *op);
00772
00773 if (OP_load (op)) { _ld_ops.push_back (op) ; continue; }
00774 if (OP_like_store (op)) { _store_ops.push_back(op); continue; }
00775 if (OP_call (op)) {
00776 _call_ops.push_back (op);
00777
00778
00779
00780 Set_Call_Loop (_loop);
00781 }
00782 }
00783 }
00784 }
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799 void
00800 LOOP_INVAR_CODE_MOTION :: Find_Out_All_Exits (void) {
00801
00802 BB_SET* bbs = LOOP_DESCR_bbset(_loop);
00803 BB* bb;
00804
00805 FOR_ALL_BB_SET_members (bbs, bb) {
00806
00807 BBLIST *succs;
00808 FOR_ALL_BB_SUCCS(bb, succs) {
00809 BB *succ = BBLIST_item(succs);
00810 if (!BB_SET_MemberP(bbs, succ) &&
00811 find (_loop_exits.begin(),
00812 _loop_exits.end(), succ) == _loop_exits.end()) {
00813 _loop_exits.push_back (bb);
00814 }
00815 }
00816 }
00817 }
00818
00819 void
00820 LOOP_INVAR_CODE_MOTION :: Misc_Init (void) {
00821 }
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831
00832 void
00833 LOOP_INVAR_CODE_MOTION :: Sanity_Check (void) {
00834
00835 #ifdef Is_True_On
00836
00837
00838
00839 BB_SET* bbs = LOOP_DESCR_bbset (_loop);
00840 BB* bb;
00841
00842 FOR_ALL_BB_SET_members (bbs, bb) {
00843 BB_Verify_OP_Order (bb);
00844 }
00845 #endif
00846 }
00847
00848 BOOL
00849 LOOP_INVAR_CODE_MOTION :: Init (void) {
00850
00851 _tn_info = hTN_MAP_Create (_mp);
00852
00853 _def_within_loop = TN_SET_Create_Empty (Last_TN + 1, _mp);
00854 _liveout_defs = TN_SET_Create_Empty (Last_TN + 1, _mp);
00855
00856 Find_Out_All_Exits ();
00857 Calc_Defs_Within_Loop_Body ();
00858 Calc_Liveout_Defs ();
00859 Collect_TN_Def_Use_Info ();
00860 Collect_Ld_St_Call ();
00861
00862 Misc_Init ();
00863
00864 _trace = Get_Trace (TP_GCM, GCM_TRACE_LICM );
00865
00866 return TRUE;
00867 }
00868
00869
00870
00871
00872
00873
00874 BB* LOOP_INVAR_CODE_MOTION::Loop_Is_Zdl()
00875 {
00876 BB *head = LOOP_DESCR_loophead( _loop );
00877 BB *prolog = BB_prev( head );
00878 if( !prolog )
00879 return NULL;
00880
00881 while( Is_BB_Empty(prolog) )
00882 prolog = BB_prev(prolog);
00883
00884
00885
00886
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898
00899 OP *loop_op = BB_last_op( prolog );
00900 if( !OP_is_loop(loop_op) ){
00901 BBLIST *preds_list;
00902 prolog = NULL;
00903 FOR_ALL_BB_PREDS( head, preds_list ){
00904 if( BB_loop_op(BBLIST_item(preds_list)) ){
00905 if( prolog )
00906 Is_True( 0, ("multi loop insn meet on a single loop head") );
00907 prolog = BBLIST_item( preds_list );
00908 }
00909 }
00910
00911
00912 if( prolog )
00913 _ugly_loop = TRUE;
00914 }
00915
00916 return prolog;
00917 }
00918
00919
00920
00921
00922
00923
00924
00925
00926
00927 BB* LOOP_INVAR_CODE_MOTION::Find_Prolog()
00928 {
00929 BB* lhead = LOOP_DESCR_loophead(_loop);
00930 BB_SET* body = LOOP_DESCR_bbset(_loop);
00931 BB* prolog = NULL;
00932
00933 prolog = Loop_Is_Zdl();
00934 if( prolog ){
00935 if( _trace )
00936 fprintf( TFile, "this is zero delay loop\n" );
00937 return prolog;
00938 }
00939
00940 BBLIST* p;
00941 FOR_ALL_BB_PREDS (lhead, p) {
00942 BB* pred = BBLIST_item (p);
00943 if (BB_SET_MemberP (body, pred)) { continue; }
00944
00945 if (prolog) {
00946 prolog = NULL; break;
00947 } else {
00948 prolog = pred;
00949 }
00950 }
00951
00952 if( prolog ){
00953 if (BB_kind (prolog) != BBKIND_GOTO ||
00954 BB_branch_op (prolog)) {
00955 prolog = NULL;
00956 }
00957 }
00958
00959 if (prolog) {
00960 Set_BB_gra_spill(prolog);
00961 }
00962
00963 if( prolog && BB_prev(lhead) != prolog ){
00964 DevWarn( "prolog BB:%d not fall through to BB:%d. Ugly due to cflow",
00965 BB_id(prolog), BB_id(lhead) );
00966 DevWarn( "I don't do LICM for it" );
00967 _ugly_loop = TRUE;
00968 return NULL;
00969 }else{
00970 if( !prolog ){
00971 if( _trace )
00972 fprintf( TFile, "Create a new :\n" );
00973 prolog = CG_LOOP_Gen_And_Prepend_To_Prolog( lhead,_loop );
00974
00975 Set_BB_dom_set( prolog, BS_Create_Empty( 2+PU_BB_Count+1, _mp ) );
00976 BS_UnionD( BB_dom_set(prolog), BB_dom_set(lhead), _mp );
00977 BS_Union1D( BB_dom_set(prolog), BB_id(prolog), _mp );
00978 BS_Difference1D( BB_dom_set(prolog), BB_id(lhead) );
00979
00980 Set_BB_pdom_set( prolog, BS_Create_Empty( 2+PU_BB_Count+1, _mp ) );
00981 BS_UnionD( BB_pdom_set(prolog), BB_pdom_set(lhead), _mp );
00982 BS_Union1D( BB_pdom_set(prolog), BB_id(prolog), _mp );
00983 }
00984 if( _trace ){
00985 fprintf( TFile, "Prolog is :\n" );
00986 Print_BB_No_Srclines( prolog );
00987 }
00988
00989 return prolog;
00990 }
00991 }
00992
00993
00994 LOOP_INVAR_CODE_MOTION::LOOP_INVAR_CODE_MOTION( LOOP_DESCR* l, BOOL ign_tn_dep ):
00995 CXX_MEM_POOL("Loop Invariant Code Motion", FALSE),
00996 _mp((*this)()), _loop_exits (_mp), _loop_invar_defs(_mp),
00997 _ld_ops (_mp), _store_ops(_mp), _call_ops(_mp),
00998 _loop(l), _op_info(l, _mp), _ugly_loop(FALSE),
00999 _ignore_tn_dep(ign_tn_dep) {
01000 Init ();
01001 _prolog = Find_Prolog();
01002 }
01003
01004
01005
01006
01007
01008
01009
01010
01011
01012
01013 BOOL
01014 LOOP_INVAR_CODE_MOTION :: TN_is_Loop_Constant (TN* t) {
01015
01016 if (It_Is_Constant_TN (t)) { return TRUE; }
01017
01018 LI_TN_INFO* info;
01019 info = (LI_TN_INFO*)hTN_MAP_Get (_tn_info, t);
01020
01021 return info->Is_Loop_Invar();
01022 }
01023
01024
01025
01026
01027
01028
01029
01030
01031
01032 BOOL
01033 LOOP_INVAR_CODE_MOTION :: All_Reaching_Def_are_Outside_Of_Loop
01034 (OP* op, INT opnd_idx) {
01035
01036 TN* opnd = OP_opnd (op, opnd_idx);
01037
01038 Is_True (opnd,
01039 ("OP[%d] (of BB:%d)'s No.%d operand does not exist!",
01040 OP_map_idx(op), BB_id(OP_bb(op)), opnd_idx));
01041
01042
01043
01044 if (It_Is_Constant_TN (opnd)) { return TRUE; }
01045
01046 return !TN_SET_MemberP (_def_within_loop, opnd);
01047 }
01048
01049
01050
01051
01052
01053
01054
01055
01056
01057
01058
01059
01060
01061
01062
01063
01064
01065
01066
01067
01068 BOOL
01069 LOOP_INVAR_CODE_MOTION :: Unique_Reaching_Def_Inside_Loop
01070 (OP* op, INT opnd_idx) {
01071
01072 BB* home = OP_bb (op);
01073
01074 TN* opnd = OP_opnd (op, opnd_idx);
01075 LI_TN_INFO* ti = (LI_TN_INFO*)hTN_MAP_Get (_tn_info, opnd);
01076 OP_Vector* ops = (OP_Vector*)ti->Defs ();
01077
01078 if (ops->size () != 1) {
01079
01080
01081
01082 return FALSE;
01083 }
01084
01085 OP* def = *ops->begin ();
01086
01087
01088
01089 if (OP_bb(op) != OP_bb(def)) {
01090 if (BB_SET_MemberP (BB_dom_set(home), OP_bb(def))) {
01091 return FALSE;
01092 }
01093 } else {
01094 if (OP_Precedes (op,def) || op == def) { return FALSE; }
01095 }
01096
01097 if (OP_has_predicate(op) && OP_opnd(op, OP_PREDICATE_OPND) != True_TN) {
01098
01099
01100
01101
01102
01103 return FALSE;
01104 }
01105
01106 return TRUE;
01107 }
01108
01109
01110
01111
01112
01113
01114
01115
01116
01117
01118
01119 BOOL
01120 LOOP_INVAR_CODE_MOTION :: Register_Para_Passing (OP* op) {
01121
01122 if (!BB_call(OP_bb(op))) { return FALSE; }
01123
01124 for (INT i = OP_results(op) - 1; i >= 0; i--) {
01125 TN* res = OP_result(op,i);
01126 if (!TN_register(res)) { continue; }
01127
01128 if (REGISTER_Is_Stacked_Output (TN_register_class(res),
01129 TN_register(res))) {
01130 return TRUE;
01131 }
01132 }
01133
01134 return FALSE;
01135 }
01136
01137
01138
01139
01140
01141
01142
01143
01144 void
01145 LOOP_INVAR_CODE_MOTION :: Mark_Dep_OPs_As_Non_Loop_Invar (OP* op) {
01146
01147 for (INT i = OP_results(op) - 1; i >= 0; i--) {
01148
01149 TN* res = OP_result(op, i);
01150 if (It_Is_Constant_TN (res)) { continue; }
01151
01152 LI_TN_INFO* tninfo = (LI_TN_INFO*)hTN_MAP_Get (_tn_info, res);
01153 OP_Vector* ops = (OP_Vector*)tninfo->Uses ();
01154
01155 for (OP_Vector_Iter iter = ops->begin ();
01156 iter != ops->end (); iter++) {
01157
01158 OP* use = *iter;
01159 LI_OP_INFO* opinfo = Get_OP_Info (use);
01160 opinfo->Reset_Def_Loop_Invar ();
01161 }
01162 }
01163 }
01164
01165
01166
01167
01168
01169
01170
01171
01172
01173
01174
01175
01176
01177
01178
01179
01180
01181
01182
01183
01184
01185
01186
01187
01188
01189
01190
01191
01192
01193
01194
01195
01196
01197
01198
01199
01200
01201
01202
01203
01204
01205
01206
01207
01208
01209
01210
01211
01212
01213 #define OP_is_dma_begin(o) ( OP_code(o) == TOP_peripheral_rw_begin )
01214 #define OP_is_dma_end(o) ( OP_code(o) == TOP_peripheral_rw_end )
01215
01216 static inline BOOL
01217 BB_has_barrier( BB *bb, OP *position )
01218 {
01219 OP *op = position;
01220 if( !op )
01221 op = BB_last_op(bb);
01222 while( op ){
01223 if( CGTARG_Is_OP_Barrier(op) )
01224 return TRUE;
01225 op = OP_prev(op);
01226 }
01227
01228 return FALSE;
01229 }
01230
01231 static inline BOOL
01232 BB_has_unpaired_dma_begin( BB *bb )
01233 {
01234 BOOL unpaired_begin = FALSE;
01235 BOOL unpaired_end = FALSE;
01236
01237 OP *op;
01238 FOR_ALL_BB_OPs_REV( bb, op ){
01239 if( OP_is_dma_begin(op) ){
01240 if( !unpaired_end )
01241 return TRUE;
01242 else
01243 unpaired_end = FALSE;
01244 }
01245 if( OP_is_dma_end(op) ){
01246 if( !unpaired_end )
01247 unpaired_end = TRUE;
01248 else
01249 Is_True( 0, ("more than 1 DMA end") );
01250 }
01251 }
01252
01253 return FALSE;
01254 }
01255
01256 static BOOL Is_Barriered( LOOP_DESCR *loop, BB *bb, OP *mem_op )
01257 {
01258
01259 OP *op = OP_prev(mem_op);
01260 if( BB_has_barrier(bb, mem_op) )
01261 return TRUE;
01262
01263
01264 BB *head = LOOP_DESCR_loophead(loop);
01265 if( head ){
01266 BB *prolog = BB_Fall_Thru_Predecessor( head );
01267 if( prolog ){
01268 return BB_has_unpaired_dma_begin( prolog );
01269 }else{
01270
01271
01272 return TRUE;
01273 }
01274 }else{
01275 Is_True( 0, ("no head for loop") );
01276 }
01277 }
01278
01279 static inline BOOL OP_Not_Suitable( LOOP_DESCR *loop, BB *bb, OP *op )
01280 {
01281 if( CGTARG_Is_OP_Barrier(op) )
01282 return TRUE;
01283
01284 if( OP_xfer (op) || OP_call (op) || OP_is_loop(op) ||
01285 ((OP_load(op) || OP_store(op)) && Is_Barriered(loop, bb, op)) )
01286 return TRUE;
01287
01288 if( CGTARG_Is_OP_Intrinsic(op) )
01289 return TRUE;
01290
01291 if( OP_volatile(op) )
01292 return TRUE;
01293
01294 return FALSE;
01295 }
01296
01297
01298
01299
01300
01301
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 void
01328 LOOP_INVAR_CODE_MOTION :: Identify_Loop_Invariants (void) {
01329
01330 for (LOOP_TOPO_ITER iter(_loop, _mp); !iter.end (); ++iter) {
01331
01332 BB* b = *iter;
01333 OP* op;
01334
01335 FOR_ALL_BB_OPs (b, op) {
01336 BOOL it_is;
01337 it_is = TRUE;
01338
01339 for (INT i = OP_opnds (op) - 1; i >= 0 && it_is; i--) {
01340
01341 TN* opnd = OP_opnd(op,i);
01342 it_is =
01343 TN_is_Loop_Constant (opnd) ||
01344 All_Reaching_Def_are_Outside_Of_Loop (op, i) ||
01345 It_Is_Loop_Invar_TN (opnd) &&
01346 Unique_Reaching_Def_Inside_Loop (op, i);
01347 }
01348
01349 if( OP_Not_Suitable(_loop, b, op) ){
01350 it_is = TRUE;
01351 continue;
01352 }
01353
01354
01355
01356
01357 if (it_is && Register_Para_Passing (op)) {
01358 it_is = FALSE;
01359 }
01360
01361
01362
01363
01364 for (INT i = OP_results (op) - 1; i >= 0; i--) {
01365 TN* res = OP_result (op, i);
01366
01367 if (It_Is_Constant_TN (res)) continue;
01368
01369 LI_TN_INFO* tninfo;
01370 tninfo = (LI_TN_INFO*) hTN_MAP_Get (_tn_info, res);
01371 if (tninfo->Inloop_Def_Num () != 1) { it_is = FALSE; }
01372
01373 if (it_is) {
01374 tninfo->Set_Loop_Invar ();
01375 } else {
01376 tninfo->Reset_Loop_Invar ();
01377 break;
01378 }
01379
01380 }
01381
01382 if (it_is) {
01383
01384
01385
01386
01387
01388 _loop_invar_defs.push_back (op);
01389 _op_info.Get(op)->Set_Def_Loop_Invar ();
01390 }
01391
01392 }
01393
01394 }
01395 }
01396
01397 BOOL
01398 LOOP_INVAR_CODE_MOTION :: Alias_With_Call (OP* op, OP* call) {
01399
01400 BOOL alias =
01401 !CG_DEP_Can_OP_Move_Across_Call (op, call, TRUE, _ignore_tn_dep) ||
01402 !CG_DEP_Can_OP_Move_Across_Call (op, call, FALSE, _ignore_tn_dep);
01403
01404 if (!alias) { return FALSE; }
01405
01406 return TRUE;
01407 }
01408
01409 BOOL
01410 LOOP_INVAR_CODE_MOTION :: It_is_Fake_Loop_Invar (OP* op) {
01411
01412 UINT8 omega = 0;
01413 BOOL definite=FALSE;
01414
01415 if (OP_store (op)) { return TRUE; }
01416
01417 if (Loop_Has_Call ()) {
01418 for (OP_Vector_Iter iter = _call_ops.begin ();
01419 iter != _call_ops.end (); iter++) {
01420
01421 if (Alias_With_Call (op, *iter)) { return TRUE; }
01422 }
01423 }
01424
01425 if (OP_load (op)) {
01426 for (OP_Vector_Iter st_iter = _store_ops.begin ();
01427 st_iter != _store_ops.end (); st_iter ++) {
01428
01429 OP* op_like_st = *st_iter;
01430 if (!OP_store (op_like_st)) {
01431
01432
01433
01434 return TRUE;
01435 }
01436
01437 if (CG_DEP_Mem_Ops_Alias (op, op_like_st, NULL)) {
01438 return TRUE;
01439 }
01440 }
01441 }
01442
01443 return FALSE;
01444 }
01445
01446
01447
01448
01449
01450
01451
01452
01453
01454
01455 BOOL
01456 LOOP_INVAR_CODE_MOTION :: Def_Dominate_All_Use (OP* linvar) {
01457
01458 BB* home = OP_bb (linvar);
01459
01460 for (INT i=0 ; i < OP_results(linvar); i++) {
01461
01462 TN* res = OP_result(linvar, i);
01463 if (It_Is_Constant_TN (res)) { continue; }
01464
01465 LI_TN_INFO* info;
01466 info = (LI_TN_INFO*)hTN_MAP_Get (_tn_info, res);
01467 Is_True (info,
01468 ("LI_TN_INFO for OP:%d of BB:%d does not exist",
01469 OP_map_idx(linvar), BB_id (OP_bb(linvar))));
01470
01471 OP_Vector* ops = (OP_Vector*)info->Uses ();
01472
01473
01474
01475 for (OP_Vector_Iter iter = ops->begin ();
01476 iter != ops->end (); iter++) {
01477
01478 OP* o = *iter;
01479 BB* t = OP_bb (o);
01480
01481
01482
01483
01484
01485 if (!BB_SET_MemberP (BB_dom_set(t), home)) {
01486 return FALSE;
01487 } else if (t == home) {
01488 if (!OP_Precedes (linvar, o)) { return FALSE; }
01489 }
01490 }
01491 }
01492 }
01493
01494
01495
01496
01497
01498
01499
01500
01501 BOOL
01502 LOOP_INVAR_CODE_MOTION :: Dom_All_Loop_Exits (BB* b) {
01503
01504 BOOL no_exit = TRUE;
01505
01506 for (BB_Lst_Iter iter = _loop_exits.begin ();
01507 iter != _loop_exits.end (); iter++) {
01508
01509 BB* exit_bb = *iter;
01510 if (!BB_SET_MemberP (BB_dom_set(exit_bb), b)) { return FALSE; }
01511
01512 no_exit = FALSE;
01513 }
01514
01515
01516
01517
01518 return !no_exit;
01519 }
01520
01521
01522
01523
01524
01525
01526
01527
01528
01529
01530 inline BOOL
01531 LOOP_INVAR_CODE_MOTION :: Live_Out_Of_Loop (OP* op) const {
01532
01533 for (INT i = OP_results (op) - 1; i >= 0; i--) {
01534 TN* res = OP_result(op, i);
01535
01536 if (!TN_is_constant(res) && TN_is_global_reg(res) &&
01537 GTN_SET_MemberP (_liveout_defs, res)) {
01538 return TRUE;
01539 }
01540 }
01541 return FALSE;
01542 }
01543
01544
01545
01546
01547
01548
01549
01550
01551
01552
01553
01554
01555
01556
01557 BOOL
01558 LOOP_INVAR_CODE_MOTION :: Code_Motion_Is_Profitable (OP* op) {
01559
01560 BB* loop_ent = LOOP_DESCR_loophead(_loop);
01561 BB* home = OP_bb (op);
01562
01563
01564
01565
01566
01567
01568 #define PROG_SCALE (100)
01569 #define LOW_PROB_FOR_ALU_OP (70)
01570 #define LOW_PROB_FOR_LD_OP (40)
01571 #define LOW_PROB_FOR_LONG_LATENCY (40)
01572
01573 float freq1 = BB_freq (loop_ent), freq2 = BB_freq (home);
01574 freq1 = (freq1 < 1.0f) ? 1.0f : freq1;
01575 INT32 div = (INT32)(freq2 * PROG_SCALE/ freq1);
01576
01577 if (CGTARG_Is_Long_Latency (OP_code (op))) {
01578 if (div < LOW_PROB_FOR_LONG_LATENCY) { return FALSE; }
01579 } else if (OP_load (op)) {
01580 if (div < LOW_PROB_FOR_LD_OP) { return FALSE; }
01581 } else {
01582 if (div < LOW_PROB_FOR_ALU_OP) { return FALSE; }
01583 }
01584
01585
01586
01587 if (Live_Out_Of_Loop (op)) {
01588
01589 return TRUE;
01590 }
01591
01592 if (_op_info.It_is_Tiny_Loop ()) { return TRUE; }
01593 if (_op_info.It_is_Huge_Loop ()) { return FALSE;}
01594 if (_op_info.It_is_Large_Loop () && !_op_info.Very_Hot_Loop ()) {
01595 return FALSE;
01596 }
01597
01598
01599
01600
01601
01602
01603
01604
01605
01606
01607
01608
01609
01610
01611
01612
01613
01614
01615
01616
01617
01618
01619
01620
01621
01622
01623 return TRUE;
01624 }
01625
01626
01627
01628
01629
01630
01631
01632
01633
01634
01635
01636
01637
01638 BOOL
01639 LOOP_INVAR_CODE_MOTION :: Ignore_Loop_With_Few_Interation (void) {
01640
01641 BB* loop_ent = LOOP_DESCR_loophead(_loop);
01642 float f = 0.0f;
01643
01644 BBLIST* pred;
01645 FOR_ALL_BB_PREDS (loop_ent,pred) {
01646 BB* b = BBLIST_item(pred);
01647 f += BB_freq (b);
01648 }
01649
01650 f = (f < 1.0f) ? 1.0f : f;
01651 return (BB_freq (loop_ent) - f) < 10^5;
01652 }
01653
01654
01655
01656
01657
01658
01659
01660
01661
01662
01663
01664
01665
01666 BOOL
01667 LOOP_INVAR_CODE_MOTION :: Illegal_Or_Nonprofitable (OP* loopinvar) {
01668
01669 BB* home = OP_bb (loopinvar);
01670
01671 if (!Def_Dominate_All_Use (loopinvar)) {
01672 return TRUE;
01673 }
01674
01675
01676
01677
01678 BOOL spec = !Dom_All_Loop_Exits (home);
01679
01680 if (spec) {
01681
01682
01683
01684 if (!CGTARG_Can_Be_Speculative (loopinvar)) {
01685 return TRUE;
01686 }
01687
01688
01689
01690 if (CGTARG_Is_OP_Speculative (loopinvar)) {
01691 return TRUE;
01692 }
01693
01694
01695 if (Live_Out_Of_Loop (loopinvar)) {
01696 return TRUE;
01697 }
01698 }
01699
01700 if (!Code_Motion_Is_Profitable (loopinvar)) {
01701 return TRUE;
01702 }
01703
01704
01705
01706
01707
01708 if (It_is_Fake_Loop_Invar (loopinvar)) {
01709 return TRUE;
01710 }
01711
01712 return FALSE;
01713 }
01714
01715
01716
01717
01718
01719
01720
01721
01722
01723
01724
01725
01726
01727
01728 extern BOOL Should_Skip( int, int, int, int );
01729 static BOOL GCM_LICM_Skip_Op_Binary_Search( INT32 op_id )
01730 {
01731 BOOL skip = Should_Skip( CG_GCM_LICM_op_skip_before,
01732 CG_GCM_LICM_op_skip_after,
01733 CG_GCM_LICM_op_skip_equal,
01734 op_id );
01735 return skip;
01736 }
01737
01738 INT32
01739 LOOP_INVAR_CODE_MOTION :: Perform_Code_Motion (void)
01740 {
01741 if( _trace ){
01742 fprintf( TFile, "======= Loop Invariant Code Motion ====\n" );
01743
01744 BB_SET* loop_bbs = LOOP_DESCR_bbset( _loop );
01745 fprintf( TFile, "GCM_For_Loop: list of bbs:" );
01746 BB_SET_Print( loop_bbs, TFile );
01747 fprintf( TFile, "\n" );
01748
01749
01750 BB* temp = NULL;
01751 BBLIST * list;
01752 FOR_ALL_BB_SET_members( loop_bbs, temp ){
01753 fprintf( TFile, "PREDs of BB[%i] are:", BB_id(temp) );
01754 FOR_ALL_BB_PREDS(temp, list) {
01755 BB *pred = BBLIST_item(list);
01756 fprintf( TFile, " %i, ",BB_id(pred) );
01757 }
01758
01759 fprintf( TFile, "\nSUCCs of BB[%i] are:", BB_id(temp) );
01760 FOR_ALL_BB_SUCCS(temp, list) {
01761 BB *succ = BBLIST_item(list);
01762 fprintf( TFile, " %i, ",BB_id(succ) );
01763 }
01764 fprintf( TFile, "\n" );
01765 }
01766 }
01767
01768 if( Ignore_Ugly_Loop() ){
01769 if( _trace ){
01770 fprintf( TFile, " -_- ignored since it's ugly loop, or not real loop\n");
01771 }
01772 fprintf( TFile, " Number of LICM: 0\n" );
01773 fprintf( TFile, "======= Finished Loop Invariant Code Motion ====\n" );
01774 return 0;
01775 }
01776
01777
01778 Identify_Loop_Invariants ();
01779
01780
01781
01782
01783 INT32 code_motion_num = 0;
01784 for (OP_Vector_Iter iter = _loop_invar_defs.begin ();
01785 iter != _loop_invar_defs.end (); iter++) {
01786
01787 OP* linvar = *iter;
01788 LI_OP_INFO* opinfo = Get_OP_Info (linvar);
01789
01790 BOOL perform = TRUE;
01791
01792 if (!opinfo->Def_Loop_Invar ()) {
01793
01794
01795
01796
01797
01798
01799
01800 perform = FALSE;
01801 }
01802
01803 if (perform && Illegal_Or_Nonprofitable (linvar)) {
01804 perform = FALSE;
01805 }
01806
01807 if (!perform) {
01808
01809
01810
01811 Mark_Dep_OPs_As_Non_Loop_Invar (linvar);
01812 } else {
01813 if( !GCM_LICM_Skip_Op_Binary_Search(code_motion_num) ){
01814 Perform_Code_Motion (linvar);
01815 code_motion_num ++;
01816 }
01817 }
01818 }
01819
01820 if( _trace ){
01821 fprintf( TFile, " Number of LICM: %i\n", code_motion_num );
01822 fprintf( TFile, "======= Finished Loop Invariant Code Motion ====\n" );
01823 }
01824
01825 return code_motion_num;
01826 }
01827
01828
01829
01830
01831
01832
01833
01834
01835
01836 static void Append_Op_To_BB(OP * cand_op, BB *cand_bb )
01837 {
01838 OP *limit_op;
01839
01840
01841
01842 if( BB_loop_op(cand_bb) )
01843 limit_op = BB_loop_op(cand_bb);
01844 else
01845 limit_op = BB_xfer_op(cand_bb);
01846
01847 if( !limit_op && BB_zdl_body(cand_bb) ) {
01848 OP* last_op = BB_last_op(cand_bb);
01849 Is_True( OP_has_tag(last_op), ("zdl tail bb should have tag") );
01850
01851
01852 BB_Append_Op (cand_bb, cand_op);
01853 LABEL_IDX tag_idx = 0;
01854 tag_idx = Get_OP_Tag( last_op );
01855 Is_True( tag_idx > 0, ("incorrect tag index") );
01856 Reset_OP_has_tag( last_op );
01857 Set_OP_Tag( cand_op, tag_idx );
01858 }else{
01859 if (limit_op)
01860 BB_Insert_Op_Before (cand_bb, limit_op, cand_op);
01861 else
01862 BB_Append_Op (cand_bb, cand_op);
01863 }
01864 }
01865
01866 void LOOP_INVAR_CODE_MOTION :: Perform_Code_Motion (OP* linvar)
01867 {
01868 if( _trace ){
01869 fprintf( TFile, " -- before moving following OP, from BB:%i to BB:%i\n",
01870 BB_id(OP_bb(linvar)), BB_id(_prolog) );
01871 Print_OP_No_SrcLine( linvar );
01872 Print_BB_No_Srclines( OP_bb(linvar) );
01873 Print_BB_No_Srclines( _prolog );
01874 }
01875
01876 BB_Remove_Op( OP_bb(linvar), linvar );
01877 Append_Op_To_BB( linvar, _prolog );
01878
01879 if( _trace ){
01880 fprintf( TFile, " -- after moving following OP, from BB:%i to BB:%i\n",
01881 BB_id(OP_bb(linvar)), BB_id(_prolog) );
01882 Print_OP_No_SrcLine( linvar );
01883 Print_BB_No_Srclines( OP_bb(linvar) );
01884 Print_BB_No_Srclines( _prolog );
01885 }
01886
01887
01888
01889 }
01890
01891
01892
01893
01894
01895
01896
01897
01898
01899
01900
01901 static float
01902 Count_Loop_Interation (LOOP_DESCR* l) {
01903
01904 LOOPINFO* li LOOP_DESCR_loopinfo(l);
01905
01906 TN* trip_count = NULL;
01907 if (li) {
01908 trip_count = LOOPINFO_trip_count_tn(li);
01909 }
01910
01911 if (trip_count && TN_is_constant(trip_count) &&
01912 TN_has_value(trip_count)) {
01913 return (float)TN_value(trip_count);
01914 }
01915
01916 BBLIST* p;
01917 BB_SET* body = LOOP_DESCR_bbset(l);
01918 BB* head = LOOP_DESCR_loophead(l);
01919 float f = 0.0f;
01920 FOR_ALL_BB_PREDS (head, p) {
01921 BB* succ = BBLIST_item(p);
01922 if (!BB_SET_MemberP (body, succ)) {
01923 continue;
01924 }
01925
01926 BBLIST* bl = BB_Find_Succ (succ,head);
01927 f += BBLIST_freq(bl);
01928 }
01929
01930 return f;
01931 }
01932
01933
01934
01935
01936
01937
01938
01939
01940
01941
01942
01943
01944 static BOOL
01945 Skip_Loop_Invar_Code_Motion (LOOP_DESCR* loop) {
01946
01947 INT bb_num = 0 , op_num = 0;
01948 BB* bb;
01949 BB_SET* body = LOOP_DESCR_bbset(loop);
01950
01951 #define HOT_LOOP_FREQ (1000000)
01952 INT32 MAX_BB = 8, MAX_OP = 64;
01953
01954
01955
01956 bb = LOOP_DESCR_loophead(loop);
01957 if (BB_freq(bb) > HOT_LOOP_FREQ) {
01958 MAX_BB = 10; MAX_OP = 100;
01959 }
01960
01961 FOR_ALL_BB_SET_members (body, bb) {
01962
01963 if (BB_rotating_kernel (bb)) {
01964
01965
01966
01967
01968 return TRUE;
01969 }
01970
01971
01972
01973 if (BB_length(bb)) { ++ bb_num; }
01974
01975 if (bb_num > MAX_BB) { return TRUE; }
01976 op_num += BB_length(bb);
01977 if (op_num > MAX_OP) { return TRUE; }
01978 }
01979
01980
01981
01982 BB *head = LOOP_DESCR_loophead(loop);
01983 LOOPINFO *info = LOOP_DESCR_loopinfo(loop);
01984
01985 if (info && WN_Loop_Unimportant_Misc(LOOPINFO_wn(info))) {
01986 return TRUE;
01987 }
01988
01989 float f1 = Count_Loop_Interation (loop);
01990 float f2 = BB_freq(head);
01991
01992 return !(f1 > 1000 || f2 > 10000);
01993 }
01994
01995
01996
01997
01998
01999
02000
02001
02002
02003
02004
02005 static void
02006 Maintain_Dominator_Info (LOOP_DESCR* l, BB* prolog, MEM_POOL* mp) {
02007
02008
02009
02010 BB* head = LOOP_DESCR_loophead(l);
02011
02012 if (prolog) {
02013 BS* dom_pro = BS_Copy (BB_dom_set(head), mp);
02014 dom_pro = BS_Union1D (dom_pro, (BS_ELT)BB_id(prolog),mp);
02015 dom_pro = BS_Difference1D (dom_pro, (BS_ELT)BB_id(head));
02016 Set_BB_dom_set (prolog, dom_pro);
02017 }
02018
02019
02020
02021 for (BB* b = REGION_First_BB; b; b = BB_next(b)) {
02022
02023
02024
02025
02026 BS* dom_set = BB_dom_set (b);
02027 if (BS_MemberP (BB_dom_set(b), BB_id(head))) {
02028 dom_set = BS_Union1D (dom_set, BB_id(prolog), mp);
02029 Set_BB_dom_set (b, dom_set);
02030 }
02031 }
02032 }
02033
02034
02035
02036
02037
02038
02039
02040
02041
02042
02043 void
02044 Perform_Loop_Invariant_Code_Motion( LOOP_DESCR *loop,
02045 MEM_POOL *pool,
02046 BOOL ignore_tn_dep )
02047 {
02048 GRA_LIVE_Init (NULL);
02049
02050 LOOP_INVAR_CODE_MOTION licm( loop, ignore_tn_dep );
02051 licm.Perform_Code_Motion();
02052
02053 GRA_LIVE_Init (NULL);
02054 }
02055