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 #ifndef _ara_loop_info_INCLUDED
00060 #define _ara_loop_info_INCLUDED
00061
00062 #ifndef lnopt_main_INCLUDED
00063 #include "lnopt_main.h"
00064 #endif
00065 #ifndef dep_graph_INCLUDED
00066 #include "dep_graph.h"
00067 #endif
00068 #ifndef lnoutils_INCLUDED
00069 #include "lnoutils.h"
00070 #endif
00071 #ifndef _ara_region_INCLUDED
00072 #include "ara_region.h"
00073 #endif
00074 #ifndef snl_INCLUDED
00075 #include "snl.h"
00076 #endif
00077 #ifndef parallel_INCLUDED
00078 #include "parallel.h"
00079 #endif
00080 #ifndef wnmp_INCLUDED
00081 #include "wn_mp.h"
00082 #endif
00083 #ifndef access_vector_INCLUDED
00084 #include "access_vector.h"
00085 #endif
00086
00087 extern BOOL Loop_Invariant_Access(WN* wn_array, const WN* loop);
00088 extern BOOL Inside_Lego_Tiled_Loop(WN* wn_loop);
00089
00090 extern MEM_POOL ARA_memory_pool;
00091
00092
00093 class ARA_LOOP_INFO;
00094
00095
00096 class KERNEL_IMAGE : public SLIST_NODE {
00097 DECLARE_SLIST_NODE_CLASS(KERNEL_IMAGE);
00098
00099 ACCESS_ARRAY * _kernel;
00100 REGION * _region;
00101 INT16 _depth;
00102 INT16 _projected_level;
00103 BOOL _decoupled;
00104 BOOL * _is_independent;
00105 BOOL * _changed;
00106
00107 public:
00108
00109 KERNEL_IMAGE(KERNEL_IMAGE* k);
00110 KERNEL_IMAGE(const ACCESS_ARRAY * a, ARA_LOOP_INFO *ara_info);
00111 KERNEL_IMAGE(const ACCESS_ARRAY * a);
00112 ~KERNEL_IMAGE();
00113
00114
00115 REGION * Region(){ return _region; }
00116 void Set_Region(REGION* r){ _region=r; }
00117 ACCESS_ARRAY * Get_Kernel(){ return _kernel; }
00118 INT16 Depth(){ return _depth; }
00119 INT16 Projected_Level() { return _projected_level; }
00120 void Project(const INT i, const ARA_LOOP_INFO &ara_info);
00121 BOOL * Get_Independent_Loops() { return _is_independent; }
00122
00123
00124 };
00125
00126 class KERNEL_LIST : public SLIST {
00127 DECLARE_SLIST_CLASS(KERNEL_LIST, KERNEL_IMAGE);
00128
00129 public:
00130 ~KERNEL_LIST(){
00131 while (!Is_Empty()) CXX_DELETE(Remove_Headnode(),&ARA_memory_pool);
00132 }
00133
00134 };
00135
00136 class KERNEL_SLIST_CONST_ITER : public SLIST_ITER {
00137 DECLARE_SLIST_CONST_ITER_CLASS(KERNEL_SLIST_CONST_ITER, KERNEL_IMAGE, KERNEL_LIST);
00138 };
00139
00140 class KERNEL_SLIST_ITER : public SLIST_ITER {
00141 DECLARE_SLIST_ITER_CLASS(KERNEL_SLIST_ITER, KERNEL_IMAGE, KERNEL_LIST);
00142 };
00143
00144
00145
00146 class ARA_REF {
00147
00148 SYMBOL *_array;
00149 INT32 _offset;
00150 REGION_UN _image;
00151 mBOOL _has_bad_alias;
00152 mBOOL _need_last_value;
00153 mBOOL _is_loop_invariant;
00154 mBOOL _donot_care_invariant;
00155 mBOOL _is_unknown_size;
00156 mBOOL _is_too_messy;
00157
00158 public:
00159
00160 ARA_REF():_image()
00161 {
00162 _array = NULL;
00163 _offset = 0;
00164 _has_bad_alias = FALSE;
00165 _need_last_value = TRUE;
00166 _is_loop_invariant = FALSE;
00167 _donot_care_invariant = FALSE;
00168 _is_unknown_size = FALSE;
00169 _is_too_messy = FALSE;
00170 }
00171
00172 ARA_REF(ARA_REF &a):_image()
00173 {
00174 _array = CXX_NEW(SYMBOL(a._array),&ARA_memory_pool);
00175 _offset = a._offset;
00176 _has_bad_alias = a.Has_Bad_Alias();
00177 _need_last_value = a.Need_Last_Value();
00178 _is_loop_invariant = a.Is_Loop_Invariant();
00179 _donot_care_invariant = a.Donot_Care_Invariant();
00180 _is_unknown_size = a.Is_Unknown_Size();
00181 _is_too_messy = a.Is_Too_Messy();
00182 REGION_CONST_ITER a_iter(&a._image);
00183 for (const REGION *cur = a_iter.First();
00184 !a_iter.Is_Empty(); cur = a_iter.Next())
00185 _image.Append(CXX_NEW(REGION(*cur), &ARA_memory_pool));
00186 }
00187
00188 ARA_REF(WN *array_wn, INT32 offset, ARA_LOOP_INFO *ali);
00189 ARA_REF(SYMBOL *array_sym, REGION* new_region,
00190 ARA_LOOP_INFO *ali, BOOL is_invariant);
00191 #if 0
00192 void Add_Ref_Region(WN* ref, REGION* reg, ARA_LOOP_INFO & ali) {
00193 Is_True((_array==NULL) || _array->St()==WN_st(WN_array_base(ref)),
00194 ("ARA_REF_INFO::Add_Ref(), base arrays are different"));
00195 if (_array==NULL) {
00196 _array = CXX_NEW(SYMBOL(WN_array_base(ref)),
00197 &ARA_memory_pool);
00198 }
00199 _image.Add_Region(reg,ali);
00200 }
00201 #endif
00202
00203 ~ARA_REF()
00204 {
00205 if (_array) CXX_DELETE(_array, &ARA_memory_pool);
00206 }
00207
00208 const SYMBOL & Array() { return *_array; }
00209 INT32 & Offset() { return _offset; }
00210 BOOL Has_Bad_Alias() { return _has_bad_alias; }
00211 BOOL Has_Formal_Parameter();
00212 BOOL Need_Last_Value() { return _need_last_value; }
00213 BOOL Is_Loop_Invariant() { return _donot_care_invariant
00214 || _is_loop_invariant; }
00215 void Assign_Loop_Invariant(BOOL b) { _is_loop_invariant=b; }
00216 BOOL Donot_Care_Invariant() { return _donot_care_invariant; }
00217 void Set_Donot_Care_Invariant() { _donot_care_invariant=TRUE; }
00218 void Set_Whole_Array(BOOL set_invariant=TRUE);
00219 BOOL Is_Whole_Array() { return (_image.Head() && _image.Head()->Is_All()); }
00220 void Set_Bad_Alias() { _has_bad_alias = TRUE; }
00221 void Set_No_Last_Value() { _need_last_value = FALSE; }
00222 void Set_Need_Last_Value() { _need_last_value = TRUE; }
00223 void Set_Loop_Invariant(WN* loop);
00224 BOOL Is_Unknown_Size() { return _is_unknown_size; }
00225 void Set_Unknown_Size() { _is_unknown_size = TRUE; }
00226 BOOL Is_Too_Messy() { return _is_too_messy; }
00227 BOOL Is_Messy();
00228 void Set_Too_Messy() { _is_too_messy = TRUE; }
00229 REGION_UN & Image() { return _image; }
00230 void Add_Ref(ARA_REF *a, const ARA_LOOP_INFO &ali);
00231 void Print(FILE *fp) const;
00232 void WB_Print(FILE *fp) const;
00233 INT WB_Print(char* bf, INT ccount) const;
00234 void Print_Analysis_Info(FILE *fp, INT indent, DOLOOP_STACK &do_stack);
00235 };
00236
00237
00238
00239
00240
00241 typedef STACK<ARA_REF*> ARA_REF_ST;
00242
00243
00244
00245
00246
00247
00248 typedef STACK<ARA_LOOP_INFO*> ARA_LOOP_INFO_ST;
00249 typedef HASH_TABLE<ST*,BOOL> S_HTABLE;
00250
00251 class ARA_LOOP_INFO {
00252
00253 BOOL _invariant;
00254
00255 ARA_LOOP_INFO_ST _children;
00256 ARA_LOOP_INFO *_parent;
00257 WN *_loop;
00258 DO_LOOP_INFO *_info;
00259 KERNEL_LIST *_kernels;
00260 DOLOOP_STACK *_do_stack;
00261 STACK<WN*> *_invariant_symbols;
00262
00263 STACK<WN*> *_processed;
00264 STACK<WN*> _reduction;
00265 BOOL _inner_loop_is_suggested_parallel;
00266
00267
00268
00269
00270 BOOL _has_bad_region;
00271 ARA_REF_ST _def;
00272 ARA_REF_ST _may_def;
00273 ARA_REF_ST _use;
00274 ARA_REF_ST _pri;
00275
00276
00277 SCALAR_STACK _scalar_def;
00278 SCALAR_STACK _scalar_use;
00279 SCALAR_STACK _scalar_pri;
00280 SCALAR_STACK _scalar_may_def;
00281 STACK<BOOL> _scalar_last_value;
00282 STACK<BOOL> _bad_alias;
00283 STACK<BOOL> _scalar_always_defined;
00284
00285
00286 INT _dep_dist;
00287 BOOL _is_good;
00288 BOOL _has_last_value_array;
00289
00290 INT _peel_value;
00291
00292 STACK<SYMBOL> _scalar_vars;
00293 STACK<SYMBOL> _scalar_alias;
00294 STACK<SYMBOL> _scalar_no_final;
00295 STACK<SYMBOL> _scalar_bad_peel;
00296 STACK<INT> _ln_scalar_bad_peel;
00297 STACK<SYMBOL> _dep_vars;
00298 STACK<SYMBOL> _dep_source;
00299 STACK<SYMBOL> _dep_sink;
00300 STACK<INT> _ln_dep_source;
00301 STACK<INT> _ln_dep_sink;
00302 STACK<SYMBOL> _dep_bad_peel;
00303 STACK<INT> _ln_dep_bad_peel;
00304 STACK<SYMBOL> _partial_array_sec;
00305
00306 STACK<char*> _call_no_dep_vars;
00307 STACK<INT> _ln_call_no_dep_vars;
00308 STACK<SYMBOL> _array_no_dep_vars;
00309 STACK<INT> _ln_array_no_dep_vars;
00310 STACK<INT> _ln_misc_no_dep_vars;
00311
00312
00313 S_HTABLE * _live_use;
00314
00315
00316 WN* Create_Old_IF_Clause();
00317 BOOL Always_Enough_Parallel_Work(BOOL* has_left_right, INT* left,
00318 INT* right);
00319 float Tc_Parallel_Cost();
00320 float Tp_Parallel_Cost();
00321 WN* Create_New_IF_Clause(BOOL is_pdo);
00322 WN* Create_IF_Clause(BOOL is_pdo);
00323 float Const_Work_Estimate(WN* wn_loop, BOOL* minimum_only);
00324
00325
00326 void Reduction_List(REDUCTION_LIST *rlist);
00327
00328 public:
00329
00330 ARA_LOOP_INFO();
00331 ARA_LOOP_INFO(ARA_LOOP_INFO* p);
00332 ARA_LOOP_INFO(WN* wn, ARA_LOOP_INFO *p, const BOOL inv);
00333 void Copy_Some_Values(ARA_LOOP_INFO *p);
00334 ~ARA_LOOP_INFO();
00335 BOOL Inner_Loop_Is_Suggested_Parallel()
00336 { return _inner_loop_is_suggested_parallel; }
00337 BOOL Has_Bad_Region() { return _has_bad_region; }
00338 void Set_Bad_Region() { _has_bad_region = TRUE; }
00339 BOOL Has_Last_Value_Array() { return _has_last_value_array; }
00340 BOOL Invariant_Bounds() const { return _invariant; }
00341 void Add_Reduction(WN* wn) { _reduction.Push(wn); }
00342 STACK<WN*> & Reduction() { return _reduction; }
00343 ARA_LOOP_INFO_ST & Children() { return _children; }
00344 void Add_Child(ARA_LOOP_INFO *child){ _children.Push(child); }
00345 void Screen_Scalar_Conditional();
00346 const DO_LOOP_INFO * Info(){ return _info; }
00347 const WN * Loop() const { return _loop; }
00348 DOLOOP_STACK & Do_Stack() { return *_do_stack; }
00349 ARA_LOOP_INFO * Parent() const { return _parent; }
00350 mUINT8 Depth() const { return (_info) ? _info->Depth: 0; }
00351 ARA_REF_ST & DEF() { return _def; }
00352 ARA_REF_ST & MAY_DEF() { return _may_def; }
00353 ARA_REF_ST & USE() { return _use; }
00354 ARA_REF_ST & PRI() { return _pri; }
00355 SCALAR_STACK & SCALAR_MAY_DEF() { return _scalar_may_def; }
00356 SCALAR_STACK & SCALAR_DEF() { return _scalar_def; }
00357 SCALAR_STACK & SCALAR_USE() { return _scalar_use; }
00358 SCALAR_STACK & SCALAR_PRI() { return _scalar_pri; }
00359 void Add_Def(ARA_REF *ara_ref);
00360 void Add_May_Def(ARA_REF *ara_ref);
00361 void Add_Use(ARA_REF *ara_ref);
00362 void Add_Pri(ARA_REF *ara_ref);
00363 void Remove_Array_Info();
00364 void Annotate_Invariant_Pri();
00365 void Annotate_Invariant_Def();
00366 void Projection();
00367 BOOL Variable_Load();
00368 BOOL Bounds_Depend_On_Index(INT depth);
00369 void Default_For_Bad_Loop();
00370
00371
00372 KERNEL_LIST & Kernels() { return *_kernels; }
00373 REGION & Iteration_Space();
00374 void Set_Whole_Array();
00375 void Add_Invariant(WN* wn) { _invariant_symbols->Push(wn); }
00376 BOOL Is_Invariant(const SYMBOL &sym) const
00377 {
00378 for (INT i=0; i<_invariant_symbols->Elements(); ++i)
00379 if (SYMBOL(_invariant_symbols->Bottom_nth(i))==sym)
00380 return TRUE;
00381
00382 return FALSE;
00383 }
00384 void Add_Processed(WN* wn) { _processed->Push(wn); }
00385 BOOL Processed(const WN* wn)
00386 {
00387 for (INT i=0; i<_processed->Elements(); ++i)
00388 if (SYMBOL(_processed->Bottom_nth(i))==SYMBOL(wn))
00389 return TRUE;
00390
00391 return FALSE;
00392 }
00393 void Walk_Loop();
00394 BOOL Is_Covered(WN *wn);
00395 BOOL Is_Exposed(WN *wn)
00396 {
00397 return !Is_Covered(wn);
00398 }
00399 BOOL Is_Covered(ARA_REF* ref);
00400 BOOL Is_Exposed(ARA_REF* ref)
00401 {
00402 return !Is_Covered(ref);
00403 }
00404 void Print(FILE *fp, BOOL terse = FALSE) const;
00405 void Print_Analysis_Info();
00406 void WB_Print(FILE *fp, BOOL terse = FALSE) const;
00407 void CI_Print(FILE* fp);
00408 void Tlog_CI_Print();
00409 BOOL Is_Privatizable(WN* wn, BOOL definitely = TRUE);
00410 BOOL Dep_Is_Good() const { return _is_good; }
00411 INT Dep_Dist() const { return _dep_dist; }
00412 void Add_Dependence(INT dist)
00413 {
00414 if (!_is_good) return;
00415 if (_dep_dist==0||_dep_dist==dist) {
00416 _dep_dist = dist;
00417 } else {
00418 _dep_dist = 0;
00419 _is_good = FALSE;
00420 }
00421 }
00422 BOOL Need_Copyin()
00423 {
00424 for (INT i = 0; i < _use.Elements(); ++i) {
00425 if (Overlap_Local_Array(_use.Bottom_nth(i)->Array()))
00426 return TRUE;
00427 }
00428 return FALSE;
00429 }
00430 BOOL Is_OK_Parallel()
00431 {
00432 return (_info && !_info->Has_Exits && !_info->Has_Bad_Mem
00433 && (_is_good && _dep_dist==0 || _info->Is_Doacross) &&
00434 Upper_Bound_Standardize(WN_end(_loop),TRUE)
00435 && !_info->Pragma_Cannot_Concurrentize
00436 && !_info->Serial_Version_of_Concurrent_Loop
00437 && !_info->Inside_Critical_Section
00438 && !_info->Has_Threadprivate
00439 && !Inside_Lego_Tiled_Loop(_loop)
00440 && !Need_Copyin() && _peel_value >= 0);
00441 }
00442 BOOL Is_Parallel()
00443 {
00444 return (_info && !_info->Has_Exits && !_info->Has_Bad_Mem
00445 && (_is_good && _dep_dist==0 || _info->Is_Doacross)
00446 && Upper_Bound_Standardize(WN_end(_loop),TRUE)
00447 && !Outermore_Parallel_Construct_Or_Lego_Loop(_loop)
00448 && !(Innermore_Parallel_Or_Lego_Loop(_loop)
00449 && !_info->Auto_Parallelized)
00450 && !_info->Pragma_Cannot_Concurrentize
00451 && !_info->Serial_Version_of_Concurrent_Loop
00452 && !_info->Inside_Critical_Section
00453 && !_info->Has_Threadprivate
00454 && !_inner_loop_is_suggested_parallel
00455 && !Inside_Lego_Tiled_Loop(_loop)
00456 && !Need_Copyin() && _peel_value >= 0);
00457 }
00458 void Set_To_Sequential()
00459 {
00460 _is_good = FALSE;
00461 _dep_dist = 0;
00462 }
00463 void Test_Alias();
00464 void Print_Loop_Property();
00465 S_HTABLE * Live_Use() { return _live_use; }
00466 void Create_Live_Use();
00467 void Delete_Live_Use()
00468 {
00469 if (_live_use!=NULL) CXX_DELETE(_live_use,&ARA_memory_pool);
00470 _live_use = NULL;
00471 }
00472 void Determine_Last_Value();
00473 void Determine_Peel();
00474 INT Peel_Value();
00475 void Generate_Parallel_Pragma();
00476 void Generate_Copyout_Loop();
00477 void Merge_then_else(ARA_LOOP_INFO *ara_then, ARA_LOOP_INFO *ara_else);
00478 void Merge_Info(ARA_LOOP_INFO *ali, BOOL seen_non_scf);
00479 void Walk_Block(WN *block_stmt);
00480 void Walk_Rhs(WN *wn, WN *skip_store_id = NULL);
00481 ARA_REF * Has_Matching(ARA_REF_ST &ara_s, ARA_REF *a);
00482 SCALAR_NODE * Has_Matching(SCALAR_STACK &st, SCALAR_NODE *sn);
00483 IF_INFO * Walk_If(WN *if_stmt);
00484
00485 BOOL Def_Is_Whole_Array(const SYMBOL &sym, INT32 offset = 0)
00486 {
00487 for (INT i = 0; i < _def.Elements(); ++ i)
00488 if (_def.Bottom_nth(i)->Array() == sym &&
00489 _def.Bottom_nth(i)->Offset() == offset) {
00490 return _def.Bottom_nth(i)->Is_Whole_Array();
00491 }
00492 return FALSE;
00493 }
00494 BOOL Overlap_Local_Array(const SYMBOL &sym, INT32 offset = 0)
00495 {
00496 for (INT i = 0; i < _pri.Elements(); ++ i)
00497 if (_pri.Bottom_nth(i)->Is_Loop_Invariant() &&
00498 _pri.Bottom_nth(i)->Array() == sym &&
00499 _pri.Bottom_nth(i)->Offset() == offset)
00500 return TRUE;
00501 return FALSE;
00502 }
00503
00504 BOOL Overlap_Local_Scalar(const SYMBOL &sym)
00505 {
00506 for (INT i = 0; i < _scalar_pri.Elements(); ++ i )
00507 if (_scalar_pri.Bottom_nth(i)->_scalar == sym)
00508 return TRUE;
00509 return FALSE;
00510 }
00511
00512 BOOL Overlap_Exposed_Array(const SYMBOL &sym, INT32 offset = 0)
00513 {
00514 for (INT i = 0; i < _use.Elements(); ++ i)
00515 if (_use.Bottom_nth(i)->Array() == sym &&
00516 _use.Bottom_nth(i)->Offset() == offset)
00517 return TRUE;
00518 return FALSE;
00519 }
00520
00521 BOOL Overlap_Exposed_Scalar(const SYMBOL &sym)
00522 {
00523 for (INT i = 0; i < _scalar_use.Elements(); ++ i )
00524 if (_scalar_use.Bottom_nth(i)->_scalar == sym)
00525 return TRUE;
00526 return FALSE;
00527 }
00528
00529 BOOL Overlap_Kill_Scalar(const SYMBOL &sym)
00530 {
00531 for (INT i = 0; i < _scalar_def.Elements(); ++ i )
00532 if (_scalar_def.Bottom_nth(i)->_scalar == sym)
00533 return TRUE;
00534 return FALSE;
00535 }
00536
00537 BOOL Overlap_Reduction_Scalar(const SYMBOL &sym)
00538 {
00539 for (INT i = 0; i < _reduction.Elements(); ++ i ) {
00540 WN * red = _reduction.Bottom_nth(i);
00541 if (WN_operator(red) == OPR_STID || WN_operator(red) == OPR_LDID) {
00542 SYMBOL symbol(red);
00543 if (symbol == sym) return TRUE;
00544 }
00545 }
00546 return FALSE;
00547 }
00548
00549 STACK<SYMBOL>& Scalar_Vars() { return _scalar_vars; }
00550 STACK<SYMBOL>& Scalar_Alias() { return _scalar_alias; }
00551 STACK<SYMBOL>& Scalar_No_Final() { return _scalar_no_final; }
00552 STACK<SYMBOL>& Dep_Vars() { return _dep_vars; }
00553 STACK<SYMBOL>& Dep_Source() { return _dep_source; }
00554 STACK<SYMBOL>& Dep_Sink() { return _dep_sink; }
00555 STACK<INT>& Ln_Dep_Source() { return _ln_dep_source; }
00556 STACK<INT>& Ln_Dep_Sink() { return _ln_dep_sink; }
00557 STACK<SYMBOL>& Scalar_Bad_Peel() { return _scalar_bad_peel; }
00558 STACK<INT>& Ln_Scalar_Bad_Peel() { return _ln_scalar_bad_peel; }
00559 STACK<SYMBOL>& Dep_Bad_Peel() { return _dep_bad_peel; }
00560 STACK<INT>& Ln_Dep_Bad_Peel() { return _ln_dep_bad_peel; }
00561 STACK<SYMBOL>& Partial_Array_Sec() { return _partial_array_sec; }
00562 STACK<char*>& Call_No_Dep_Vars() { return _call_no_dep_vars; }
00563 STACK<INT>& Ln_Call_No_Dep_Vars() { return _ln_call_no_dep_vars; }
00564 STACK<SYMBOL>& Array_No_Dep_Vars() { return _array_no_dep_vars; }
00565 STACK<INT>& Ln_Array_No_Dep_Vars() { return _ln_misc_no_dep_vars; }
00566 STACK<INT>& Ln_Misc_No_Dep_Vars() { return _ln_array_no_dep_vars; }
00567 BOOL Is_Problem_Scalar(WN* wn);
00568 void Bad_Array_Dependence(WN* wn_source, WN* wn_sink);
00569 BOOL Not_Enough_Parallel_Work();
00570 };
00571
00572 extern void Walk_Loop_Dependence(WN * func_nd);
00573
00574 #endif