00001 /* 00002 00003 Copyright (C) 2000, 2001 Silicon Graphics, Inc. All Rights Reserved. 00004 00005 This program is free software; you can redistribute it and/or modify it 00006 under the terms of version 2 of the GNU General Public License as 00007 published by the Free Software Foundation. 00008 00009 This program is distributed in the hope that it would be useful, but 00010 WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 00012 00013 Further, this software is distributed without any warranty that it is 00014 free of the rightful claim of any third person regarding infringement 00015 or the like. Any license provided herein, whether implied or 00016 otherwise, applies only to this software file. Patent licenses, if 00017 any, provided herein do not apply to combinations of this program with 00018 other software, or any other product whatsoever. 00019 00020 You should have received a copy of the GNU General Public License along 00021 with this program; if not, write the Free Software Foundation, Inc., 59 00022 Temple Place - Suite 330, Boston MA 02111-1307, USA. 00023 00024 Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pky, 00025 Mountain View, CA 94043, or: 00026 00027 http://www.sgi.com 00028 00029 For further information regarding this notice, see: 00030 00031 http://oss.sgi.com/projects/GenInfo/NoticeExplan 00032 00033 */ 00034 00035 00036 #ifndef sxlist_INCLUDED 00037 #define sxlist_INCLUDED "sxlist.h" 00038 00039 // class SX_PNODE : public CHAIN_NODE 00040 // 00041 // This data structure describes how a scalar is used within a loop. 00042 // Actually, it precomputes information about privatizability assuming 00043 // transformations may only occur beween loops s1 and s2, say, where s1 00044 // and s2 are in the same SNL. One can then query this structure to find 00045 // out what the situation is for a scalar (transformation illegal, 00046 // scalar expansion req'd at a given level, transformation legal w/o 00047 // scalar expansion) for SNL transformations affecting loops x through s2, 00048 // where s1<=x<=s2. That is, you ask "if I transform x through to the inner 00049 // of the SNL, is that legal". The way things are set up, if the answer is 00050 // yes, the scalar is distributable. Inside the outermost definition of the 00051 // scalar, there must either be no defs of the scalar, or 00052 // all defs and uses must be reductions, else the nest is considered 00053 // untransformable. TODO OK. This is conservative. Thus, we miss 00054 // 00055 // do i 00056 // s = 1 00057 // do j 00058 // s = -s 00059 // 00060 // which after scalar expansion and distribution, is 00061 // 00062 // do i 00063 // s[i] = 1 00064 // do i 00065 // do j 00066 // s[i] = -s[i] 00067 // 00068 // which has the dependence (0,+), which is no problem much of the time. 00069 // So the SX_INFO could be enhanced to handle this simply by 00070 // noting that if it's privatizable at a level and the only other defs and 00071 // uses are one level further in, then expansion is legal (though distribution 00072 // of that inner code, if it's not the inner loop, isn't), etc. 00073 // 00074 // 00075 // SX_PNODE is normally built by Make_Sx_Info(), so 00076 // here I show how the information is used. The outer possible loop 00077 // being transformed is at depth s1, and the inner at depth s2. 00078 // 00079 // WN* Wn_Symbol() 00080 // 00081 // A node which belongs to the equivalence class of the nodes 00082 // being scalar expanded. 00083 // 00084 // const SYMBOL& Symbol() const 00085 // 00086 // The symbol of interest. For most preciseness, renaming should 00087 // have been done. Otherwise, will need to be conservative. 00088 // 00089 // enum STATUS { ILLEGAL, SE_REQD, SE_NOT_REQD}; 00090 // 00091 // STATUS Transformable(outer, permutation, nloops) const; 00092 // 00093 // s1 <= outer <= s2. If we want to transform [outer,s2], but this 00094 // scalar prevents that, return ILLEGAL. If this transf doesn't, 00095 // but scalar expansion is required, return SE_REQD. In this case 00096 // there are guaranteed to be no dependences, and distribution of 00097 // the scalar is legal. Finally, if the nest is transformable 00098 // (and optionally distributable) without transformation, return 00099 // SE_NOT_REQD. 00100 // 00101 // If you specify the optional 'permutation' of length 'nloops', 00102 // Transformable() will return SE_NOT_REQD in one additional case 00103 // where without this information it had to return SE_REQD. This 00104 // is the case where the scalar is defined only over the set of 00105 // loops whose order does not change in the permutation. 00106 // 00107 // INT Expansion_Depth() const 00108 // 00109 // For when Transformable() returns SE_REQD, this tells you how to 00110 // expand the scalar. 00111 // If 0, the outermost def occurs inside the outermost loop. 00112 // If indeed the loop is scalar expandable, then you must expand 00113 // this variable s to s[i_{0}, i_{1}, ... i_{Expansion_Depth}]. 00114 // This value is exactly the depth of the "defining definiton". 00115 // That is, if we have 00116 // DO i 00117 // x = 00118 // DO j 00119 // use(x) 00120 // then the expansion depth is zero. 00121 // 00122 // BOOL Has_Reductions() const 00123 // 00124 // True if reduction found. 00125 // 00126 // WN* Reduction_Carried_By() const 00127 // 00128 // If Has_Reductions(), the loop_stmt for uses in that reduction 00129 // E.g. 00130 // s = 0 00131 // do i 00132 // s += ... 00133 // Reduction_Carried_By() is a pointer to loop i 00134 // 00135 // void Print(FILE*) const 00136 // 00137 // SX_INFO 00138 // 00139 // Holds all information about scalars. 00140 // 00141 // SX_PLIST Plist; 00142 // 00143 // INT First_Transformable_Depth(const SNL_PLIST_NODE** p =NULL) const 00144 // If no scalars, returns 0. Otherwise return largest 00145 // outer_se_reqd on Plist. Transformations involving loops 00146 // with depths smaller than the returned value are illegal. 00147 // Otherwise, legal. If p is not NULL, set *p to point to 00148 // the node that caused the problem. 00149 // 00150 // SX_PNODE* Find(const SYMBOL&); 00151 // const SX_PNODE* Find(const SYMBOL&) const; 00152 // void Enter(WN* wn_def, const SYMBOL&, 00153 // WN* reduction_carried_by, 00154 // INT se_not_depth, INT se_depth, 00155 // INT defining_def_depth); 00156 // void Remove(SX_PNODE*); 00157 // Take this node off the list and free it. 00158 // void Print(FILE*) const; 00159 // Print 00160 // SX_INFO(MEM_POOL*) 00161 // Construct one with of these with nothing in it. 00162 // 00163 // TODO: The important thing to fix is homing. If we have 00164 // do i 00165 // t = a(i) 00166 // do j 00167 // use(t) 00168 // then t will be expanded to t(i), where it would have been fine to use 00169 // a(i). Likewise, for 00170 // do i 00171 // t = a(i) 00172 // do j 00173 // t += 00174 // a(i) = t 00175 // one just replaces t with a(i) and removes the non-perfect statements. 00176 // Finally, 00177 // do i 00178 // t = 0 00179 // do j 00180 // t += 00181 // a(i) = t 00182 // one can do the same but replace the upper non-perfect statement with a(i)=0. 00183 // 00184 // TODO OK: If we always scalar expanded, would minvariant always be able 00185 // to remove it? If so, we could expand all the time. That would allow us 00186 // to handle the case we talk about missing at the top of these comments. 00187 00188 class SX_PLIST; 00189 class SX_PITER; 00190 class SX_CONST_PITER; 00191 class SX_PNODE; 00192 class SX_INFO; 00193 00194 class SX_PNODE : public CHAIN_NODE { 00195 DECLARE_CHAIN_NODE_CLASS(SX_PNODE); 00196 friend class SX_PLIST; 00197 friend class SX_PITER; 00198 friend class SX_INFO; 00199 private: 00200 WN* _wn_symbol; 00201 SYMBOL _symbol; 00202 BOOL _finalize; 00203 BOOL _lcd_depth; 00204 WN* _reduction_carried_by; 00205 mINT8 _outer_se_reqd; 00206 mINT8 _outer_se_not_reqd; 00207 mINT8 _defining_def_depth; 00208 SX_PNODE(WN* wn_sym, const SYMBOL& symbol, WN* reduction_carried_by, 00209 INT outer_se_reqd, INT outer_se_not_reqd, INT defining_def_depth, 00210 INT lcd_depth, BOOL finalize); 00211 ~SX_PNODE() {} 00212 public: 00213 enum STATUS {ILLEGAL=234, SE_REQD, SE_NOT_REQD}; 00214 WN* Wn_Symbol() const {return _wn_symbol;} 00215 const SYMBOL& Symbol() const {return _symbol;} 00216 BOOL Finalize() const {return _finalize;} 00217 BOOL Lcd_Depth() const {return _lcd_depth;} 00218 BOOL Has_Reduction() const {return _reduction_carried_by != NULL;} 00219 WN* Reduction_Carried_By() const {return _reduction_carried_by;} 00220 void Set_Reduction_Carried_By(WN* wn) {_reduction_carried_by = wn;} 00221 INT Expansion_Depth() const {return _defining_def_depth;} 00222 STATUS Transformable(INT depth, INT* permutation = NULL, INT nloops = 0) 00223 const; 00224 STATUS Splittable(INT split_depth, INT innermost_depth) const 00225 {return innermost_depth < split_depth || _defining_def_depth >= 00226 split_depth ? SE_NOT_REQD : SE_REQD; } 00227 void Print(FILE* fp) const; 00228 // normal users don't know what these are 00229 INT Outer_Se_Reqd() const {return _outer_se_reqd;} 00230 INT Outer_Se_Not_Reqd() const {return _outer_se_not_reqd;} 00231 }; 00232 00233 class SX_PLIST: public CHAIN { 00234 DECLARE_CHAIN_CLASS(SX_PLIST, SX_PNODE); 00235 private: 00236 friend class SX_INFO; 00237 MEM_POOL* _pool; 00238 public: 00239 SX_PLIST(MEM_POOL* pool) : _pool(pool), CHAIN() {} 00240 void Print(FILE *fp) const; 00241 ~SX_PLIST(); 00242 }; 00243 00244 class SX_PITER: public CHAIN_ITER { 00245 DECLARE_CHAIN_ITER_CLASS(SX_PITER, SX_PNODE, SX_PLIST) 00246 public: 00247 ~SX_PITER() {} 00248 }; 00249 00250 class SX_CONST_PITER: public CHAIN_ITER { 00251 DECLARE_CHAIN_CONST_ITER_CLASS(SX_CONST_PITER, SX_PNODE, 00252 SX_PLIST) 00253 public: 00254 ~SX_CONST_PITER() {} 00255 }; 00256 00257 struct SX_INFO { 00258 public: 00259 SX_PLIST Plist; 00260 SX_INFO(MEM_POOL* p) : Plist(p) {} 00261 SX_INFO(const SX_INFO& pinfo, WN* orig, WN* copy, MEM_POOL* pool); 00262 SX_INFO(const SX_INFO& pinfo, WN* orig, HASH_TABLE<WN*,WN*>* loop_map, 00263 MEM_POOL* pool); 00264 ~SX_INFO() {} 00265 SX_PNODE* Find(const SYMBOL&); 00266 const SX_PNODE* Find(const SYMBOL&) const; 00267 void Enter(WN* wn_def, const SYMBOL&, WN* reduction_carried_by, 00268 INT se_not_depth, INT se_depth, INT defining_def_depth, 00269 INT lcd_depth, BOOL finalize); 00270 void Remove(SX_PNODE*); 00271 void Print(FILE*) const; 00272 INT First_Transformable_Depth(const SX_PNODE** = NULL) const; 00273 void Make_Sx_Info(WN* wn_outer, INT nloops, BOOL ignore_illegal=FALSE); 00274 void Update_Reduction_Loop_Stmts(WN* wn_inner); 00275 INT Lcd_Depth(); 00276 BOOL Must_Finalize(); 00277 private: 00278 void Handle_Use(WN* wn_use, INT depth, HASH_TABLE<WN*,BOOL>* loops); 00279 void Handle_Index_Variable_Def(WN* wn_def, WN* wn_rep_def, 00280 INT depth); 00281 BOOL Analyze_Reduction(WN* wn_def, INT outer, STACK<WN*>* 00282 equivalence_class, DOLOOP_STACK* dostack, WN** wn_non_red_def_ptr, 00283 INT* non_red_depth_ptr, WN** wn_red_loop_stmt_ptr); 00284 void Handle_Other_Def(WN* wn_def, WN* wn_rep_def, INT outer, 00285 INT inner, INT depth, DOLOOP_STACK* dostack); 00286 void Handle_Def(WN* wn_def, WN* wn_rep_def, INT outer, INT inner, 00287 INT depth, DOLOOP_STACK* dostack); 00288 void Walk(WN* wn, INT outer, INT inner, INT depth, 00289 HASH_TABLE<WN*,BOOL>* loops, DOLOOP_STACK* dostack); 00290 }; 00291 00292 #endif /* sxlist_INCLUDED */
1.5.6