00001 //-*-c++-*- 00002 00003 /* 00004 * Copyright 2004, 2005, 2006 PathScale, Inc. All Rights Reserved. 00005 */ 00006 00007 // ==================================================================== 00008 // ==================================================================== 00009 // 00010 // Module: opt_vn_expr.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_expr.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 // INCLUSION DEPENDENCIES: 00051 // 00052 // Before including this file, you must also include the following 00053 // files directly or indirectly: 00054 // 00055 // common/com/defs.h 00056 // common/util/errors.h 00057 // common/com/targ_const.h 00058 // 00059 // 00060 // INTERFACE DESCRIPTION: 00061 // 00062 // This file defines three classes: 00063 // 00064 // VN_VALNUM: Our value-number representation. Value numbering 00065 // is an abstract program interpretation mechanism which will 00066 // use VN_VALNUM as its value domain. We take two different 00067 // views of value numbers. For hashing purposes we view two 00068 // value numbers as identical (operator '==') only if they are 00069 // truly exactly the same. 00070 // 00071 // For VN_EXPR:simplify() purposes we view the range of value 00072 // numbers as a lattice, where a Bottom() value is different from 00073 // any value, even other bottom values), while a Top() value 00074 // matches any other value except a Bottom() value. Literals 00075 // match only identical literals. This lattice view of equality 00076 // is embodied by the "equivalent_to()" method. 00077 // 00078 // VN_EXPR: Our representation of expressions formed from 00079 // value numbers. This is the domain of expressions over 00080 // which value numbering operates. We provide mechanisms 00081 // for folding value number expressions into simpler ones 00082 // (fold method) and to hash them into a hash-table. Note 00083 // that we have included a notion of memory locations (MEMLOC) 00084 // in our expression taxonomy, which can be viewed as a form of 00085 // lvalue expression that allows us to handle indirect loads 00086 // and stores. 00087 // 00088 // VN_EXPR_MAP: A mapping from each value number to its defining 00089 // value number expression. Bottom() and Top() always map to 00090 // a NULL expression, and cannot be changed. When a value number 00091 // is intrinsically defined (ENTRY_STMT or Chi node), then the 00092 // mapping should map the VN_VALNUM to a NULL expression. Such 00093 // use of NULL maps should obviate any need for a special kind 00094 // of VN_EXPR for Chi nodes or ENTRY_STMT nodes. 00095 // 00096 // This map automatically grows to accommodate any value number it 00097 // is set (set_map) for, so be careful to only define maps for 00098 // valid value numbers. If the NULL valued holes in the map turn 00099 // out to be very large, it may be better to use a more compact 00100 // representation for this map (TODO?). 00101 // 00102 // Note that we only export methods to create mempool allocated 00103 // VN_EXPR objects. This is because the VN_EXPR class really 00104 // represents a taxonomy of expression kinds (literal, unary, binary, 00105 // phi, etc.), and this taxonomy and associated memory management 00106 // is easiest maintained in terms of object references. As a 00107 // consequence, the client of a VN_EXPR can never create stack 00108 // allocated VN_EXPR objects or an array of allocated VN_EXPR objects, 00109 // only a stack or array of VN_EXPR object pointers. 00110 // 00111 // From a client's perspective, a VN_EXPR should be viewed as a union 00112 // of the various kinds (VN_EXPR::KIND). Some accessors are only valid 00113 // for certain kinds of expression and we assert when accessors are 00114 // called for the wrong kinds of expressions. 00115 // 00116 // We do allow creation and simplification of VN_EXPR objects with Top() 00117 // or Bottom() value numbers as operands, but we *never* allow hashing 00118 // of such objects (the hash() method will assert!). 00119 // 00120 // Each public method is described in further detail at its point 00121 // of declaration below. 00122 // 00123 // 00124 // IMPLEMENTATION DETAILS: 00125 // 00126 // We divide the VN_EXPR objects into different subclasses of 00127 // expressions depending on the kind of expression (VN_EXPR::KIND) 00128 // we are dealing with. This is best expressed using an inheritance 00129 // hierarchy, and we therefore take the liberty here of creating an 00130 // inheritance hierarchy to represent this expression taxonomy. 00131 // 00132 // The user of a VN_EXPR need never be concerned with this taxonomy, 00133 // since it is made completely transparant through the class and object 00134 // interface provided through VN_EXPR. One consequence of this is that 00135 // we only export a means for a user to create a pointer to a VN_EXPR, 00136 // where the VN_EXPR is allocated using a given mempool. A VN_EXPR 00137 // may be deleted by means of the free() class method, which in an 00138 // implementation defined manner may or may not actually free up the 00139 // memory. To free up all allocated VN_EXPR memory (i.e. any free-lists 00140 // kept around), we provide the method VN_EXPR::Reclaim_Free_Lists(). 00141 // This should be done even when the memory reclamation is automatic 00142 // (e.g. by means of popping a mempool), since the free-lists is an 00143 // odd mix if malloc'ed and CXX_ALLOC'ed memory. 00144 // 00145 // POSSIBLE IMPROVEMENTS (TODO): 00146 // 00147 // If the NULL valued holes in the VN_EXPR_MAP turn out to be very 00148 // large, it may be better to use a more compact representation for 00149 // this map. 00150 // 00151 // Currently, we never expect to see Top() operands in any expressions 00152 // other than phi nodes, and as such the optimistic simplification of 00153 // other kinds of expressions is just there for generality and to support 00154 // potential future functionality. We can add more aggressive 00155 // simplification incrementally, while leaving open the possibility 00156 // that simplified VN_EXPRs may have Top() operands. 00157 // Ideally we should have various degrees of simplification. The most 00158 // aggressive version should always reduces an expression into a form 00159 // without any Top() values, since *any* value can be substituted for 00160 // a Top() value. Conceivably, there may be cases, however, where a 00161 // less agressive simplification algorithm is desirable (e.g. to keep 00162 // the simplification implementation simpler, or to delay the folding 00163 // of Top() values until more context is available). 00164 // This is then a note to keep adding more aggressive rules of 00165 // simplification, and perhaps allow various degrees of simplification. 00166 // 00167 // CONSTRAINTS: 00168 // 00169 // A UNARY VN_EXPR should never be a PARM expression, except when returned 00170 // as a result of "simplify()". 00171 // 00172 // A BINARY VN_EXPR cannot be a COMMA or RCOMMA expression. 00173 // 00174 // SEE ALSO: 00175 // 00176 // opt_vn_hashtab.h : A mapping from VN_EXPR::PTR to VN_VALNUM, based on 00177 // a hashing algorithm. 00178 // 00179 // opt_vn.h : Top level interface to the value-numbering 00180 // algorithms, and associated resultant maps. 00181 // 00182 // ==================================================================== 00183 // ==================================================================== 00184 00185 00186 #ifndef opt_vn_expr_INCLUDED 00187 #define opt_vn_expr_INCLUDED "opt_vn_expr.h" 00188 00189 #include "segmented_array.h" 00190 00191 // Some common universally applicable number for the chunksizes used in 00192 // segmented arrays, mainly used to minimize the number of instantiations 00193 // of SEGMENTED_ARRAY. 00194 // 00195 #define VN_BUFFER_CHUNKSIZE 256 00196 00197 00198 //---------------------- A Value Number ------------------------ 00199 //-------------------------------------------------------------- 00200 // 00201 class VN_VALNUM 00202 { 00203 private: 00204 00205 UINT32 _num; 00206 00207 VN_VALNUM(UINT32 v): _num(v) {} 00208 00209 static UINT32 _top() {return UINT32_MAX;} 00210 static UINT32 _bottom() {return 0U;} 00211 00212 public: 00213 00214 static VN_VALNUM First() {return VN_VALNUM(1);} 00215 00216 static VN_VALNUM Next(const VN_VALNUM prev) 00217 { 00218 return VN_VALNUM(prev._num + 1); 00219 } 00220 00221 static VN_VALNUM Top() {return VN_VALNUM(_top());} // Matches all 00222 00223 static VN_VALNUM Bottom() {return VN_VALNUM(_bottom());} // Matches none 00224 00225 static VN_VALNUM Vn(UINT32 i) {return VN_VALNUM(i);} // For internal use! 00226 00227 VN_VALNUM() : _num(_bottom()) {} 00228 VN_VALNUM(const VN_VALNUM &v) : _num(v._num) {} 00229 00230 VN_VALNUM &operator= (const VN_VALNUM &v) {_num = v._num; return *this;} 00231 BOOL operator< (const VN_VALNUM &v) const {return _num < v._num;} 00232 BOOL operator> (const VN_VALNUM &v) const {return _num > v._num;} 00233 BOOL operator<= (const VN_VALNUM &v) const {return _num <= v._num;} 00234 BOOL operator>= (const VN_VALNUM &v) const {return _num >= v._num;} 00235 BOOL operator== (const VN_VALNUM &v) const {return _num == v._num;} 00236 BOOL operator!= (const VN_VALNUM &v) const {return _num != v._num;} 00237 00238 BOOL is_bottom() const {return _num == _bottom();} 00239 BOOL is_top() const {return _num == _top();} 00240 BOOL equivalent_to(const VN_VALNUM &v) const 00241 { 00242 return (!(is_bottom() || v.is_bottom()) && 00243 (_num == v._num || is_top() || v.is_top())); 00244 } 00245 00246 UINT32 ordinal() const {return _num;} // Only for use by VN_EXPR_MAP! 00247 00248 void print(FILE *fp = stderr) const; 00249 INT32 sprint(char *buf) const; // buf must be large enough to hold "vnNNN"! 00250 00251 }; // VN_VALNUM 00252 00253 00254 //---------------- A Value Number Expression ------------------- 00255 //-------------------------------------------------------------- 00256 // 00257 class VN; // Defined in opt_vn.h 00258 class VN_EXPR 00259 { 00260 public: 00261 00262 typedef VN_EXPR *PTR; 00263 typedef const VN_EXPR *CONST_PTR; 00264 00265 protected: 00266 00267 static MEM_POOL *_Mpool; 00268 00269 public: 00270 00271 // This enumeration should be replaced by an enumeration in PHI_NODE 00272 // when we upgrade our intermediate representatiojn to support gated 00273 // phi nodes. I just insert it here now as a temporary placeholder. 00274 // 00275 enum PHI_TAG {PHI_TAG_UNKNOWN}; 00276 00277 // The kinds of expressions a VN_EXPR may represent. 00278 // 00279 enum KIND {LITERAL, // Constant value 00280 UNARY, // One operand 00281 BINARY, // Two operands 00282 TERNARY, // Three operands 00283 INTR_OP, // Intrinsic function call 00284 PHI, // SSA Phi node 00285 LDA_ADDR, // A symbol's address 00286 ARRAY_ADDR, // An array element's address 00287 MEMLOC // The value of a memory location 00288 #ifdef KEY 00289 ,CALL_OP // Pure function call op 00290 #endif 00291 }; 00292 00293 // A call to activate the memory allocation scheme for VN_EXPR 00294 // objects. Such objects should always be created using one of 00295 // the Create_xxx() methods, and should always be deleted using the 00296 // "free()" method. This method MUST be called before any other 00297 // method of the VN_EXPR class. If there is already a free-list 00298 // active when this method is called, then the old one will be 00299 // discarded but not reclaimed. 00300 // 00301 static void Init_Free_Lists(MEM_POOL *mpool = Malloc_Mem_Pool); 00302 00303 // The following method will reclaim memory for all VN_EXPR nodes 00304 // currently accumulated on free lists, and it will reclaim memory 00305 // for the free-list itself. This is the ONLY way to reclaim 00306 // VN_EXPR memory! Following this call, a new call to Init_Free_Lists() 00307 // is needed before any call to Create_xxx() methods. Never call this 00308 // method before all VN_EXPR objects are free()'ed (i.e. until they are 00309 // all on the free-list). 00310 // 00311 static void Reclaim_Free_Lists(); 00312 00313 // The following are constructors for the various kinds of expressions 00314 // we handle. The operands for expressions with a variable number of 00315 // operands (INTRINISC_OP, PHI and ARRAY_ADDR objects) must be set with 00316 // separate calls to "set_opnd()"; initially such operands are 00317 // VN_VALNUM::Bottom(). 00318 // 00319 // The value number operands to an ARRAY_ADDR should always be set in 00320 // the following order (same order as for an OPR_ARRAY whirl node): 00321 // 00322 // opnd(0) == base_address 00323 // opnd(1..num_dims()) == dimension_size 00324 // opnd(num_dims()+1..num_dims()+num_dims()) == index 00325 // 00326 static PTR Create_Literal(const TCON &tcon); 00327 static PTR Create_Unary(OPCODE opc, 00328 const VN_VALNUM &vn1); 00329 static PTR Create_Binary(OPCODE opc, 00330 const VN_VALNUM &vn1, 00331 const VN_VALNUM &vn2); 00332 static PTR Create_Ternary(OPCODE opc, 00333 const VN_VALNUM &vn1, 00334 const VN_VALNUM &vn2, 00335 const VN_VALNUM &vn3); 00336 static PTR Create_Intr_Op(INTRINSIC intr_opc, 00337 UINT32 num_opnds); 00338 static PTR Create_Phi(UINT32 num_opnds, 00339 IDTYPE block_id, 00340 PHI_TAG phi_tag = PHI_TAG_UNKNOWN); 00341 static PTR Create_Lda_Addr(INT32 lda_cr_id); 00342 static PTR Create_Array_Addr(WN_ESIZE esize, INT32 num_dims); 00343 static PTR Create_Memloc(MTYPE dsctype, 00344 const VN_VALNUM &bytesize, 00345 const VN_VALNUM &offset, 00346 const VN_VALNUM &base_addr, 00347 const VN_VALNUM &vsym_valnum); 00348 #ifdef KEY 00349 static PTR Create_Call_Op(ST_IDX, UINT32); 00350 #endif 00351 00352 // The following will put "this" on a free list, and is the only 00353 // way to set a VN_EXPR object up for memory deallocation. 00354 // 00355 virtual void free() = 0; 00356 00357 // Accessors: The kind() and num_opnds() determine which of the following 00358 // accessors are valid for a VN_EXPR. Note that operands are enumerated 00359 // starting at i=0. The default implementations, for those that have one, 00360 // will assert when the method is called. 00361 // 00362 virtual KIND get_kind() const = 0; 00363 virtual UINT32 get_num_opnds() const = 0; 00364 virtual VN_VALNUM get_opnd(UINT i=0) const; // All, but LITERAL/LDA/MEMLOC 00365 virtual BOOL has_top_opnd() const = 0; 00366 virtual BOOL has_bottom_opnd() const = 0; 00367 virtual OPCODE get_opc() const; // UNARY,BINARY,TERNARY 00368 virtual INTRINSIC get_intr_opc() const; // INTR_OP 00369 virtual PHI_TAG get_phi_tag() const; // PHI 00370 virtual IDTYPE get_block_id() const; // PHI 00371 virtual const TCON &get_tcon() const; // LITERAL 00372 virtual INT32 get_lda_cr_id() const; // LDA 00373 virtual INT32 get_num_dims() const; // ARRAY_ADDR 00374 virtual WN_ESIZE get_esize() const; // ARRAY_ADDR 00375 virtual MTYPE get_dsctype() const; // MEMLOC 00376 virtual VN_VALNUM get_bytesize() const; // MEMLOC 00377 virtual VN_VALNUM get_offset() const; // MEMLOC 00378 virtual VN_VALNUM get_base_addr() const; // MEMLOC 00379 virtual VN_VALNUM get_vsym(UINT i=0) const; // MEMLOC/INTR_OP (ivar mu) 00380 #ifdef KEY 00381 virtual ST_IDX get_aux_id() const; // PURE_CALL_OP 00382 #endif 00383 00384 // Modifiers: 00385 // 00386 // set_opnd() will change the given operand of "this" expression, where 00387 // operand numbers are zero (0) based. set_opnd_vsym() will change 00388 // the vsym associated with the given parameter of "this" INTR_OP 00389 // expression, where the parameter numbers (i) are zero based. 00390 // 00391 // simplify() will try to fold "this" expression into a simpler 00392 // new expression or into a value number. When successful, "this" 00393 // expression will be freed up (this->free()), and a new expression 00394 // will be returned; otherwise, this is returned. Note that simplify 00395 // always returns a new expression with fewer operands than "this" 00396 // expression (except when a unary expression folds into a value-number). 00397 // When the expression folds into a single value number, a unary 00398 // OPC_VPARM expression is returned. Such an expression cannot be 00399 // hashed, and MUST BE SPECIALLY RECOGNIZED BY THE CLIENT of this 00400 // class. An expression with a Bottom() operand will always simplify 00401 // to a Bottom() value number. 00402 // 00403 virtual void set_opnd(UINT32 i, VN_VALNUM vn); 00404 virtual void set_opnd_vsym(UINT32 i, VN_VALNUM vn); // INTR_OP 00405 virtual PTR simplify(VN *v) = 0; 00406 00407 // Any VN_EXPR can be hashed into a value suited for distribution 00408 // across a hash-table (see opt_vn_hashtab.h). Hashing will apply 00409 // canonicalization rules such as commutativity to catch as many 00410 // equivalences as possible, which means this expression may change 00411 // as a side-effect. This method should never be called when 00412 // this->has_top_opnd() || this->has_bottom_opnd()! 00413 // 00414 virtual size_t hash() = 0; 00415 00416 // Inequality/Equality tests: 00417 // 00418 virtual BOOL is_equal_to(CONST_PTR expr) const = 0; 00419 00420 virtual void print(FILE *fp = stderr) const = 0; 00421 00422 }; // VN_EXPR 00423 00424 00425 //-------------- A Value Number Expression Map ----------------- 00426 //-------------------------------------------------------------- 00427 // 00428 class VN_EXPR_MAP 00429 { 00430 private: 00431 00432 SEGMENTED_ARRAY<VN_EXPR::PTR, VN_BUFFER_CHUNKSIZE> _map; 00433 00434 public: 00435 00436 VN_EXPR_MAP(MEM_POOL *mpool): _map(mpool) {} 00437 00438 ~VN_EXPR_MAP() 00439 { 00440 for (INT32 i = _map.Size() - 1; i >= 0; i--) 00441 if (_map[i] != NULL) 00442 _map[i]->free(); 00443 _map.Delete_last(_map.Size()); 00444 } 00445 00446 // Resets all expressions referenced in the map (puts them on free- 00447 // lists) between the two given value numbers provided (inclusively), 00448 // where is_true(from_vn < to_vn) for the call to have any effect. 00449 // 00450 void reset_exprs(VN_VALNUM from_vn, VN_VALNUM to_vn) 00451 { 00452 INT32 max = (to_vn.ordinal() < _map.Size()? 00453 to_vn.ordinal() : _map.Size() - 1); 00454 00455 for (INT32 i = from_vn.ordinal(); i <= max; i++) 00456 if (_map[i] != NULL) 00457 { 00458 _map[i]->free(); 00459 _map[i] = NULL; 00460 } 00461 } 00462 00463 // Resets all expressions referenced in the map (puts them on free- 00464 // lists), and sets all value numbers to map to NULL expressions. 00465 // 00466 void reset_all_exprs() 00467 { 00468 reset_exprs(first(), last()); 00469 } 00470 00471 // First value number in the mapping. Use VN_VALNUM::Next() to iterate. 00472 // Returns VN_VALNUM::Bottom() when the mapping is empty. 00473 // 00474 VN_VALNUM first() const 00475 { 00476 return (_map.Size() > 0? VN_VALNUM::First() : VN_VALNUM::Bottom()); 00477 } 00478 00479 // Last value number in the mapping. Returns VN_VALNUM::Bottom() 00480 // when the mapping is empty. 00481 // 00482 VN_VALNUM last() const 00483 { 00484 return (_map.Size() > 0? 00485 VN_VALNUM::Vn(_map.Size() - 1) : 00486 VN_VALNUM::Bottom()); 00487 } 00488 00489 // Always NULL for Top() and Bottom(). 00490 // 00491 VN_EXPR::PTR operator[] (const VN_VALNUM& v) const 00492 { 00493 if (v.is_top() || v.is_bottom()) 00494 return NULL; 00495 else 00496 { 00497 const UINT32 i = v.ordinal(); 00498 return ((i >= _map.Size())? NULL : _map[i]); 00499 } 00500 } // operator[] 00501 00502 00503 // Never call this for a Top() or Bottom() value number. Sets 00504 // a mapping as indicated (creating a new one if none exists). 00505 // 00506 void set_map(const VN_VALNUM& v, VN_EXPR::PTR expr) 00507 { 00508 FmtAssert(!(v.is_top() || v.is_bottom()), 00509 ("Illegal value number in call to VN_EXPR_MAP::set_map")); 00510 { 00511 const UINT32 i = v.ordinal(); 00512 for (UINT32 sz = _map.Size(); sz <= (i+1); _map.New_entry(sz) = NULL); 00513 _map[i] = expr; 00514 } 00515 } // set_map 00516 00517 }; // VN_EXPR_MAP 00518 00519 00520 #endif // opt_vn_expr_INCLUDED
1.5.6