00001 //-*-c++-*- 00002 00003 /* 00004 * Copyright 2003, 2004, 2005, 2006 PathScale, Inc. All Rights Reserved. 00005 */ 00006 00007 // ==================================================================== 00008 // ==================================================================== 00009 // 00010 // Module: opt_vn.h 00011 // $Revision: 1.1.1.1 $ 00012 // $Date: 2005/10/21 19:00:00 $ 00013 // $Author: marcel $ 00014 // $Source: /proj/osprey/CVS/open64/osprey1.0/be/opt/opt_vn.h,v $ 00015 // 00016 // ==================================================================== 00017 // 00018 // Copyright (C) 2000, 2001 Silicon Graphics, Inc. All Rights Reserved. 00019 // 00020 // This program is free software; you can redistribute it and/or modify 00021 // it under the terms of version 2 of the GNU General Public License as 00022 // published by the Free Software Foundation. 00023 // 00024 // This program is distributed in the hope that it would be useful, but 00025 // WITHOUT ANY WARRANTY; without even the implied warranty of 00026 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 00027 // 00028 // Further, this software is distributed without any warranty that it 00029 // is free of the rightful claim of any third person regarding 00030 // infringement or the like. Any license provided herein, whether 00031 // implied or otherwise, applies only to this software file. Patent 00032 // licenses, if any, provided herein do not apply to combinations of 00033 // this program with other software, or any other product whatsoever. 00034 // 00035 // You should have received a copy of the GNU General Public License 00036 // along with this program; if not, write the Free Software Foundation, 00037 // Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA. 00038 // 00039 // Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pky, 00040 // Mountain View, CA 94043, or: 00041 // 00042 // http://www.sgi.com 00043 // 00044 // For further information regarding this notice, see: 00045 // 00046 // http://oss.sgi.com/projects/GenInfo/NoticeExplan 00047 // 00048 // ==================================================================== 00049 // 00050 // INTERFACE DESCRIPTION: 00051 // ---------------------- 00052 // 00053 // This file introduces a class of object representing a value numbering. 00054 // The constructor will walk over the CFG and create the value numbering. 00055 // Once the value numbering (VN) object is constructed, the other exported 00056 // methods may be used to access the value numbering results. Note 00057 // that the cfg passed in to the constructor MUST already be in SSA 00058 // form. 00059 // 00060 // The following outlines characteristics of the results of a value 00061 // numbering: 00062 // 00063 // * The expr_cr() mapping maps a CODEREP::Coderep_id() to a CODEREP*. 00064 // Ideally this ought to be part of the codemap, but since it is not 00065 // we need to define this mapping as part of the value numbering. 00066 // TODO: get rid of this when it is created as part of a CODEMAP. 00067 // 00068 // * The expr_valnum() mapping maps a CODEREP::Coderep_id() to a value 00069 // number and should always be well defined and should never be 00070 // Bottom() or Top(), with a few exceptions: black boxes 00071 // may be Bottom() or Top(), OPR_CALL, OPR_PICCALL, OPR_ICALL, 00072 // OPR_INTRINSIC_CALL) and zero version VARs will be assigned 00073 // Bottom() values. OPR_PARM CK_IVAR codereps and OPR_PARM 00074 // CK_OP codereps will be assigned the same value number as the 00075 // argument expression (Base_opnd() and Opnd0() respectively). The 00076 // client of the interface exported here should assert if any 00077 // unexpected Top() or Bottom() value number is returned. 00078 // 00079 // * Note that we *do* value number dead statements, since no statement 00080 // is marked as live immediately after the CODEMAP is created, and we 00081 // may wish to employ offline value numbering before the "live" flags 00082 // are set reliably on STMTREPs. 00083 // 00084 // * The expr_stmts() is a mapping from each CODEREP::Coderep_id() to 00085 // the STMTREP* that contains it. The range of the mapping has to be 00086 // a list of STMTREPs, since our program representation allows a 00087 // CODEREP to be shared between different statements. We do not record 00088 // any STMTREP for CODEREPs that have no valid value number (e.g. _|_), 00089 // or when the CODEREP is a VAR or IVAR on the lhs of an assignment, 00090 // or when the value number denotes a LITERAL and the coderep is also 00091 // a literal value (on the assumption that no consumer of the STMT_LIST 00092 // ever need these). The current definition of a STMT_LIST as produced 00093 // by a VN is made to fit the needs of our redundancy elimination 00094 // algorithm. 00095 // 00096 // * The valnum_expr() mapping maps each value number to the VN_EXPR::PTR 00097 // used to derive the value number. This mapping will yield a NULL 00098 // value when VN_EXPR::PTR contained Bottom() operands or was arrived 00099 // at through a Chi node. All other cases should be non-NULL. 00100 // 00101 // * Integral VN_EXPR::LITERALs will all have type I8, and must be 00102 // coerced into the appropriate type if they are to be inserted 00103 // into our IR as part of an optimization. 00104 // 00105 // * The VALNUM_TO_EXPR_LIST class can be used to construct the reverse 00106 // mapping of the VN::expr_valnum() mapping. This reverse mapping 00107 // will be NULL for value numbers that are not well-defined (such 00108 // as Top() and Bottom()). 00109 // 00110 // USAGE: 00111 // ------ 00112 // 00113 // The VN class employs the given global memory pool (gpool) to allocate 00114 // data-structures for a constructed VN object, while it pushes and pops 00115 // the local memory pool (lpool) during construction (VN::VN) and while 00116 // performing object methods. We made the choice of separating the 00117 // decision as to what mempool is used for allocation of VN_EXPR objects 00118 // from the mempools used by a VN object. This requires a bit of care 00119 // from the user of the VN_EXPR and the VN interfaces: 00120 // 00121 // 1) Make sure you call VN_EXPR::Init_Free_Lists(mpool) before you 00122 // construct any VN object; otherwise VN construction will fail 00123 // with a segv fault. 00124 // 00125 // 2) Make sure the mpool for VN_EXPRs and the lpool for VNs are 00126 // either different, or they are both the Malloc_Mem_Pool. 00127 // 00128 // 3) Make sure you call VN_EXPR::Reclaim_Free_Lists() to reclaim 00129 // free-lists of VN_EXPR objects. Deletion of a VN object will 00130 // not delete the VN_EXPR free-lists. If you wish to allocate 00131 // VN_EXPR from a new mempool always call Reclaim_Free_Lists() 00132 // followed by Init_Free_Lists(mpool). 00133 // 00134 // The decoupling of the VN_EXPR mempool from the VN mempools allows 00135 // more freedom in the allocation scheme, and in particular it allows 00136 // repeated use of VN_EXPR free-lists, while constructing and deleting 00137 // multiple VN objects. 00138 // 00139 // Example: 00140 // 00141 // OPT_POOL_Push(gpool, -1); 00142 // { 00143 // VN_EXPR::Init_Free_Lists(gpool); 00144 // { 00145 // VN vn(VN::ITERATIVE, cfg, codemap, lpool, gpool); 00146 // ... // use first vn 00147 // } 00148 // ... // Do other stuff! 00149 // { 00150 // VN vn(VN::SINGLE_PASS, cfg, codemap, lpool, gpool); 00151 // ... // use second vn 00152 // } 00153 // VN_EXPR::Reclaim_Free_Lists(); 00154 // } 00155 // OPT_POOL_Pop(gpool, -1); 00156 // 00157 // Note that VALNUM_TO_EXPR_LIST also uses a mempool, which may or may 00158 // not be different from the VN mempools! 00159 // 00160 // 00161 // IMPLEMENTATION DETAILS AND RELATION OF ALGORITHM TO LITERATURE: 00162 // --------------------------------------------------------------- 00163 // 00164 // The algorithms implemented here are based on Taylor Simpson's 00165 // work, as documented in his Ph.D. thesis from Rice University entitled 00166 // "Value Driven Redundancy Elimination", April 1996. 00167 // 00168 // His thesis describes two methods of value numbering which we have 00169 // implemented here. One is the pessimistic one-pass "unified hash-table 00170 // algorithm"; and the other is the similar optimistic iterative 00171 // "Reverse Postorder" (RPO) algorithm. His SCC (strongly connected 00172 // components) algorithm is touted as the most efficient version of 00173 // the RPO algorithm, but it is sufficiently different in implementation 00174 // and hard to intuitively understand from the theoretically proven 00175 // RPO algorithm, that we instead opted to implement the straight-forward 00176 // RPO algorithm. The efficiency benefit of the SCC over the RPO 00177 // algorithm is not clear. 00178 // 00179 // Some characteristics of our SSA representation that affects the 00180 // algorithm and caused some changes in the way we do things are as 00181 // follows: 00182 // 00183 // 1) Instead of triplets, we have a program representation in terms 00184 // of CODEREPS, where the Coderep_id() can be viewed as the 00185 // notion of a "register" as used in Taylor's algorithms. 00186 // 00187 // 2) Since codereps may be shared between different expressions, 00188 // we need a is_numbered[] boolean array to denote whether or 00189 // not a Coderep_id[] has already been value numbered (in a 00190 // particular iteration of the RPO algorithm). This saves us 00191 // from having to construct a VN_EXPR, simplify, and hash an 00192 // expression twice. 00193 // 00194 // 3) We do not use Coderep_id() as a value number, instead assigning 00195 // consecutive numbers as value numbers, since there are likely 00196 // to be many more CODEREP nodes than value numbers. This reduces 00197 // the size of any maps we have from value numbers to other info, 00198 // such as the VN_VALNUM-->VN_EXPR::PTR map. 00199 // 00200 // 4) Our method for finding congruences between indirect loads and 00201 // stores is a little different from Taylor's method. We use 00202 // the regular hash-table to hash lvalues, and will map such lvalue 00203 // expressions (MEMLOC expressions) to the lhs of assignments. 00204 // We may see a load off an lvalue without seeing a store into 00205 // one beforehand, and will apply a unique value number to such 00206 // a load. When a store is seen into an lvalue, the fact that 00207 // we use the version of the virtual variable as part of the MEMLOC 00208 // guarantees that a load from the same location has not been seen 00209 // beforehand. The lvalue MEMLOC for a store will be mapped to 00210 // the same value number as the rhs expression's value number, and 00211 // this is the only case when two different expressions in the 00212 // hash-table may map to the same value number. 00213 // 00214 // 5) Taylor specifies that the iterative algorithm requires reverse 00215 // postorder traversal of the CFG, while the single-pass algorithm 00216 // requires a preorder (or reverse postorder) travesal of the 00217 // dominator tree with a CFG reverse postorder traversal of the 00218 // dominator tree kids. We simplify this to use a reverse postorder 00219 // traversal of the CFG in both cases. The algorithms are therefore 00220 // essentially the same in each pass over the CFG, except that 00221 // one of them starts off with optimistic assumptions, while the 00222 // other starts off with pessimistic assumptions. Given this order 00223 // of traversal, the only undefined values we *ever* encounter 00224 // are parameters of phi nodes representing data-flow up back-edges 00225 // in the CFG and indirect loads of lvalues (see point 4 concerning 00226 // lvalues). 00227 // 00228 // 6) We create a map from VN_VALNUMs to VN_EXPR:PTR in addition to the 00229 // Coderep_Id() to VN_VALNUM mapping. This is useful to any 00230 // subsequent optimizations (such as AVAIL based redundancy 00231 // elimination or partial redundancy elimination). 00232 // 00233 // 7) For phi nodes the value number will be assigned to the RESULT 00234 // coderep in the cr_to_vn mapping. For ivars (indirect loads/stores) 00235 // the value number will be assigned to the ivar coderep. 00236 // 00237 // 8) Our representation (CODEREPS) may have implicit conversion 00238 // operations (e.g. U8U4ILOAD for mips3), and we will also need 00239 // to associate these with an EXPRID. To handle this, and yet 00240 // have the iterative algorithm terminate we need a second cr_to_vn 00241 // mapping. 00242 // 00243 // SEE ALSO: 00244 // --------- 00245 // 00246 // opt_cfg.h: Control flow graph. 00247 // opt_ssa.h: Control flow graph in SSA form. 00248 // opt_htable.h: Utilities for creating the CODEREP form of the cfg. 00249 // 00250 // opt_vn_expr.h : Implementation of VN_VALNUM, VN_EXPR, and VN_EXPR_MAP. 00251 // 00252 // opt_vn_hashtab.h : Implementation of VN_HASHTAB, which maps a 00253 // VN_EXPR::PTR to VN_VALNUM, based on a hashing algorithm. 00254 // 00255 // ==================================================================== 00256 // ==================================================================== 00257 00258 00259 #ifndef opt_vn_INCLUDED 00260 #define opt_vn_INCLUDED "opt_vn.h" 00261 00262 #include <ext/slist> 00263 #include <vector> 00264 #include "segmented_array.h" 00265 #include "opt_vn_expr.h" // For VN_VALNUM, VN_EXPR, and VN_EXPR_MAP 00266 #include "opt_vn_hashtab.h" // For VN_HASHTAB 00267 00268 #ifdef __STL_USE_NAMESPACES 00269 using std::slist; 00270 using std::vector; 00271 #endif 00272 00273 class CODEREP; 00274 class STMTREP; 00275 class CFG; 00276 class CODEMAP; 00277 class VALNUM_TO_EXPR_LIST; 00278 00279 00280 class VN 00281 { 00282 public: 00283 00284 typedef INT32 EXPRID; // CODEREP::Coderep_id() 00285 00286 enum VN_ALGORITHM {SINGLE_PASS, ITERATIVE}; 00287 00288 typedef mempool_allocator<STMTREP*> STMT_ALLOCATOR; 00289 typedef slist<STMTREP*, STMT_ALLOCATOR> STMT_LIST; // linked list 00290 00291 typedef mempool_allocator<VN_VALNUM> VALNUM_ALLOCATOR; 00292 typedef vector<VN_VALNUM, VALNUM_ALLOCATOR> VALNUM_VECTOR; 00293 00294 typedef mempool_allocator<bool> BVECTOR_ALLOCATOR; 00295 typedef vector<bool, BVECTOR_ALLOCATOR> BIT_VECTOR; 00296 00297 private: 00298 00299 typedef mempool_allocator<CODEREP*> CODEREP_ALLOCATOR; 00300 typedef vector<CODEREP*, CODEREP_ALLOCATOR> CODEREP_VECTOR; 00301 00302 typedef mempool_allocator<STMT_LIST> STMTLIST_ALLOCATOR; 00303 typedef vector<STMT_LIST, STMTLIST_ALLOCATOR> STMTLIST_VECTOR; 00304 00305 struct VN_ALGORITHM_STATUS 00306 { 00307 VN_HASHTAB *expr_to_vn; // VN_EXPR->VN_VALNUM (used for callback) 00308 BIT_VECTOR *is_numbered; // VN_VALNUM->BOOL (for explicit ops) 00309 BIT_VECTOR *locked_to_vn; // VN_VALNUM->BOOL (for explicit ops) 00310 BIT_VECTOR *locked_to_vn2; // VN_VALNUM->BOOL (for implicit ops) 00311 VALNUM_VECTOR *exprid_to_vn2; // EXPRID->VN_VALNUM (for implicit ops) 00312 BOOL changed; // Any valnum changed in this iteration 00313 00314 VN_ALGORITHM_STATUS(): 00315 expr_to_vn(NULL), 00316 is_numbered(NULL), 00317 locked_to_vn(NULL), 00318 locked_to_vn2(NULL), 00319 exprid_to_vn2(NULL), 00320 changed(FALSE) 00321 {} 00322 }; // struct VN_ALGORITHM_STATUS 00323 00324 MEM_POOL *_lpool; // Pool used for internal algorithms 00325 MEM_POOL *_gpool; // Pool used for a "this" object 00326 STMTREP *_current_stmt; // For use during value numbering 00327 INT32 _no_of_iterations; // For debugging 00328 VN_VALNUM _zero_valnum; // For integer literals 00329 VN_VALNUM _next_valnum; 00330 VN_EXPR_MAP _vn_to_expr; // VN_VALNUM --> VN_EXPR 00331 VALNUM_VECTOR _exprid_to_vn; // Coderep_id --> VN_VALNUM 00332 STMTLIST_VECTOR _exprid_to_stmtlist; // Coderep_id --> STMT_LIST; 00333 CODEREP_VECTOR _exprid_to_cr; // Coderep_id --> (CODEREP*) 00334 VN_ALGORITHM_STATUS _status; // Needed only during construction 00335 00336 static VN_VALNUM Initial_Valnum(VN_ALGORITHM algo) 00337 { 00338 return (algo == SINGLE_PASS? VN_VALNUM::Bottom() : VN_VALNUM::Top()); 00339 } 00340 00341 void _grow_exprid_maps(EXPRID id); 00342 00343 EXPRID _get_exprid(const CODEREP *cr) 00344 { 00345 const EXPRID exprid = cr->Coderep_id(); 00346 _exprid_to_cr[exprid] = (CODEREP *)cr; 00347 return exprid; 00348 } 00349 00350 EXPRID _append_exprid(const CODEREP *cr) 00351 { 00352 // Only use this to modify an existing value numbering, such as 00353 // changes caused by VNFRE. 00354 // 00355 const EXPRID exprid = cr->Coderep_id(); 00356 _grow_exprid_maps(exprid); 00357 _exprid_to_cr[exprid] = (CODEREP *)cr; 00358 return exprid; 00359 } 00360 00361 VN_VALNUM _unique_valnum(EXPRID exprid, 00362 const VALNUM_VECTOR &exprid_to_vn, 00363 const BIT_VECTOR &locked_to_vn) const 00364 { 00365 return (locked_to_vn[exprid]? exprid_to_vn[exprid] : _next_valnum); 00366 } 00367 00368 VN_VALNUM _get_literal_valnum(INT64 i) const 00369 { 00370 return VN_VALNUM::Vn(i + _zero_valnum.ordinal()); 00371 } 00372 00373 void _init_integer_valnum_map(); 00374 00375 VN_VALNUM _valnum_integer(INT64 literal, 00376 BOOL is_signed); 00377 00378 inline void _set_stmt_map(CODEKIND ck, EXPRID id, const VN_VALNUM &vn); 00379 00380 void _set_valnum(EXPRID id, 00381 const VN_VALNUM &vn, 00382 VALNUM_VECTOR &exprid_to_vn, 00383 BIT_VECTOR &locked_to_vn); 00384 00385 VN_VALNUM _valnum_vn_expr(EXPRID exprid, 00386 VN_EXPR::PTR expr, 00387 VALNUM_VECTOR &exprid_to_vn, 00388 BIT_VECTOR &locked_to_vn); 00389 00390 VN_VALNUM _valnum_sym(CODEREP *sym); 00391 00392 VN_VALNUM _valnum_op(CODEREP *cr); 00393 00394 00395 VN_VALNUM _valnum_expr(CODEREP *cr); 00396 00397 VN_VALNUM _valnum_implicit_integral_cvt(EXPRID exprid, 00398 VN_VALNUM opnd_valnum, 00399 MTYPE from_mty, 00400 MTYPE to_mty, 00401 VALNUM_VECTOR &exprid_to_vn, 00402 BIT_VECTOR &locked_to_vn); 00403 00404 VN_VALNUM _valnum_lhs(EXPRID lhs_exprid, 00405 VN_VALNUM valnum, 00406 MTYPE lhs_dty, 00407 MTYPE lhs_dscty, 00408 MTYPE rhs_dty); 00409 00410 VN_VALNUM _valnum_memloc_load(CODEREP *cr); 00411 00412 void _valnum_memloc_store(CODEREP *lhs, 00413 VN_VALNUM rhs_valnum, 00414 MTYPE rhs_mtype); 00415 00416 void _valnum_phi_list(IDTYPE bb_id, 00417 PHI_LIST *phi_list); 00418 00419 void _valnum_chi_list(CHI_LIST *chi_list); 00420 00421 00422 void _valnum_stmt(STMTREP *stmt); 00423 00424 void _valnum_cfg(CFG *cfg); 00425 00426 void _trace(EXPRID id, VN_VALNUM valnum, FILE *fp = stderr); 00427 00428 void _print_exprid_to_vn(FILE *fp, EXPRID id, INT32 column_width) const; 00429 00430 void _print_vn_to_exprid(FILE *fp, 00431 const VALNUM_TO_EXPR_LIST &vn_to_exprid, 00432 VN_VALNUM valnum) const; 00433 00434 public: 00435 00436 VN(VN_ALGORITHM algo, 00437 CFG *cfg, 00438 CODEMAP *codemap, 00439 MEM_POOL *lpool = Malloc_Mem_Pool, 00440 MEM_POOL *gpool = Malloc_Mem_Pool); 00441 00442 ~VN(); 00443 00444 CODEREP * expr_cr(EXPRID exprid) const 00445 { 00446 Is_True(exprid <_exprid_to_cr.size(), 00447 ("Out of bounds access to VN::expr_cr()")); 00448 return _exprid_to_cr[exprid]; 00449 } 00450 00451 VN_VALNUM expr_valnum(EXPRID exprid) const 00452 { 00453 Is_True(exprid < _exprid_to_vn.size(), 00454 ("Out of bounds access to VN::expr_valnum()")); 00455 return (_exprid_to_vn[exprid] == VN_VALNUM::Top()? 00456 VN_VALNUM::Bottom() : _exprid_to_vn[exprid]); 00457 } 00458 00459 const STMT_LIST *expr_stmts(EXPRID exprid) const 00460 { 00461 Is_True(exprid < _exprid_to_stmtlist.size(), 00462 ("Out of bounds access to VN::expr_stmts()")); 00463 return &_exprid_to_stmtlist[exprid]; 00464 } 00465 00466 VN_EXPR::PTR valnum_expr(VN_VALNUM vn) const 00467 { 00468 return _vn_to_expr[vn]; 00469 } 00470 00471 EXPRID last_exprid() const 00472 { 00473 return _exprid_to_vn.size() - 1; 00474 } 00475 00476 VN_VALNUM last_valnum() const 00477 { 00478 return VN_VALNUM::Vn(_next_valnum.ordinal() - 1); 00479 } 00480 00481 // Modifications to a computed value numbering. 00482 // 00483 void reset_valnum(const CODEREP *cr, VN_VALNUM valnum) 00484 { 00485 _exprid_to_vn[_get_exprid(cr)] = valnum; 00486 } 00487 00488 void new_cr(const CODEREP *cr, VN_VALNUM valnum) 00489 { 00490 _exprid_to_vn[_append_exprid(cr)] = valnum; 00491 } 00492 00493 // In addition to the expr_valnum() mapping, we also print out the 00494 // reverse valnum->exprid mapping for all value numbers that are 00495 // neither Bottom() nor Top(). This reverse mapping will also 00496 // show the value number expression associated with each value number. 00497 // 00498 void print(FILE *fp = stderr, BOOL emit_stmt_maps = FALSE) const; 00499 00500 VN_VALNUM invent_unique_valnum() 00501 { 00502 VN_VALNUM unique = _next_valnum; 00503 _next_valnum = VN_VALNUM::Next(_next_valnum); 00504 return unique; 00505 } 00506 00507 // The following is a callback routine used during VN construction, 00508 // but may also be called after VN construction, in which case we always 00509 // simply create a unique value number. 00510 // 00511 VN_VALNUM valnum_integer(TCON int_tcon) 00512 { 00513 Is_True(MTYPE_is_integral(TCON_ty(int_tcon)), 00514 ("Illegal argument to VN::valnum_integer")); 00515 00516 if (_status.expr_to_vn != NULL) 00517 return _valnum_integer(Targ_To_Host(int_tcon), 00518 MTYPE_is_signed(TCON_ty(int_tcon))); 00519 else 00520 return invent_unique_valnum(); 00521 } 00522 00523 }; // class VN 00524 00525 00526 //--------------------------------------------------------------------------- 00527 // VALNUM_TO_EXPR_LIST: Maps each VN_VALNUM to a list of Coderep_id() numbers, 00528 // except Bottom() and Top() values. Note that the "[]" operator returns 00529 // a NULL value for Top(), Bottom(), or an invalid value number; Iterate 00530 // over this mapping from VN_VALNUM::First() to last_valnum(). 00531 //--------------------------------------------------------------------------- 00532 // 00533 class VALNUM_TO_EXPR_LIST 00534 { 00535 public: 00536 00537 typedef mempool_allocator<VN::EXPRID> EXPRID_ALLOCATOR; 00538 typedef slist<VN::EXPRID, EXPRID_ALLOCATOR> EXPR_LIST; // linked list 00539 typedef EXPR_LIST::const_iterator EXPR_ITERATOR; 00540 00541 private: 00542 00543 typedef mempool_allocator<EXPR_LIST> EXPRLIST_ALLOCATOR; 00544 vector<EXPR_LIST, EXPRLIST_ALLOCATOR> _map; 00545 00546 public: 00547 00548 VALNUM_TO_EXPR_LIST(const VN &vn, MEM_POOL *mpool = Malloc_Mem_Pool); 00549 00550 BOOL is_empty(const VN_VALNUM& v) const 00551 { 00552 return (v.is_top() || v.is_bottom() || _map[v.ordinal()].empty()); 00553 } 00554 00555 INT32 size(const VN_VALNUM& v) const 00556 { 00557 return ((v.is_top() || v.is_bottom())? 0 : _map[v.ordinal()].size()); 00558 } 00559 00560 VN::EXPRID front(const VN_VALNUM& v) const 00561 { 00562 if (v.is_top() || v.is_bottom() || _map[v.ordinal()].empty()) 00563 return 0; 00564 else 00565 return _map[v.ordinal()].front(); 00566 } 00567 00568 EXPR_ITERATOR begin(const VN_VALNUM& v) const 00569 { 00570 return ((v.is_top() || v.is_bottom())? 00571 EXPR_ITERATOR() : _map[v.ordinal()].begin()); 00572 } 00573 00574 EXPR_ITERATOR end(const VN_VALNUM& v) const 00575 { 00576 return ((v.is_top() || v.is_bottom())? 00577 EXPR_ITERATOR() : _map[v.ordinal()].end()); 00578 } 00579 00580 }; // VALNUM_TO_EXPR_LIST 00581 00582 00583 #endif // opt_vn_INCLUDED
1.5.6