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
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106 #ifndef opt_vn_ivc_INCLUDED
00107 #define opt_vn_ivc_INCLUDED "opt_vn_ivc.h"
00108
00109 #include <vector>
00110 #include <iterator>
00111 #include "opt_vn_expr.h"
00112 #include "opt_vn.h"
00113
00114 using std::vector;
00115
00116
00117
00118
00119
00120
00121
00122
00123 inline BOOL IVC_Enabled()
00124 {
00125 return (WOPT_Enable_Vn_Ivc > 0);
00126 }
00127
00128 inline BOOL IVC_Maximize_Live_Ranges()
00129 {
00130 return (WOPT_Enable_Vn_Ivc >= 1 && WOPT_Enable_Vn_Ivc <= 4);
00131 }
00132
00133 inline BOOL IVC_Minimize_Live_Ranges()
00134 {
00135 return !IVC_Maximize_Live_Ranges();
00136 }
00137
00138 inline BOOL IVC_Conservative()
00139 {
00140 return (WOPT_Enable_Vn_Ivc == 1 || WOPT_Enable_Vn_Ivc == 2 ||
00141 WOPT_Enable_Vn_Ivc == 5 || WOPT_Enable_Vn_Ivc == 6);
00142 }
00143
00144 inline BOOL IVC_Aggressive()
00145 {
00146 return !IVC_Conservative();
00147 }
00148
00149 inline BOOL IVC_LoopInvariant_Diff()
00150 {
00151 return (WOPT_Enable_Vn_Ivc == 1 || WOPT_Enable_Vn_Ivc == 3 ||
00152 WOPT_Enable_Vn_Ivc == 5 || WOPT_Enable_Vn_Ivc == 7);
00153 }
00154
00155 inline BOOL IVC_Only_Literal_Diff()
00156 {
00157 return !IVC_LoopInvariant_Diff();
00158 }
00159
00160
00161
00162
00163
00164 typedef INT32 ENTRY_IDX;
00165 #define INVALID_ENTRY_IDX ENTRY_IDX(-1)
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181 struct STEP_EQCLASS
00182 {
00183 VN_VALNUM step_valnum;
00184 OPCODE step_opc;
00185 ENTRY_IDX first_eqclass;
00186 ENTRY_IDX last_eqclass;
00187
00188 STEP_EQCLASS(VN_VALNUM stepsize, OPCODE stepop):
00189 step_valnum(stepsize),
00190 step_opc(stepop),
00191 first_eqclass(INVALID_ENTRY_IDX),
00192 last_eqclass(INVALID_ENTRY_IDX)
00193 {}
00194 };
00195
00196
00197 struct EQCLASS
00198 {
00199 INT32 num_members;
00200 ENTRY_IDX first_member;
00201 ENTRY_IDX last_member;
00202 ENTRY_IDX next;
00203
00204 EQCLASS():
00205 num_members(0),
00206 first_member(INVALID_ENTRY_IDX),
00207 last_member(INVALID_ENTRY_IDX),
00208 next(INVALID_ENTRY_IDX)
00209 {}
00210 };
00211
00212
00213 struct EQCLASS_MEMBER
00214 {
00215 INT32 num_occurs;
00216 INT32 num_hits;
00217 PHI_NODE *indvar_phi;
00218 INT32 indvar_init_kidno;
00219 VN_VALNUM indvar_init_valnum;
00220 VN_VALNUM indvar_valnum;
00221 INT64 literal_ofst;
00222 BOOL is_literal_ofst;
00223 BOOL required_index;
00224
00225 ENTRY_IDX step;
00226 ENTRY_IDX eqclass;
00227 ENTRY_IDX next;
00228
00229 EQCLASS_MEMBER(PHI_NODE *indphi,
00230 INT32 initkid,
00231 VN_VALNUM initval,
00232 VN_VALNUM indval,
00233 ENTRY_IDX step_idx,
00234 ENTRY_IDX eqclass_idx):
00235 num_occurs(0),
00236 num_hits(0),
00237 indvar_phi(indphi),
00238 indvar_init_kidno(initkid),
00239 indvar_init_valnum(initval),
00240 indvar_valnum(indval),
00241 literal_ofst(0),
00242 is_literal_ofst(FALSE),
00243 required_index(FALSE),
00244 step(step_idx),
00245 eqclass(eqclass_idx),
00246 next(INVALID_ENTRY_IDX)
00247 {}
00248 };
00249
00250
00251 struct NEXT_EQCLASS_MEMBER
00252 {
00253 ENTRY_IDX operator () (const EQCLASS_MEMBER &m) const
00254 {
00255 return m.next;
00256 }
00257 };
00258
00259
00260
00261
00262
00263 template<typename _Tp, typename _Distance>
00264 struct forward_iterator {
00265 typedef forward_iterator_tag iterator_category;
00266 typedef _Tp value_type;
00267 typedef _Distance difference_type;
00268 typedef _Tp* pointer;
00269 typedef _Tp& reference;
00270 };
00271
00272 template <class Container, class Next>
00273 class forward_to_next_iterator :
00274 public forward_iterator<
00275 typename std::iterator_traits<typename Container::iterator>::value_type,
00276 typename std::iterator_traits<typename Container::iterator>::difference_type>
00277 {
00278 public:
00279
00280 typedef typename Container::iterator iterator_type;
00281 typedef forward_to_next_iterator<Container, Next> Self;
00282 typedef typename Self::reference reference;
00283
00284 protected:
00285
00286 Container * _obj;
00287 INT32 _idx;
00288
00289 bool _is_dereferencable() const {return _idx >= 0 && _idx < _obj->size();}
00290
00291 reference _deref() const
00292 {
00293 Is_True(_is_dereferencable(),
00294 ("forward_to_next_iterator out of bounds %d", _idx));
00295 return (*_obj)[_idx];
00296 }
00297
00298 public:
00299
00300 forward_to_next_iterator() {}
00301 explicit forward_to_next_iterator(Container &c, INT32 i)
00302 : _obj(&c), _idx(i) {}
00303
00304 forward_to_next_iterator(const Self& x) : _obj(x._obj), _idx(x._idx) {}
00305
00306 Container *container() const {return _obj;}
00307 INT32 current_idx() const {return _idx;}
00308
00309 reference operator*() const
00310 {
00311 return _deref();
00312 }
00313
00314 Self& operator++()
00315 {
00316 _idx = Next()(_deref());
00317 return *this;
00318 }
00319
00320 Self operator++(int)
00321 {
00322 Self tmp = *this;
00323 _idx = Next()(_deref());
00324 return tmp;
00325 }
00326
00327 };
00328
00329
00330 template <class Container, class Next>
00331 bool operator== (const forward_to_next_iterator<Container,Next> &it1,
00332 const forward_to_next_iterator<Container,Next> &it2)
00333 {
00334 return (it1.container() == it2.container() &&
00335 it1.current_idx() == it2.current_idx());
00336 }
00337
00338
00339
00340
00341 class VN_IVC
00342 {
00343 public:
00344
00345 enum IVC_KIND {IVC_CONST_DIFF, IVC_INVARIANT_DIFF};
00346
00347 private:
00348
00349 typedef mempool_allocator<STEP_EQCLASS> STEP_ALLOCATOR;
00350 typedef mempool_allocator<EQCLASS> EQCLASS_ALLOCATOR;
00351 typedef mempool_allocator<EQCLASS_MEMBER> EQCLASS_MEMBER_ALLOCATOR;
00352
00353 typedef vector<STEP_EQCLASS, STEP_ALLOCATOR> IVC_STEP;
00354 typedef vector<EQCLASS, EQCLASS_ALLOCATOR> IVC_EQCLASS;
00355 typedef vector<EQCLASS_MEMBER, EQCLASS_MEMBER_ALLOCATOR> IVC_EQCLASS_MEMB;
00356
00357 MEM_POOL *_lpool;
00358 VN *_vn;
00359 IVC_KIND _kind;
00360 IVC_STEP _steps;
00361 IVC_EQCLASS _eqclasses;
00362 IVC_EQCLASS_MEMB _eqclass_membs;
00363
00364 static BOOL Is_induction_step(VN_EXPR::PTR step, VN_VALNUM join_result);
00365
00366 pair<BOOL,INT64> _get_literal_diff(VN_VALNUM v1, VN_VALNUM v2, MTYPE rty);
00367
00368 ENTRY_IDX _find_or_insert_step(VN_VALNUM step_valnum, OPCODE step_opc);
00369
00370 ENTRY_IDX _find_or_insert_eqclass(ENTRY_IDX stepi,
00371 VN_VALNUM init_valnum,
00372 MTYPE rty);
00373
00374 ENTRY_IDX _find_or_insert_member(PHI_NODE *phi,
00375 INT32 init_kidno,
00376 VN_VALNUM join_valnum,
00377 VN_VALNUM init_valnum,
00378 ENTRY_IDX stepi,
00379 ENTRY_IDX eqclassi,
00380 BOOL required_index);
00381
00382 ENTRY_IDX _enter_class(PHI_NODE *phi,
00383 INT32 init_kidno,
00384 VN_VALNUM join_valnum,
00385 VN_VALNUM init_valnum,
00386 VN_VALNUM step_valnum,
00387 VN_EXPR::PTR step_expr,
00388 BOOL required_index);
00389
00390 public:
00391
00392 typedef forward_to_next_iterator<IVC_EQCLASS_MEMB,
00393 NEXT_EQCLASS_MEMBER> members_iterator;
00394
00395 VN_IVC(IVC_KIND kind, VN *vn, MEM_POOL *lpool):
00396 _kind(kind), _vn (vn), _lpool(lpool) {}
00397
00398 BOOL classify(PHI_NODE *phi, VN_VALNUM join_valnum, BOOL required_index);
00399
00400
00401
00402
00403
00404 ENTRY_IDX num_eqclasses() const
00405 {
00406 return _eqclasses.size();
00407 }
00408
00409 ENTRY_IDX num_members(ENTRY_IDX eqclassi) const
00410 {
00411 Is_True(eqclassi < _eqclasses.size(),
00412 ("Equivalence class idx %d out of bounds in IVC:num_members",
00413 eqclassi));
00414
00415 return (_eqclasses[eqclassi].num_members);
00416 }
00417
00418 members_iterator members_begin(ENTRY_IDX eqclassi)
00419 {
00420 Is_True(eqclassi < _eqclasses.size(),
00421 ("Equivalence class idx %d out of bounds in IVC:member_num_hits",
00422 eqclassi));
00423
00424 return members_iterator(_eqclass_membs,
00425 (INT32)_eqclasses[eqclassi].first_member);
00426 }
00427
00428 members_iterator members_end()
00429 {
00430 return members_iterator(_eqclass_membs, INVALID_ENTRY_IDX);
00431 }
00432
00433
00434
00435
00436
00437 void set_num_occurs(EQCLASS_MEMBER &mem, INT32 num_occurs)
00438 {
00439 mem.num_occurs = num_occurs;
00440 }
00441
00442 void reset_num_hits(EQCLASS_MEMBER &mem, INT32 num_hits)
00443 {
00444 mem.num_hits = num_hits;
00445 }
00446
00447 void set_literal_ofst(EQCLASS_MEMBER &mem, INT64 ofst)
00448 {
00449 mem.literal_ofst = ofst;
00450 mem.is_literal_ofst = TRUE;
00451 }
00452
00453 void reset_literal_ofst(EQCLASS_MEMBER &mem)
00454 {
00455 mem.literal_ofst = 0;
00456 mem.is_literal_ofst = FALSE;
00457 }
00458
00459 INT32 finalize_for_coalescing(const EQCLASS_MEMBER &base,
00460 members_iterator memb_it_start,
00461 members_iterator memb_it_end,
00462 BOOL be_conservative);
00463
00464
00465
00466
00467
00468 IVC_KIND kind() const
00469 {
00470 return _kind;
00471 }
00472
00473 INT32 num_hits(const EQCLASS_MEMBER &mem) const
00474 {
00475 return mem.num_hits;
00476 }
00477
00478 INT32 num_occurs(const EQCLASS_MEMBER &mem) const
00479 {
00480 return mem.num_occurs;
00481 }
00482
00483 PHI_NODE *indvar_phi(const EQCLASS_MEMBER &mem) const
00484 {
00485 return mem.indvar_phi;
00486 }
00487
00488 VN_VALNUM indvar_valnum(const EQCLASS_MEMBER &mem) const
00489 {
00490 return mem.indvar_valnum;
00491 }
00492
00493 VN_VALNUM indvar_init_valnum(const EQCLASS_MEMBER &mem) const
00494 {
00495 return mem.indvar_init_valnum;
00496 }
00497
00498 CODEREP *indvar_init_cr(const EQCLASS_MEMBER &mem) const
00499 {
00500 return mem.indvar_phi->OPND(mem.indvar_init_kidno);
00501 }
00502
00503 BB_NODE *indvar_init_bb(const EQCLASS_MEMBER &mem) const
00504 {
00505 return mem.indvar_phi->Bb()->Nth_pred(mem.indvar_init_kidno);
00506 }
00507
00508 BOOL indvar_is_literal_ofst(const EQCLASS_MEMBER &mem) const
00509 {
00510 return mem.is_literal_ofst;
00511 }
00512
00513 INT64 indvar_literal_ofst(const EQCLASS_MEMBER &mem) const
00514 {
00515 return mem.literal_ofst;
00516 }
00517
00518 BOOL required_index(const EQCLASS_MEMBER &mem) const
00519 {
00520 return mem.required_index;
00521 }
00522
00523 OPCODE step_opc(const EQCLASS_MEMBER &mem) const
00524 {
00525 return _steps[mem.step].step_opc;
00526 }
00527
00528 static BOOL Is_Induction_Var(VN *vn, VN_VALNUM v);
00529
00530
00531
00532
00533
00534 void print(const EQCLASS_MEMBER &base,
00535 const EQCLASS_MEMBER &mem,
00536 FILE *outf = stderr);
00537
00538 };
00539
00540
00541
00542
00543
00544 BOOL
00545 VN_IVC::Is_induction_step(VN_EXPR::PTR step, VN_VALNUM join_result)
00546 {
00547
00548
00549
00550
00551 return (step != NULL &&
00552 step->get_kind() == VN_EXPR::BINARY &&
00553 ((OPCODE_operator(step->get_opc()) == OPR_ADD &&
00554 (step->get_opnd(0) == join_result ||
00555 step->get_opnd(1) == join_result)) ||
00556 (OPCODE_operator(step->get_opc()) == OPR_SUB &&
00557 step->get_opnd(0) == join_result)));
00558 }
00559
00560
00561 pair<BOOL,INT64>
00562 VN_IVC::_get_literal_diff(VN_VALNUM v1, VN_VALNUM v2, MTYPE rty)
00563 {
00564
00565
00566
00567
00568 pair<BOOL, INT64> retval(FALSE, 0);
00569 OPCODE opc = OPCODE_make_op(OPR_SUB, rty, MTYPE_V);
00570 VN_EXPR::PTR offset_expr = VN_EXPR::Create_Binary(opc, v1, v2);
00571 VN_EXPR::PTR offset_val = offset_expr->simplify(_vn);
00572
00573 Is_True(MTYPE_is_integral(rty), ("Illegal rty in _get_literal_diff()"));
00574
00575 if (offset_val->get_kind() == VN_EXPR::LITERAL)
00576 retval = pair<BOOL,INT64>(TRUE, Targ_To_Host(offset_val->get_tcon()));
00577 else
00578 {
00579
00580
00581
00582 VN_EXPR::PTR offset_expr2 = VN_EXPR::Create_Binary(opc, v2, v1);
00583 VN_EXPR::PTR offset_val2 = offset_expr2->simplify(_vn);
00584
00585 if (offset_val2->get_kind() == VN_EXPR::LITERAL)
00586 retval = pair<BOOL,INT64>(TRUE,
00587 -Targ_To_Host(offset_val2->get_tcon()));
00588
00589 offset_val2->free();
00590 }
00591 offset_val->free();
00592
00593 return retval;
00594 }
00595
00596
00597 ENTRY_IDX
00598 VN_IVC::_find_or_insert_step(VN_VALNUM step_valnum, OPCODE step_opc)
00599 {
00600 ENTRY_IDX stepi = INVALID_ENTRY_IDX;
00601
00602
00603
00604
00605 for (ENTRY_IDX i = 0; i < _steps.size(); i++)
00606 {
00607 if (_steps[i].step_valnum == step_valnum &&
00608 _steps[i].step_opc == step_opc)
00609 stepi = i;
00610 }
00611 if (stepi == INVALID_ENTRY_IDX)
00612 {
00613
00614
00615 _steps.push_back(STEP_EQCLASS(step_valnum, step_opc));
00616 stepi = _steps.size()-1;
00617 }
00618 return stepi;
00619 }
00620
00621
00622 ENTRY_IDX
00623 VN_IVC::_find_or_insert_eqclass(ENTRY_IDX stepi,
00624 VN_VALNUM init_valnum,
00625 MTYPE rty)
00626 {
00627 ENTRY_IDX eqclassi = INVALID_ENTRY_IDX;
00628
00629 if (_kind == IVC_INVARIANT_DIFF)
00630 {
00631
00632
00633
00634
00635
00636 Is_True(_steps[stepi].first_eqclass == _steps[stepi].last_eqclass,
00637 ("Too many equivalence classes for equivalent step-sizes"
00638 "VN_IVC::_find_or_insert_eqclass()"));
00639
00640 if (_steps[stepi].first_eqclass != INVALID_ENTRY_IDX)
00641 eqclassi = _steps[stepi].first_eqclass;
00642 }
00643 else
00644 {
00645
00646
00647
00648
00649 for (ENTRY_IDX i = _steps[stepi].first_eqclass;
00650 i != INVALID_ENTRY_IDX && eqclassi == INVALID_ENTRY_IDX;
00651 i = _eqclasses[i].next)
00652 {
00653 const VN_VALNUM next_init_valnum =
00654 _eqclass_membs[_eqclasses[i].first_member].indvar_init_valnum;
00655
00656 if (next_init_valnum == init_valnum)
00657 eqclassi = i;
00658 else
00659 {
00660 pair<BOOL,INT64> ofst =
00661 _get_literal_diff(init_valnum, next_init_valnum, rty);
00662
00663 if (ofst.first)
00664 eqclassi = i;
00665 }
00666 }
00667 }
00668
00669 if (eqclassi == INVALID_ENTRY_IDX)
00670 {
00671
00672
00673 _eqclasses.push_back(EQCLASS());
00674
00675
00676
00677 eqclassi = _eqclasses.size()-1;
00678
00679
00680
00681
00682 if (_steps[stepi].first_eqclass == INVALID_ENTRY_IDX)
00683 {
00684 _steps[stepi].first_eqclass = eqclassi;
00685 }
00686 else
00687 {
00688 _eqclasses[_steps[stepi].last_eqclass].next = eqclassi;
00689 }
00690 _steps[stepi].last_eqclass = eqclassi;
00691 }
00692 return eqclassi;
00693 }
00694
00695
00696 ENTRY_IDX
00697 VN_IVC::_find_or_insert_member(PHI_NODE *phi,
00698 INT32 init_kidno,
00699 VN_VALNUM join_valnum,
00700 VN_VALNUM init_valnum,
00701 ENTRY_IDX stepi,
00702 ENTRY_IDX eqclassi,
00703 BOOL required_index)
00704 {
00705 ENTRY_IDX eqclass_membi = INVALID_ENTRY_IDX;
00706
00707
00708
00709
00710 for (ENTRY_IDX i = _eqclasses[eqclassi].first_member;
00711 i != INVALID_ENTRY_IDX;
00712 i = _eqclass_membs[i].next)
00713 {
00714 if (join_valnum == _eqclass_membs[i].indvar_valnum)
00715 eqclass_membi = i;
00716 }
00717
00718
00719
00720
00721 if (eqclass_membi == INVALID_ENTRY_IDX)
00722 {
00723 _eqclass_membs.push_back(EQCLASS_MEMBER(phi, init_kidno, init_valnum,
00724 join_valnum, stepi, eqclassi));
00725
00726
00727
00728 eqclass_membi = _eqclass_membs.size()-1;
00729
00730
00731
00732
00733 if (_eqclasses[eqclassi].first_member == INVALID_ENTRY_IDX)
00734 {
00735 _eqclasses[eqclassi].first_member = eqclass_membi;
00736 }
00737 else
00738 {
00739 _eqclass_membs[_eqclasses[eqclassi].last_member].next =
00740 eqclass_membi;
00741 }
00742 _eqclasses[eqclassi].last_member = eqclass_membi;
00743 _eqclasses[eqclassi].num_members += 1;
00744 }
00745
00746
00747
00748 _eqclass_membs[eqclass_membi].num_hits += 1;
00749
00750
00751
00752
00753
00754
00755 if (required_index)
00756 {
00757 _eqclass_membs[eqclass_membi].required_index = TRUE;
00758 _eqclass_membs[eqclass_membi].indvar_phi = phi;
00759 }
00760
00761 return eqclass_membi;
00762 }
00763
00764
00765 ENTRY_IDX
00766 VN_IVC::_enter_class(PHI_NODE *phi,
00767 INT32 init_kidno,
00768 VN_VALNUM join_valnum,
00769 VN_VALNUM init_valnum,
00770 VN_VALNUM step_valnum,
00771 VN_EXPR::PTR step_expr,
00772 BOOL required_index)
00773 {
00774
00775
00776
00777
00778
00779 const OPCODE step_opc = step_expr->get_opc();
00780 const MTYPE rty = OPCODE_rtype(step_opc);
00781 const VN_VALNUM step_size = (step_expr->get_opnd(0) == join_valnum?
00782 step_expr->get_opnd(1) :
00783 step_expr->get_opnd(0));
00784
00785
00786
00787
00788 ENTRY_IDX stepi = _find_or_insert_step(step_size, step_opc);
00789
00790 ENTRY_IDX eqclass = _find_or_insert_eqclass(stepi, init_valnum, rty);
00791
00792 ENTRY_IDX member =
00793 _find_or_insert_member(phi, init_kidno, join_valnum, init_valnum,
00794 stepi, eqclass, required_index);
00795 return member;
00796 }
00797
00798
00799 BOOL
00800 VN_IVC::classify(PHI_NODE *phi, VN_VALNUM join_valnum, BOOL required_index)
00801 {
00802
00803
00804
00805
00806
00807
00808 VN_EXPR::PTR join_expr = _vn->valnum_expr(join_valnum);
00809
00810 Is_True(!join_valnum.is_bottom() &&
00811 join_expr != NULL &&
00812 join_expr->get_kind() == VN_EXPR::PHI &&
00813 join_expr->get_num_opnds() == 2,
00814 ("Illegal candidate as induction variable in "
00815 "VN_IVC::classify()"));
00816
00817 const VN_VALNUM valnum0 = join_expr->get_opnd(0);
00818 const VN_VALNUM valnum1 = join_expr->get_opnd(1);
00819 ENTRY_IDX eqclass = INVALID_ENTRY_IDX;
00820
00821 if (!(valnum0.is_bottom() || valnum1.is_bottom()))
00822 {
00823 VN_EXPR::PTR expr0 = _vn->valnum_expr(valnum0);
00824 VN_EXPR::PTR expr1 = _vn->valnum_expr(valnum1);
00825
00826 if (Is_induction_step(expr0, join_valnum) &&
00827 MTYPE_is_integral(OPCODE_rtype(expr0->get_opc())))
00828 {
00829 eqclass = _enter_class(phi, 1 , join_valnum,
00830 valnum1, valnum0, expr0, required_index);
00831 }
00832 else if (Is_induction_step(expr1, join_valnum) &&
00833 MTYPE_is_integral(OPCODE_rtype(expr1->get_opc())))
00834 {
00835 eqclass = _enter_class(phi, 0 , join_valnum,
00836 valnum0, valnum1, expr1, required_index);
00837 }
00838 }
00839 return (eqclass != INVALID_ENTRY_IDX);
00840 }
00841
00842
00843 BOOL
00844 VN_IVC::Is_Induction_Var(VN *vn, VN_VALNUM v)
00845 {
00846 BOOL is_ivar = FALSE;
00847
00848 if (!v.is_bottom())
00849 {
00850 VN_EXPR::PTR join_expr = vn->valnum_expr(v);
00851
00852 if (join_expr != NULL &&
00853 join_expr->get_kind() == VN_EXPR::PHI &&
00854 join_expr->get_num_opnds() == 2)
00855 {
00856 VN_VALNUM valnum0 = join_expr->get_opnd(0);
00857 VN_VALNUM valnum1 = join_expr->get_opnd(1);
00858 VN_EXPR::PTR expr0 = vn->valnum_expr(valnum0);
00859 VN_EXPR::PTR expr1 = vn->valnum_expr(valnum1);
00860
00861 if (Is_induction_step(expr0, v) || Is_induction_step(expr1, v))
00862 is_ivar = TRUE;
00863 }
00864 }
00865 return is_ivar;
00866 }
00867
00868
00869 INT32
00870 VN_IVC::finalize_for_coalescing(const EQCLASS_MEMBER &base,
00871 VN_IVC::members_iterator memb_it_start,
00872 VN_IVC::members_iterator memb_it_end,
00873 BOOL aggressive)
00874 {
00875
00876
00877
00878
00879
00880
00881
00882
00883 const VN_VALNUM base_init_valnum = indvar_init_valnum(base);
00884 VN_IVC::members_iterator memb;
00885 INT32 hit_counter = 0;
00886
00887 for (memb = memb_it_start; memb != memb_it_end; ++memb)
00888 {
00889 const VN_VALNUM init_valnum = indvar_init_valnum(*memb);
00890
00891 if (base_init_valnum == init_valnum)
00892 {
00893 set_literal_ofst(*memb, 0);
00894 hit_counter += num_hits(*memb);
00895 }
00896 else if (!aggressive && num_hits(*memb) < 2)
00897 {
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908
00909
00910
00911 reset_num_hits(*memb, 0);
00912 }
00913 else
00914 {
00915 const MTYPE rty = OPCODE_rtype(step_opc(*memb));
00916 pair<BOOL,INT64> literal_diff =
00917 _get_literal_diff(init_valnum, base_init_valnum, rty);
00918
00919 if (literal_diff.first)
00920 {
00921
00922
00923
00924
00925 set_literal_ofst(*memb, literal_diff.second);
00926 hit_counter += num_hits(*memb);
00927 }
00928 else if (kind() == IVC_CONST_DIFF)
00929 {
00930
00931
00932
00933
00934
00935
00936
00937
00938 reset_num_hits(*memb, 0);
00939 }
00940 else
00941 {
00942 reset_literal_ofst(*memb);
00943 hit_counter += num_hits(*memb);
00944 }
00945 }
00946 }
00947 return hit_counter;
00948 }
00949
00950
00951 void
00952 VN_IVC::print(const EQCLASS_MEMBER &base,
00953 const EQCLASS_MEMBER &mem,
00954 FILE *outf)
00955 {
00956 if (mem.is_literal_ofst)
00957 {
00958 fprintf(outf,
00959 "EQCLASS %d, "
00960 "indvar=vn%d, "
00961 "hits=%d, "
00962 "init_ofst=%lld, "
00963 "init_bb=%d\n",
00964 mem.eqclass,
00965 (INT32)mem.indvar_valnum.ordinal(),
00966 mem.num_hits,
00967 mem.literal_ofst,
00968 (INT32)indvar_init_bb(mem)->Id());
00969 }
00970 else
00971 {
00972 fprintf(outf,
00973 "EQCLASS %d, "
00974 "indvar=vn%d, "
00975 "hits=%d, "
00976 "init_ofst=(vn%d(cr%d) - vn%d(cr%d)), "
00977 "init_bb=%d\n",
00978 mem.eqclass,
00979 (INT32)mem.indvar_valnum.ordinal(),
00980 mem.num_hits,
00981 (INT32)mem.indvar_init_valnum.ordinal(),
00982 (INT32)indvar_init_cr(mem)->Coderep_id(),
00983 (INT32)base.indvar_init_valnum.ordinal(),
00984 (INT32)indvar_init_cr(base)->Coderep_id(),
00985 (INT32)indvar_init_bb(mem)->Id());
00986 }
00987 }
00988
00989
00990
00991
00992
00993 template <class GET_NUM_OCCURS>
00994 VN_IVC::members_iterator
00995 VN_IVC_choose_eqclass_base_indvar(GET_NUM_OCCURS get_num_occurs,
00996 VN_IVC &vn_ivc,
00997 VN_IVC::members_iterator memb_it_start,
00998 VN_IVC::members_iterator memb_it_end)
00999 {
01000
01001
01002
01003
01004
01005
01006
01007
01008
01009 BOOL found_required_base = FALSE;
01010 VN_IVC::members_iterator base_memb = memb_it_start;
01011 VN_IVC::members_iterator memb_it;
01012
01013
01014
01015
01016
01017 for (memb_it = memb_it_start; memb_it != memb_it_end; ++memb_it)
01018 {
01019 const INT32 num_occurs = get_num_occurs(vn_ivc.indvar_valnum(*memb_it));
01020
01021 vn_ivc.set_num_occurs(*memb_it, num_occurs);
01022 if (vn_ivc.required_index(*memb_it))
01023 {
01024 base_memb = memb_it;
01025 found_required_base = TRUE;
01026 }
01027 else if (!found_required_base &&
01028 num_occurs > vn_ivc.num_occurs(*base_memb))
01029 {
01030 base_memb = memb_it;
01031 }
01032 }
01033 return base_memb;
01034 }
01035
01036 #endif // opt_vn_ivc_INCLUDED