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
00102 typedef mempool_allocator<OP*> OP_ALLOC;
00103 typedef std::vector<OP*,OP_ALLOC> OP_Vector;
00104 typedef OP_Vector::iterator OP_Vector_Iter;
00105
00106
00107 typedef mempool_allocator<BB*> BB_ALLOC;
00108 typedef std::list<BB*,BB_ALLOC> BB_Lst;
00109 typedef BB_Lst::iterator BB_Lst_Iter;
00110
00111
00112
00113
00114 class LI_TN_INFO {
00115 private:
00116 OP_Vector _def_list;
00117 OP_Vector _use_list;
00118 INT32 _inloop_def_num;
00119 INT32 _inloop_use_num;
00120 mBOOL _loop_invar;
00121
00122 public:
00123
00124 LI_TN_INFO (MEM_POOL* mp):
00125 _def_list(mp), _use_list(mp), _loop_invar(FALSE),
00126 _inloop_def_num(0), _inloop_use_num(0) {};
00127 ~LI_TN_INFO (void) {} ;
00128
00129 void Add_Def_OP (OP* o) { _def_list.push_back (o); }
00130 void Add_Use_OP (OP* o) { _use_list.push_back (o); }
00131
00132 const OP_Vector* Defs (void) const { return &_def_list; }
00133 const OP_Vector* Uses (void) const { return &_use_list; }
00134
00135 BOOL Is_Loop_Invar (void) const { return _loop_invar; }
00136 void Set_Loop_Invar (void) { _loop_invar = TRUE; }
00137 void Reset_Loop_Invar (void) { _loop_invar = FALSE;}
00138
00139 INT32 Inloop_Def_Num (void) const { return _inloop_def_num; }
00140 INT32 Dec_Inloop_Def_Num (void) { return --_inloop_def_num; }
00141 INT32 Inc_Inloop_Def_Num (void) { return ++_inloop_def_num; }
00142
00143 INT32 Inloop_Use_Num (void) const { return _inloop_use_num; }
00144 INT32 Dec_Inloop_Use_Num (void) { return --_inloop_use_num; }
00145 INT32 Inc_Inloop_Use_Num (void) { return ++_inloop_use_num; }
00146 };
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158 class LOOP_TOPO_ITER {
00159 private:
00160 MEM_POOL* _mp;
00161 BB_SET* _visit;
00162 LOOP_DESCR* _loop;
00163 BB* _cur;
00164 BB_Lst _seq;
00165
00166 public:
00167 LOOP_TOPO_ITER (LOOP_DESCR* l, MEM_POOL* mp);
00168 ~LOOP_TOPO_ITER (void) {};
00169 BOOL end (void) const { return _seq.empty (); }
00170
00171 LOOP_TOPO_ITER& operator++ (void);
00172
00173
00174 BB* operator*(void) const { return _cur; }
00175 };
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188 class LI_OP_INFO_MGR;
00189 class LI_OP_INFO {
00190 friend class LI_OP_INFO_MGR;
00191 private:
00192 mBOOL _def_loop_invar;
00193 INT16 _level;
00194
00195
00196
00197 void Set_Level (INT32 l) { _level = (INT16)l; }
00198
00199 public:
00200 LI_OP_INFO (void): _def_loop_invar(FALSE), _level(0) {};
00201 ~LI_OP_INFO (void) {};
00202 BOOL Def_Loop_Invar (void) const { return _def_loop_invar; }
00203 void Set_Def_Loop_Invar (void) { _def_loop_invar = TRUE; }
00204 void Reset_Def_Loop_Invar (void) { _def_loop_invar = FALSE;}
00205
00206 INT32 Level (void) const { return (INT32)_level; }
00207 BOOL Invalid_Level (void) const { return _level == -1; }
00208 };
00209
00210 class LI_OP_INFO_MGR {
00211 private:
00212 MEM_POOL* _mp;
00213 LOOP_DESCR* _loop;
00214
00215 INT16 _bb_num;
00216 INT16 _op_num;
00217 INT16 _max_level;
00218
00219 typedef struct bb_map_bb_pair{
00220 BB_OP_MAP op_info;
00221 BB* bb;
00222 } BB_MAP_BB_PAIR;
00223 BB_MAP_BB_PAIR* _info;
00224
00225
00226 inline const BB_MAP_BB_PAIR* Idx (BB* b) const;
00227
00228 void Init_OP_Level (void);
00229
00230 public:
00231 LI_OP_INFO_MGR (LOOP_DESCR* l, MEM_POOL* mp);
00232 ~LI_OP_INFO_MGR (void) {} ;
00233
00234 LI_OP_INFO* Get (OP*) const;
00235 void Set (OP*, LI_OP_INFO*);
00236
00237 INT32 BB_Num (void) const { return (INT32)_bb_num; }
00238 INT32 OP_Num (void) const { return (INT32)_op_num; }
00239 INT32 Max_Level (void) const { return (INT32)_max_level;}
00240
00241 BOOL It_is_Tiny_Loop (void) const {return _op_num <= 8;}
00242 BOOL It_is_Small_Loop (void) const {return _op_num<16 && _op_num >=8;}
00243 BOOL It_is_Mediate_Sized_Loop (void) const
00244 { return _op_num < 32 && _op_num >= 16; }
00245 BOOL It_is_Large_Loop (void) const { return _op_num >= 32; }
00246 BOOL It_is_Huge_Loop (void) const { return _op_num >= 128; }
00247 BOOL Very_Hot_Loop (void) const {
00248 BB* b = LOOP_DESCR_loophead(_loop);
00249 return BB_freq(b) > 1000000;
00250 }
00251 };
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264 void
00265 LI_OP_INFO_MGR :: Init_OP_Level (void) {
00266
00267
00268
00269 INT32 start_level = 0;
00270 BB* header = LOOP_DESCR_loophead (_loop);
00271
00272 for (LOOP_TOPO_ITER iter(_loop, _mp); !iter.end (); ++iter) {
00273 BB* cur_bb = *iter;
00274
00275
00276
00277 if (cur_bb != header) {
00278 BBLIST* P;
00279 FOR_ALL_BB_PREDS (cur_bb,P) {
00280 BB* pred = BBLIST_item(P);
00281 if (BB_loop_head_bb (pred) != header) {
00282
00283 continue;
00284 }
00285
00286 OP* last = BB_last_op (pred);
00287 if (last) {
00288 INT32 l = Get(last)->Level ();
00289 start_level = MAX(start_level, l);
00290 }
00291 }
00292 }
00293
00294 OP* op;
00295 FOR_ALL_BB_OPs (cur_bb, op) {
00296 LI_OP_INFO* oi = Get(op);
00297 oi->Set_Level (start_level++);
00298 }
00299
00300 }
00301 }
00302
00303 LI_OP_INFO_MGR :: LI_OP_INFO_MGR (LOOP_DESCR* l, MEM_POOL* mp):
00304 _loop (l), _mp(mp) {
00305
00306 BB_SET* bbs = LOOP_DESCR_bbset (l);
00307 BB* bb;
00308 _bb_num = 0 ;
00309 _op_num = 0;
00310
00311
00312
00313 FOR_ALL_BB_SET_members (bbs, bb) {
00314 _bb_num ++; _op_num += BB_length(bb);
00315 }
00316
00317
00318
00319 _info = TYPE_MEM_POOL_ALLOC_N (BB_MAP_BB_PAIR, _mp, _bb_num);
00320 INT i = 0;
00321 FOR_ALL_BB_SET_members (bbs, bb) {
00322 _info[i].op_info = BB_OP_MAP_Create (bb, _mp);
00323 _info[i].bb = bb;
00324
00325 OP* o;
00326 FOR_ALL_BB_OPs (bb, o) {
00327 LI_OP_INFO* oi = CXX_NEW (LI_OP_INFO, _mp);
00328 BB_OP_MAP_Set (_info[i].op_info, o, oi);
00329 }
00330
00331 i ++;
00332 }
00333
00334
00335
00336
00337
00338
00339 for (INT i1 = _bb_num - 2; i1 >= 0; i1 --) {
00340 for (INT i2 = i1; i2 >= 0 ; i2 --) {
00341 if (BB_id(_info[i2+1].bb) < BB_id(_info[i2].bb)) {
00342
00343 BB_MAP_BB_PAIR t = _info[i2];
00344 _info[i2] = _info[i2+1]; _info[i2] = t;
00345 }
00346 }
00347 }
00348
00349 Init_OP_Level ();
00350 }
00351
00352
00353
00354
00355
00356
00357
00358
00359 inline const LI_OP_INFO_MGR::BB_MAP_BB_PAIR*
00360 LI_OP_INFO_MGR :: Idx (BB* b) const {
00361
00362 mBB_NUM id = BB_id (b);
00363 INT32 low=1, high=_bb_num, mid;
00364
00365 do {
00366 mid = (low + high)/2;
00367 mBB_NUM t = BB_id (_info[mid-1].bb);
00368
00369 if (t == id) return _info+mid-1;
00370 if (t < id) { low = mid + 1; continue; }
00371 high = mid - 1;
00372 } while (low <= high);
00373
00374 Is_True (FALSE, ("No BB_MAP_BB_PAIR associated with BB:%d", id));
00375 return NULL;
00376 }
00377
00378
00379
00380
00381
00382
00383
00384 LI_OP_INFO*
00385 LI_OP_INFO_MGR :: Get (OP* op) const {
00386
00387 const BB_MAP_BB_PAIR* t = Idx (OP_bb(op));
00388 return (LI_OP_INFO*) BB_OP_MAP_Get (t->op_info, op);
00389 }
00390
00391
00392
00393
00394
00395
00396
00397 void
00398 LI_OP_INFO_MGR :: Set (OP* op, LI_OP_INFO* info) {
00399 const BB_MAP_BB_PAIR* t = Idx (OP_bb(op));
00400 BB_OP_MAP_Set (t->op_info, op, info);
00401 }
00402
00403 LOOP_TOPO_ITER :: LOOP_TOPO_ITER (LOOP_DESCR* l, MEM_POOL* mp) : _mp(mp) {
00404 _loop = l;
00405
00406 _cur = LOOP_DESCR_loophead(l);
00407 _seq.push_back (_cur);
00408 _visit = BB_SET_Create_Empty (252, _mp);
00409 }
00410
00411
00412 LOOP_TOPO_ITER&
00413 LOOP_TOPO_ITER :: operator++ (void) {
00414
00415 if (end ()) { _cur = NULL; return *this; }
00416
00417 Is_True (_cur == *_seq.begin (),
00418 ("currently visited (BB:%d) is not the first element of visit-sequence",
00419 BB_id(_cur)));
00420
00421 BB_SET* body = LOOP_DESCR_bbset(_loop);
00422 BB* head = LOOP_DESCR_loophead(_loop);
00423
00424 _visit = BB_SET_Union1D (_visit, _cur, _mp);
00425 _seq.pop_front ();
00426
00427 BBLIST *s,*p;
00428 FOR_ALL_BB_SUCCS(_cur, s) {
00429
00430 BB* succ = BBLIST_item(s);
00431 if (!BB_SET_MemberP (body,succ)) { continue; }
00432 if (BB_SET_MemberP (_visit,succ)){ continue; }
00433
00434 BOOL all_pred_visited = TRUE;
00435 if (succ != head) {
00436
00437 FOR_ALL_BB_PREDS (succ, p) {
00438 BB* pred = BBLIST_item (p);
00439 if (!BB_SET_MemberP (_visit, pred)) {
00440 all_pred_visited = FALSE; break;
00441 }
00442 }
00443 }
00444
00445 if (all_pred_visited) { _seq.push_back (succ); }
00446 }
00447
00448 _cur = *_seq.begin ();
00449
00450 return *this;
00451 }
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464 class LOOP_INVAR_CODE_MOTION : public CXX_MEM_POOL {
00465
00466
00467
00468
00469 private:
00470 LOOP_DESCR* _loop;
00471 BB* _prolog;
00472 MEM_POOL* _mp;
00473
00474 TN_SET* _def_within_loop;
00475 GTN_SET* _liveout_defs;
00476
00477 hTN_MAP _tn_info;
00478 LI_OP_INFO_MGR _op_info;
00479 OP_Vector _loop_invar_defs;
00480
00481
00482 BB_Lst _loop_exits;
00483
00484 OP_Vector _ld_ops,
00485 _store_ops,
00486 _call_ops;
00487
00488 BOOL It_Is_Constant_TN (TN* t) const {
00489 return TN_is_const_reg(t) || TN_is_constant (t) || t == GP_TN; }
00490
00491 BOOL It_Is_Loop_Invar_TN (TN* t) const {
00492 LI_TN_INFO* i = (LI_TN_INFO*)hTN_MAP_Get (_tn_info,t);
00493 return i->Is_Loop_Invar ();
00494 }
00495
00496 LI_OP_INFO* Get_OP_Info (OP* o) const { return _op_info.Get (o); }
00497
00498 void Sanity_Check (void);
00499
00500 void Calc_Defs_Within_Loop_Body (void);
00501 void Calc_Liveout_Defs (void);
00502 void Collect_TN_Def_Use_Info (void);
00503 void Collect_Ld_St_Call (void);
00504 void Find_Out_All_Exits (void);
00505 void Misc_Init (void);
00506 BOOL Init (void);
00507
00508 void Mark_Dep_OPs_As_Non_Loop_Invar (OP* op);
00509
00510 void Identify_Loop_Invariants (void);
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531 BOOL TN_is_Loop_Constant (TN* tn);
00532 BOOL All_Reaching_Def_are_Outside_Of_Loop (OP *, INT opnd_idx);
00533 BOOL Unique_Reaching_Def_Inside_Loop (OP*, INT opdn_idx);
00534 BOOL Register_Para_Passing (OP* op);
00535 BOOL Alias_With_Call(OP*, OP* call);
00536 BOOL It_is_Fake_Loop_Invar (OP*);
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555 BOOL Def_Dominate_All_Use (OP*);
00556 BOOL Dom_All_Loop_Exits (BB* );
00557 inline BOOL Live_Out_Of_Loop (OP* ) const;
00558 BOOL Illegal_Or_Nonprofitable (OP* );
00559 void Perform_Code_Motion (OP* );
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569 BOOL Ignore_Loop_With_Few_Interation (void);
00570 BOOL Code_Motion_Is_Profitable (OP*);
00571
00572 public:
00573
00574
00575 LOOP_INVAR_CODE_MOTION (LOOP_DESCR* l, BB* prolog);
00576 ~LOOP_INVAR_CODE_MOTION (void) {}
00577
00578 INT32 Perform_Code_Motion (void);
00579
00580
00581
00582 BOOL Loop_Has_Call (void) const { return Is_Call_Loop(_loop);}
00583 const LOOP_DESCR* Loop (void) const { return _loop;}
00584
00585 void Dump (FILE* f=stderr);
00586 #ifdef Is_True_On
00587
00588
00589
00590 void gdb_dump (void);
00591 #endif
00592 };
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603 void
00604 LOOP_INVAR_CODE_MOTION :: Calc_Defs_Within_Loop_Body (void) {
00605
00606 BB_SET* bbs = LOOP_DESCR_bbset (_loop);
00607 BB* bb;
00608
00609 FOR_ALL_BB_SET_members (bbs, bb) {
00610 OP* op;
00611
00612 FOR_ALL_BB_OPs (bb, op) {
00613 for (INT i = OP_results (op) - 1; i >= 0; i--) {
00614 TN* res = OP_result(op, i);
00615 _def_within_loop = TN_SET_Union1D (_def_within_loop,res, _mp);
00616
00617 }
00618 }
00619 }
00620 }
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632 void
00633 LOOP_INVAR_CODE_MOTION :: Calc_Liveout_Defs (void) {
00634
00635 BB_SET* body = LOOP_DESCR_bbset (_loop);
00636
00637 for (BB_Lst_Iter iter = _loop_exits.begin ();
00638 iter != _loop_exits.end (); iter++) {
00639
00640 BB* exit_blk = *iter;
00641 BBLIST* s;
00642
00643 FOR_ALL_BB_SUCCS (exit_blk, s) {
00644 BB* succ = BBLIST_item (s);
00645 if (BB_SET_MemberP (body, succ)) { continue ; }
00646
00647 if (BB_bbregs(succ))
00648 _liveout_defs =
00649 GTN_SET_UnionD (_liveout_defs, BB_live_in (succ), _mp);
00650
00651 }
00652 }
00653 }
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664 void
00665 LOOP_INVAR_CODE_MOTION :: Collect_TN_Def_Use_Info (void) {
00666
00667 BB_SET* bbs = LOOP_DESCR_bbset(_loop);
00668 BB* bb;
00669
00670 FOR_ALL_BB_SET_members (bbs, bb) {
00671
00672 OP* op;
00673 FOR_ALL_BB_OPs (bb, op) {
00674
00675
00676 for (INT i = 0 ; i < OP_results(op); i++) {
00677
00678 TN* res = OP_result(op,i);
00679 if (It_Is_Constant_TN (res)) { continue; }
00680
00681 LI_TN_INFO* info;
00682 info = (LI_TN_INFO*)hTN_MAP_Get (_tn_info, res);
00683
00684 if (!info) {
00685 info = CXX_NEW(LI_TN_INFO(_mp), _mp);
00686 hTN_MAP_Set (_tn_info, res, (void*)info);
00687 }
00688
00689 info->Add_Def_OP (op);
00690 info->Inc_Inloop_Def_Num ();
00691
00692 }
00693
00694
00695
00696 for (INT i = 0; i < OP_opnds(op); i++) {
00697
00698 TN* opnd = OP_opnd(op,i);
00699 if (It_Is_Constant_TN (opnd)) { continue; }
00700
00701 LI_TN_INFO* info;
00702 info = (LI_TN_INFO*)hTN_MAP_Get (_tn_info, opnd);
00703
00704 if (!info) {
00705 info = CXX_NEW (LI_TN_INFO(_mp), _mp);
00706 hTN_MAP_Set (_tn_info, opnd, (void*)info);
00707 }
00708
00709 info->Add_Use_OP (op);
00710 info->Inc_Inloop_Use_Num ();
00711
00712 }
00713 }
00714 }
00715 }
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725 void
00726 LOOP_INVAR_CODE_MOTION :: Collect_Ld_St_Call (void) {
00727
00728 BB_SET* bbs = LOOP_DESCR_bbset(_loop);
00729 BB* bb;
00730
00731 FOR_ALL_BB_SET_members (bbs, bb) {
00732 OP* op;
00733 FOR_ALL_BB_OPs (bb,op) {
00734
00735 extern BOOL OP_like_store(OP *op);
00736
00737 if (OP_load (op)) { _ld_ops.push_back (op) ; continue; }
00738 if (OP_like_store (op)) { _store_ops.push_back(op); continue; }
00739 if (OP_call (op)) {
00740 _call_ops.push_back (op);
00741
00742
00743
00744 Set_Call_Loop (_loop);
00745 }
00746 }
00747 }
00748 }
00749
00750
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762
00763 void
00764 LOOP_INVAR_CODE_MOTION :: Find_Out_All_Exits (void) {
00765
00766 BB_SET* bbs = LOOP_DESCR_bbset(_loop);
00767 BB* bb;
00768
00769 FOR_ALL_BB_SET_members (bbs, bb) {
00770
00771 BBLIST *succs;
00772 FOR_ALL_BB_SUCCS(bb, succs) {
00773 BB *succ = BBLIST_item(succs);
00774 if (!BB_SET_MemberP(bbs, succ) &&
00775 find (_loop_exits.begin(),
00776 _loop_exits.end(), succ) == _loop_exits.end()) {
00777 _loop_exits.push_back (bb);
00778 }
00779 }
00780 }
00781 }
00782
00783 void
00784 LOOP_INVAR_CODE_MOTION :: Misc_Init (void) {
00785 }
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796 void
00797 LOOP_INVAR_CODE_MOTION :: Sanity_Check (void) {
00798
00799 #ifdef Is_True_On
00800
00801
00802
00803 BB_SET* bbs = LOOP_DESCR_bbset (_loop);
00804 BB* bb;
00805
00806 FOR_ALL_BB_SET_members (bbs, bb) {
00807 BB_Verify_OP_Order (bb);
00808 }
00809 #endif
00810 }
00811
00812 BOOL
00813 LOOP_INVAR_CODE_MOTION :: Init (void) {
00814
00815 _tn_info = hTN_MAP_Create (_mp);
00816
00817 _def_within_loop = TN_SET_Create_Empty (Last_TN + 1, _mp);
00818 _liveout_defs = TN_SET_Create_Empty (Last_TN + 1, _mp);
00819
00820 Find_Out_All_Exits ();
00821 Calc_Defs_Within_Loop_Body ();
00822 Calc_Liveout_Defs ();
00823 Collect_TN_Def_Use_Info ();
00824 Collect_Ld_St_Call ();
00825
00826 Misc_Init ();
00827
00828 return TRUE;
00829 }
00830
00831
00832 LOOP_INVAR_CODE_MOTION::LOOP_INVAR_CODE_MOTION (LOOP_DESCR* l, BB* prolog):
00833 CXX_MEM_POOL("Loop Invariant Code Motion", FALSE),
00834 _mp((*this)()), _loop_exits (_mp), _loop_invar_defs(_mp),
00835 _ld_ops (_mp), _store_ops(_mp), _call_ops(_mp),
00836 _loop(l), _op_info(l, _mp) {
00837
00838 _prolog = prolog;
00839
00840 Init ();
00841 }
00842
00843
00844
00845
00846
00847
00848
00849
00850
00851
00852 BOOL
00853 LOOP_INVAR_CODE_MOTION :: TN_is_Loop_Constant (TN* t) {
00854
00855 if (It_Is_Constant_TN (t)) { return TRUE; }
00856
00857 LI_TN_INFO* info;
00858 info = (LI_TN_INFO*)hTN_MAP_Get (_tn_info, t);
00859
00860 return info->Is_Loop_Invar();
00861 }
00862
00863
00864
00865
00866
00867
00868
00869
00870
00871 BOOL
00872 LOOP_INVAR_CODE_MOTION :: All_Reaching_Def_are_Outside_Of_Loop
00873 (OP* op, INT opnd_idx) {
00874
00875 TN* opnd = OP_opnd (op, opnd_idx);
00876
00877 Is_True (opnd,
00878 ("OP[%d] (of BB:%d)'s No.%d operand does not exist!",
00879 OP_map_idx(op), BB_id(OP_bb(op)), opnd_idx));
00880
00881
00882
00883 if (It_Is_Constant_TN (opnd)) { return TRUE; }
00884
00885 return !TN_SET_MemberP (_def_within_loop, opnd);
00886 }
00887
00888
00889
00890
00891
00892
00893
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907 BOOL
00908 LOOP_INVAR_CODE_MOTION :: Unique_Reaching_Def_Inside_Loop
00909 (OP* op, INT opnd_idx) {
00910
00911 BB* home = OP_bb (op);
00912
00913 TN* opnd = OP_opnd (op, opnd_idx);
00914 LI_TN_INFO* ti = (LI_TN_INFO*)hTN_MAP_Get (_tn_info, opnd);
00915 OP_Vector* ops = (OP_Vector*)ti->Defs ();
00916
00917 if (ops->size () != 1) {
00918
00919
00920
00921 return FALSE;
00922 }
00923
00924 OP* def = *ops->begin ();
00925
00926
00927
00928 if (OP_bb(op) != OP_bb(def)) {
00929 if (BB_SET_MemberP (BB_dom_set(home), OP_bb(def))) {
00930 return FALSE;
00931 }
00932 } else {
00933 if (OP_Precedes (op,def) || op == def) { return FALSE; }
00934 }
00935
00936 if (OP_has_predicate(op) && OP_opnd(op, OP_PREDICATE_OPND) != True_TN) {
00937
00938
00939
00940
00941
00942 return FALSE;
00943 }
00944
00945 return TRUE;
00946 }
00947
00948
00949
00950
00951
00952
00953
00954
00955
00956
00957
00958 BOOL
00959 LOOP_INVAR_CODE_MOTION :: Register_Para_Passing (OP* op) {
00960
00961 if (!BB_call(OP_bb(op))) { return FALSE; }
00962
00963 for (INT i = OP_results(op) - 1; i >= 0; i--) {
00964 TN* res = OP_result(op,i);
00965 if (!TN_register(res)) { continue; }
00966
00967 if (REGISTER_Is_Stacked_Output (TN_register_class(res),
00968 TN_register(res))) {
00969 return TRUE;
00970 }
00971 }
00972
00973 return FALSE;
00974 }
00975
00976
00977
00978
00979
00980
00981
00982
00983 void
00984 LOOP_INVAR_CODE_MOTION :: Mark_Dep_OPs_As_Non_Loop_Invar (OP* op) {
00985
00986 for (INT i = OP_results(op) - 1; i >= 0; i--) {
00987
00988 TN* res = OP_result(op, i);
00989 if (It_Is_Constant_TN (res)) { continue; }
00990
00991 LI_TN_INFO* tninfo = (LI_TN_INFO*)hTN_MAP_Get (_tn_info, res);
00992 OP_Vector* ops = (OP_Vector*)tninfo->Uses ();
00993
00994 for (OP_Vector_Iter iter = ops->begin ();
00995 iter != ops->end (); iter++) {
00996
00997 OP* use = *iter;
00998 LI_OP_INFO* opinfo = Get_OP_Info (use);
00999 opinfo->Reset_Def_Loop_Invar ();
01000 }
01001 }
01002 }
01003
01004
01005
01006
01007
01008
01009
01010
01011
01012
01013
01014
01015
01016
01017
01018
01019
01020
01021
01022
01023
01024
01025
01026
01027
01028
01029
01030
01031
01032
01033
01034
01035 void
01036 LOOP_INVAR_CODE_MOTION :: Identify_Loop_Invariants (void) {
01037
01038 for (LOOP_TOPO_ITER iter(_loop, _mp); !iter.end (); ++iter) {
01039
01040 BB* b = *iter;
01041 OP* op;
01042
01043 FOR_ALL_BB_OPs (b, op) {
01044 BOOL it_is;
01045 it_is = TRUE;
01046
01047 for (INT i = OP_opnds (op) - 1; i >= 0 && it_is; i--) {
01048
01049 TN* opnd = OP_opnd(op,i);
01050 it_is =
01051 TN_is_Loop_Constant (opnd) ||
01052 All_Reaching_Def_are_Outside_Of_Loop (op, i) ||
01053 It_Is_Loop_Invar_TN (opnd) &&
01054 Unique_Reaching_Def_Inside_Loop (op, i);
01055 }
01056
01057 if (OP_xfer (op) || OP_call (op)) {
01058
01059
01060 it_is = TRUE;
01061 continue;
01062 }
01063
01064
01065
01066
01067 if (it_is && Register_Para_Passing (op)) {
01068 it_is = FALSE;
01069 }
01070
01071
01072
01073
01074 for (INT i = OP_results (op) - 1; i >= 0; i--) {
01075 TN* res = OP_result (op, i);
01076
01077 if (It_Is_Constant_TN (res)) continue;
01078
01079 LI_TN_INFO* tninfo;
01080 tninfo = (LI_TN_INFO*) hTN_MAP_Get (_tn_info, res);
01081 if (tninfo->Inloop_Def_Num () != 1) { it_is = FALSE; }
01082
01083 if (it_is) {
01084 tninfo->Set_Loop_Invar ();
01085 } else {
01086 tninfo->Reset_Loop_Invar ();
01087 break;
01088 }
01089
01090 }
01091
01092 if (it_is) {
01093
01094
01095
01096
01097
01098 _loop_invar_defs.push_back (op);
01099 _op_info.Get(op)->Set_Def_Loop_Invar ();
01100 }
01101
01102 }
01103
01104 }
01105 }
01106
01107 BOOL
01108 LOOP_INVAR_CODE_MOTION :: Alias_With_Call (OP* op, OP* call) {
01109
01110 BOOL alias =
01111 !CG_DEP_Can_OP_Move_Across_Call (op, call, TRUE, TRUE) ||
01112 !CG_DEP_Can_OP_Move_Across_Call (op, call, FALSE, TRUE);
01113
01114 if (!alias) { return FALSE; }
01115
01116
01117
01118
01119
01120
01121
01122
01123
01124 if (OP_code(op) != TOP_addl) { return TRUE; }
01125
01126
01127
01128
01129 for (INT i = 0; i < OP_opnds(op); i++) {
01130 TN* opnd = OP_opnd(op,i);
01131 if (!It_Is_Constant_TN (opnd)) return TRUE;
01132 }
01133
01134 for (INT i = 0; i < OP_results(op); i++) {
01135
01136 TN* result = OP_result(op, i);
01137 if (TN_is_dedicated(result)) { return TRUE; }
01138
01139 REGISTER reg = TN_register(result);
01140 if (reg == REGISTER_UNDEFINED) continue;
01141 ISA_REGISTER_CLASS rclass = TN_register_class (result);
01142
01143
01144
01145 if(REGISTER_SET_MemberP(REGISTER_CLASS_function_value(rclass), reg) ||
01146 REGISTER_SET_MemberP(REGISTER_CLASS_function_argument(rclass),
01147 reg) ||
01148 REGISTER_SET_MemberP(REGISTER_CLASS_caller_saves(rclass), reg)) {
01149 return TRUE;
01150 }
01151
01152 #ifdef HAS_STACKED_REGISTERS
01153 if (REGISTER_Is_Stacked_Output(rclass, reg)) {
01154 return TRUE;
01155 }
01156 #endif
01157 }
01158
01159 return FALSE;
01160 }
01161
01162 BOOL
01163 LOOP_INVAR_CODE_MOTION :: It_is_Fake_Loop_Invar (OP* op) {
01164
01165 UINT8 omega = 0;
01166 BOOL definite=FALSE;
01167
01168 if (OP_store (op)) { return TRUE; }
01169
01170 if (Loop_Has_Call ()) {
01171 for (OP_Vector_Iter iter = _call_ops.begin ();
01172 iter != _call_ops.end (); iter++) {
01173
01174 if (Alias_With_Call (op, *iter)) { return TRUE; }
01175 }
01176 }
01177
01178 if (OP_load (op)) {
01179 for (OP_Vector_Iter st_iter = _store_ops.begin ();
01180 st_iter != _store_ops.end (); st_iter ++) {
01181
01182 OP* op_like_st = *st_iter;
01183 if (!OP_store (op_like_st)) {
01184
01185
01186
01187 return TRUE;
01188 }
01189
01190 if (CG_DEP_Mem_Ops_Alias (op, op_like_st, NULL)) {
01191 return TRUE;
01192 }
01193 }
01194 }
01195
01196 return FALSE;
01197 }
01198
01199
01200
01201
01202
01203
01204
01205
01206
01207
01208 BOOL
01209 LOOP_INVAR_CODE_MOTION :: Def_Dominate_All_Use (OP* linvar) {
01210
01211 BB* home = OP_bb (linvar);
01212
01213 for (INT i=0 ; i < OP_results(linvar); i++) {
01214
01215 TN* res = OP_result(linvar, i);
01216 if (It_Is_Constant_TN (res)) { continue; }
01217
01218 LI_TN_INFO* info;
01219 info = (LI_TN_INFO*)hTN_MAP_Get (_tn_info, res);
01220 Is_True (info,
01221 ("LI_TN_INFO for OP:%d of BB:%d does not exist",
01222 OP_map_idx(linvar), BB_id (OP_bb(linvar))));
01223
01224 OP_Vector* ops = (OP_Vector*)info->Uses ();
01225
01226
01227
01228 for (OP_Vector_Iter iter = ops->begin ();
01229 iter != ops->end (); iter++) {
01230
01231 OP* o = *iter;
01232 BB* t = OP_bb (o);
01233
01234
01235
01236
01237
01238 if (!BB_SET_MemberP (BB_dom_set(t), home)) {
01239 return FALSE;
01240 } else if (t == home) {
01241 if (!OP_Precedes (linvar, o)) { return FALSE; }
01242 }
01243 }
01244 }
01245 }
01246
01247
01248
01249
01250
01251
01252
01253
01254 BOOL
01255 LOOP_INVAR_CODE_MOTION :: Dom_All_Loop_Exits (BB* b) {
01256
01257 BOOL no_exit = TRUE;
01258
01259 for (BB_Lst_Iter iter = _loop_exits.begin ();
01260 iter != _loop_exits.end (); iter++) {
01261
01262 BB* exit_bb = *iter;
01263 if (!BB_SET_MemberP (BB_dom_set(exit_bb), b)) { return FALSE; }
01264
01265 no_exit = FALSE;
01266 }
01267
01268
01269
01270
01271 return !no_exit;
01272 }
01273
01274
01275
01276
01277
01278
01279
01280
01281
01282
01283 inline BOOL
01284 LOOP_INVAR_CODE_MOTION :: Live_Out_Of_Loop (OP* op) const {
01285
01286 for (INT i = OP_results (op) - 1; i >= 0; i--) {
01287 TN* res = OP_result(op, i);
01288
01289 if (!TN_is_constant(res) && TN_is_global_reg(res) &&
01290 GTN_SET_MemberP (_liveout_defs, res)) {
01291 return TRUE;
01292 }
01293 }
01294 return FALSE;
01295 }
01296
01297
01298
01299
01300
01301
01302
01303
01304
01305
01306
01307
01308
01309
01310 BOOL
01311 LOOP_INVAR_CODE_MOTION :: Code_Motion_Is_Profitable (OP* op) {
01312
01313 BB* loop_ent = LOOP_DESCR_loophead(_loop);
01314 BB* home = OP_bb (op);
01315
01316
01317
01318
01319
01320
01321 #define PROG_SCALE (100)
01322 #define LOW_PROB_FOR_ALU_OP (70)
01323 #define LOW_PROB_FOR_LD_OP (40)
01324 #define LOW_PROB_FOR_LONG_LATENCY (40)
01325
01326 float freq1 = BB_freq (loop_ent), freq2 = BB_freq (home);
01327 freq1 = (freq1 < 1.0f) ? 1.0f : freq1;
01328 INT32 div = (INT32)(freq2 * PROG_SCALE/ freq1);
01329
01330 if (CGTARG_Is_Long_Latency (OP_code (op))) {
01331 if (div < LOW_PROB_FOR_LONG_LATENCY) { return FALSE; }
01332 } else if (OP_load (op)) {
01333 if (div < LOW_PROB_FOR_LD_OP) { return FALSE; }
01334 } else {
01335 if (div < LOW_PROB_FOR_ALU_OP) { return FALSE; }
01336 }
01337
01338
01339
01340 if (Live_Out_Of_Loop (op)) {
01341
01342 return TRUE;
01343 }
01344
01345 if (_op_info.It_is_Tiny_Loop ()) { return TRUE; }
01346 if (_op_info.It_is_Huge_Loop ()) { return FALSE;}
01347 if (_op_info.It_is_Large_Loop () && !_op_info.Very_Hot_Loop ()) {
01348 return FALSE;
01349 }
01350
01351
01352
01353
01354
01355
01356
01357
01358
01359
01360
01361
01362
01363
01364
01365
01366
01367
01368
01369
01370
01371
01372
01373
01374
01375
01376 return TRUE;
01377 }
01378
01379
01380
01381
01382
01383
01384
01385
01386
01387
01388
01389
01390
01391 BOOL
01392 LOOP_INVAR_CODE_MOTION :: Ignore_Loop_With_Few_Interation (void) {
01393
01394 BB* loop_ent = LOOP_DESCR_loophead(_loop);
01395 float f = 0.0f;
01396
01397 BBLIST* pred;
01398 FOR_ALL_BB_PREDS (loop_ent,pred) {
01399 BB* b = BBLIST_item(pred);
01400 f += BB_freq (b);
01401 }
01402
01403 f = (f < 1.0f) ? 1.0f : f;
01404 return (BB_freq (loop_ent) - f) < 10^5;
01405 }
01406
01407
01408
01409
01410
01411
01412
01413
01414
01415
01416
01417
01418
01419 BOOL
01420 LOOP_INVAR_CODE_MOTION :: Illegal_Or_Nonprofitable (OP* loopinvar) {
01421
01422 BB* home = OP_bb (loopinvar);
01423
01424 if (!Def_Dominate_All_Use (loopinvar)) {
01425 return TRUE;
01426 }
01427
01428
01429
01430
01431 BOOL spec = !Dom_All_Loop_Exits (home);
01432
01433 if (spec) {
01434
01435
01436
01437 if (!CGTARG_Can_Be_Speculative (loopinvar)) {
01438 return TRUE;
01439 }
01440
01441
01442
01443 if (CGTARG_Is_OP_Speculative (loopinvar)) {
01444 return TRUE;
01445 }
01446
01447
01448 if (Live_Out_Of_Loop (loopinvar)) {
01449 return TRUE;
01450 }
01451 }
01452
01453 if (!Code_Motion_Is_Profitable (loopinvar)) {
01454 return TRUE;
01455 }
01456
01457
01458
01459
01460
01461 if (It_is_Fake_Loop_Invar (loopinvar)) {
01462 return TRUE;
01463 }
01464
01465 return FALSE;
01466 }
01467
01468
01469
01470
01471
01472
01473
01474
01475
01476
01477
01478
01479
01480
01481 INT32
01482 LOOP_INVAR_CODE_MOTION :: Perform_Code_Motion (void) {
01483
01484 Identify_Loop_Invariants ();
01485
01486
01487
01488
01489 INT32 code_motion_num = 0;
01490 for (OP_Vector_Iter iter = _loop_invar_defs.begin ();
01491 iter != _loop_invar_defs.end (); iter++) {
01492
01493 OP* linvar = *iter;
01494 LI_OP_INFO* opinfo = Get_OP_Info (linvar);
01495
01496 BOOL perform = TRUE;
01497
01498 if (!opinfo->Def_Loop_Invar ()) {
01499
01500
01501
01502
01503
01504
01505
01506 perform = FALSE;
01507 }
01508
01509 if (perform && Illegal_Or_Nonprofitable (linvar)) {
01510 perform = FALSE;
01511 }
01512
01513 if (!perform) {
01514
01515
01516
01517 Mark_Dep_OPs_As_Non_Loop_Invar (linvar);
01518 } else {
01519 Perform_Code_Motion (linvar);
01520 code_motion_num ++;
01521 }
01522 }
01523 return code_motion_num;
01524 }
01525
01526
01527
01528
01529
01530
01531
01532
01533
01534 void
01535 LOOP_INVAR_CODE_MOTION :: Perform_Code_Motion (OP* linvar) {
01536
01537 BB_Move_Op_To_End (_prolog, OP_bb(linvar), linvar);
01538
01539
01540
01541
01542 }
01543
01544
01545
01546
01547
01548
01549
01550
01551
01552
01553
01554 static float
01555 Count_Loop_Interation (LOOP_DESCR* l) {
01556
01557 LOOPINFO* li LOOP_DESCR_loopinfo(l);
01558
01559 TN* trip_count = NULL;
01560 if (li) {
01561 trip_count = LOOPINFO_trip_count_tn(li);
01562 }
01563
01564 if (trip_count && TN_is_constant(trip_count) &&
01565 TN_has_value(trip_count)) {
01566 return (float)TN_value(trip_count);
01567 }
01568
01569 BBLIST* p;
01570 BB_SET* body = LOOP_DESCR_bbset(l);
01571 BB* head = LOOP_DESCR_loophead(l);
01572 float f = 0.0f;
01573 FOR_ALL_BB_PREDS (head, p) {
01574 BB* succ = BBLIST_item(p);
01575 if (!BB_SET_MemberP (body, succ)) {
01576 continue;
01577 }
01578
01579 BBLIST* bl = BB_Find_Succ (succ,head);
01580 f += BBLIST_freq(bl);
01581 }
01582
01583 return f;
01584 }
01585
01586
01587
01588
01589
01590
01591
01592
01593
01594
01595
01596
01597 static BOOL
01598 Skip_Loop_Invar_Code_Motion (LOOP_DESCR* loop) {
01599
01600 INT bb_num = 0 , op_num = 0;
01601 BB* bb;
01602 BB_SET* body = LOOP_DESCR_bbset(loop);
01603
01604 #define HOT_LOOP_FREQ (1000000)
01605 INT32 MAX_BB = 8, MAX_OP = 64;
01606
01607
01608
01609 bb = LOOP_DESCR_loophead(loop);
01610 if (BB_freq(bb) > HOT_LOOP_FREQ) {
01611 MAX_BB = 10; MAX_OP = 100;
01612 }
01613
01614 FOR_ALL_BB_SET_members (body, bb) {
01615
01616 if (BB_rotating_kernel (bb)) {
01617
01618
01619
01620
01621 return TRUE;
01622 }
01623
01624
01625
01626 if (BB_length(bb)) { ++ bb_num; }
01627
01628 if (bb_num > MAX_BB) { return TRUE; }
01629 op_num += BB_length(bb);
01630 if (op_num > MAX_OP) { return TRUE; }
01631 }
01632
01633
01634
01635 BB *head = LOOP_DESCR_loophead(loop);
01636 LOOPINFO *info = LOOP_DESCR_loopinfo(loop);
01637
01638 if (info && WN_Loop_Unimportant_Misc(LOOPINFO_wn(info))) {
01639 return TRUE;
01640 }
01641
01642 float f1 = Count_Loop_Interation (loop);
01643 float f2 = BB_freq(head);
01644
01645 return !(f1 > 1000 || f2 > 10000);
01646 }
01647
01648
01649
01650
01651
01652
01653
01654
01655
01656
01657
01658 static void
01659 Maintain_Dominator_Info (LOOP_DESCR* l, BB* prolog, MEM_POOL* mp) {
01660
01661
01662
01663 BB* head = LOOP_DESCR_loophead(l);
01664
01665 if (prolog) {
01666 BS* dom_pro = BS_Copy (BB_dom_set(head), mp);
01667 dom_pro = BS_Union1D (dom_pro, (BS_ELT)BB_id(prolog),mp);
01668 dom_pro = BS_Difference1D (dom_pro, (BS_ELT)BB_id(head));
01669 Set_BB_dom_set (prolog, dom_pro);
01670 }
01671
01672
01673
01674 for (BB* b = REGION_First_BB; b; b = BB_next(b)) {
01675
01676
01677
01678
01679 BS* dom_set = BB_dom_set (b);
01680 if (BS_MemberP (BB_dom_set(b), BB_id(head))) {
01681 dom_set = BS_Union1D (dom_set, BB_id(prolog), mp);
01682 Set_BB_dom_set (b, dom_set);
01683 }
01684 }
01685 }
01686
01687 static BB*
01688 Create_Loop_Prologue (LOOP_DESCR* l) {
01689
01690 BB* lhead = LOOP_DESCR_loophead(l);
01691 BB_SET* body = LOOP_DESCR_bbset(l);
01692 BB* like_prolog = NULL;
01693
01694 BBLIST* p;
01695 FOR_ALL_BB_PREDS (lhead, p) {
01696 BB* pred = BBLIST_item (p);
01697 if (BB_SET_MemberP (body, pred)) { continue; }
01698
01699 if (like_prolog) {
01700 like_prolog = NULL; break;
01701 } else {
01702 like_prolog = pred;
01703 }
01704 }
01705
01706 if (like_prolog) {
01707 if (BB_kind (like_prolog) != BBKIND_GOTO ||
01708 BB_branch_op (like_prolog)) {
01709 like_prolog = NULL;
01710 }
01711 }
01712
01713 if (like_prolog) {
01714 Set_BB_gra_spill(like_prolog);
01715 }
01716
01717 Is_True (!like_prolog || BB_prev(lhead) == like_prolog,
01718 ("BB:%d's does not fall through to BB:%d",
01719 BB_id(like_prolog), BB_id(lhead)));
01720
01721 return like_prolog ? like_prolog :
01722 CG_LOOP_Gen_And_Prepend_To_Prolog (lhead,l);
01723 }
01724
01725
01726
01727
01728
01729
01730
01731
01732
01733
01734 void
01735 Perform_Loop_Invariant_Code_Motion (void) {
01736
01737 CXX_MEM_POOL local_mp("LICM", FALSE);
01738
01739 MEM_POOL loop_descr_pool;
01740 MEM_POOL_Initialize(&loop_descr_pool, "loop_descriptors", TRUE);
01741 MEM_POOL_Push (&loop_descr_pool);
01742
01743
01744
01745 GRA_LIVE_Init (NULL);
01746 Calculate_Dominators ();
01747
01748 for (LOOP_DESCR *l = LOOP_DESCR_Detect_Loops(&loop_descr_pool);
01749 l; l = LOOP_DESCR_next(l)) {
01750
01751 if (Skip_Loop_Invar_Code_Motion (l)) { continue; }
01752
01753 BB* prolog;
01754 prolog = Create_Loop_Prologue (l);
01755 if (!prolog) { continue; }
01756 Reset_BB_gra_spill (prolog);
01757
01758 Maintain_Dominator_Info (l, prolog, local_mp());
01759
01760 LOOP_INVAR_CODE_MOTION licm (l, prolog);
01761 licm.Perform_Code_Motion ();
01762 }
01763
01764 GRA_LIVE_Init (NULL);
01765 Free_Dominators_Memory ();
01766
01767 MEM_POOL_Pop (&loop_descr_pool);
01768 MEM_POOL_Delete(&loop_descr_pool);
01769
01770 }