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 #define __STDC_LIMIT_MACROS
00099 #include <stdint.h>
00100 #ifdef USE_PCH
00101 #include "lno_pch.h"
00102 #endif // USE_PCH
00103 #pragma hdrstop
00104
00105 static const char *source_file = __FILE__;
00106 static const char *rcs_id = "$Source: /home/bos/bk/kpro64-pending/be/lno/SCCS/s.autod.cxx $ $Revision: 1.5 $";
00107
00108 #include <sys/types.h>
00109 #include <ctype.h>
00110 #include <limits.h>
00111 #include <alloca.h>
00112
00113 #include "pu_info.h"
00114 #include "autod.h"
00115 #include "lego_pragma.h"
00116 #include "fiz_fuse.h"
00117 #include "snl_utils.h"
00118
00119 static MEM_POOL Distr_Local_Pool;
00120 static BOOL distributed_something=FALSE;
00121 static BOOL distributed_something_pu;
00122 TY_IDX Create_New_Array_Type(TY_IDX old_array_ty);
00123 extern "C" {
00124 void Lego_File_Init (void);
00125 }
00126
00127 void Automatic_Data_Distribute(WN *wn)
00128 {
00129 distributed_something_pu=FALSE;
00130 MEM_POOL_Initialize(&Distr_Local_Pool,"Distr_Local_Pool",FALSE);
00131 DISTRIBUTION(wn,&Distr_Local_Pool);
00132 MEM_POOL_Delete(&Distr_Local_Pool);
00133 }
00134
00135 void Transpose_For_MP(WN *wn)
00136 {
00137 MEM_POOL_Push(&LNO_local_pool);
00138 TRANSPOSE_DIRECTED_GRAPH16 graph(100,100);
00139 ARRAY_TRANSPOSE_TREE *arrays =
00140 CXX_NEW(ARRAY_TRANSPOSE_TREE(&LNO_local_pool),&LNO_local_pool);
00141 graph.Build(wn,arrays);
00142 graph.Solve(arrays);
00143 if (graph.Did_Transpose()) {
00144 graph.Transpose(wn,arrays);
00145 LNO_Build_Access(wn, &LNO_default_pool);
00146 }
00147 MEM_POOL_Pop(&LNO_local_pool);
00148 }
00149
00150
00151 DISTRIBUTION::DISTRIBUTION(WN *wn, MEM_POOL *pool)
00152 {
00153 _pool = pool;
00154 MEM_POOL_Push(_pool);
00155 _locals = CXX_NEW(ARRAY_DESCR_TREE(_pool),_pool);
00156 _locals_stack = CXX_NEW(ARRAY_DESCR_STACK(_pool),_pool);
00157 _globals = CXX_NEW(ARRAY_DESCR_TREE(_pool),_pool);
00158 _globals_stack = CXX_NEW(ARRAY_DESCR_STACK(_pool),_pool);
00159 _do_stack = CXX_NEW(DOLOOP_STACK(_pool),_pool);
00160 _preamble = WN_first(WN_func_body(wn));
00161 while (WN_opcode(_preamble) != OPC_PRAGMA ||
00162 WN_pragma(_preamble) != WN_PRAGMA_PREAMBLE_END) {
00163 _preamble = WN_next(_preamble);
00164 }
00165
00166 Gather_Arrays(wn,FALSE);
00167 Distribute_Arrays();
00168 MEM_POOL_Pop(_pool);
00169 }
00170
00171
00172 void DISTRIBUTION::Distribute_Arrays()
00173 {
00174
00175 INT i;
00176
00177 for (i=0; i<_locals_stack->Elements(); i++) {
00178 ARRAY_DESCRIPTOR ad = ARRAY_DESCRIPTOR(_locals_stack->Bottom_nth(i),0,0);
00179 BINARY_TREE_NODE<ARRAY_DESCRIPTOR> *find = _locals->Find(ad);
00180 if (find) {
00181 ARRAY_DESCRIPTOR *descr = find->Get_Data();
00182 descr->Distribute_Array(WN_next(_preamble));
00183 }
00184 }
00185
00186 for (i=0; i<_globals_stack->Elements(); i++) {
00187 ARRAY_DESCRIPTOR ad = ARRAY_DESCRIPTOR(_globals_stack->Bottom_nth(i),0,0);
00188 BINARY_TREE_NODE<ARRAY_DESCRIPTOR> *find = _globals->Find(ad);
00189 if (find) {
00190 ARRAY_DESCRIPTOR *descr = find->Get_Data();
00191 descr->Distribute_Array(WN_next(_preamble));
00192 }
00193 }
00194 }
00195
00196
00197 void ARRAY_DESCRIPTOR::Distribute_Array(WN *insert_point)
00198 {
00199 if (Is_Bad()) {
00200 return;
00201 }
00202
00203 TY_IDX array_ty = Get_Array_Type(_st);
00204 mINT16 ndims = TY_AR_ndims (array_ty);
00205
00206
00207 INT i;
00208 for (i=0; i<ndims; i++) {
00209 if (!TY_AR_const_lbnd(array_ty,i) ||
00210 !TY_AR_const_ubnd(array_ty,i)) {
00211 return;
00212 }
00213 }
00214
00215 if (!LNO_Run_Lego) {
00216 if (!distributed_something) {
00217 Lego_File_Init();
00218 }
00219 if (!distributed_something_pu) {
00220 Lego_PU_Init();
00221 }
00222 }
00223 LNO_Run_Lego = TRUE;
00224 distributed_something=TRUE;
00225 distributed_something_pu=TRUE;
00226 #ifdef _NEW_SYMTAB
00227 Set_PU_mp_needs_lno(Get_Current_PU());
00228 Set_FILE_INFO_needs_lno(File_info);
00229 #else
00230 Set_SYMTAB_mp_needs_lno(Current_Symtab);
00231 Set_SYMTAB_mp_needs_lno(Global_Symtab);
00232 #endif
00233
00234
00235
00236 if (ndims != _parallel_dims->Size()) return;
00237 WN *first_pragma;
00238 for (i=0; i<ndims; i++) {
00239 BOOL is_block = _parallel_dims->Test(i);
00240 WN *pragma = WN_CreatePragma(WN_PRAGMA_DISTRIBUTE,_st,0,0);
00241 WN_set_pragma_compiler_generated(pragma);
00242 if (i == 0) first_pragma = pragma;
00243 WN_pragma_index(pragma) = i;
00244 if (is_block) {
00245 WN_pragma_distr_type(pragma) = DISTRIBUTE_BLOCK;
00246 } else {
00247 WN_pragma_distr_type(pragma) = DISTRIBUTE_STAR;
00248 }
00249 LWN_Insert_Block_Before(LWN_Get_Parent(insert_point),insert_point,pragma);
00250
00251 INT64 size = (TY_AR_ubnd_val(array_ty, ndims-1-i)-
00252 TY_AR_lbnd_val(array_ty, ndims-1-i)+1);
00253 WN *xpwn = WN_Create(OPC_XPRAGMA, 1);
00254 WN_pragma(xpwn) = WN_PRAGMA_DISTRIBUTE;
00255 WN_set_pragma_compiler_generated(xpwn);
00256 WN_st_idx(xpwn) = ST_st_idx(_st);
00257 if (size > INT32_MAX) {
00258 WN_kid0(xpwn) = LWN_Make_Icon(MTYPE_I8,size);
00259 } else {
00260 WN_kid0(xpwn) = LWN_Make_Icon(MTYPE_I4,size);
00261 }
00262 LWN_Parentize(xpwn);
00263 LWN_Insert_Block_Before(LWN_Get_Parent(insert_point),insert_point,xpwn);
00264
00265 }
00266 Read_Pragma_Distribute(first_pragma);
00267 }
00268
00269
00270
00271
00272
00273
00274
00275
00276 void DISTRIBUTION::Gather_Arrays(WN *wn, BOOL seen_mp)
00277 {
00278 OPCODE opc = WN_opcode(wn);
00279 OPERATOR oper = OPCODE_operator(opc);
00280 if (opc == OPC_BLOCK) {
00281 WN *kid = WN_first(wn);
00282 while (kid) {
00283 Gather_Arrays(kid,seen_mp);
00284 kid = WN_next(kid);
00285 }
00286 return;
00287 }
00288 if (opc == OPC_DO_LOOP) {
00289 if (Do_Loop_Is_Mp(wn)) {
00290 seen_mp = TRUE;
00291 }
00292 _do_stack->Push(wn);
00293 } else if ((oper == OPR_ILOAD) || (oper == OPR_ISTORE)) {
00294 if (seen_mp) Process_Memory(wn);
00295 }
00296 for (INT kidno=0; kidno<WN_kid_count(wn); kidno++) {
00297 Gather_Arrays(WN_kid(wn,kidno),seen_mp);
00298 }
00299 if (opc == OPC_DO_LOOP) {
00300 _do_stack->Pop();
00301 }
00302 }
00303
00304
00305 void DISTRIBUTION::Process_Memory(WN *wn)
00306 {
00307
00308 WN *array ;
00309 if (OPCODE_is_store(WN_opcode(wn))) {
00310 array = WN_kid1(wn);
00311 } else {
00312 array = WN_kid0(wn);
00313 }
00314 if (WN_operator(array) != OPR_ARRAY) return;
00315 if (WN_offset(wn)) return;
00316 WN *array_base = WN_array_base(array);
00317 if (WN_operator(array_base) != OPR_LDA) {
00318 return;
00319 }
00320 ST *st = WN_st(array_base);
00321 ARRAY_DESCR_TREE *tree;
00322 ARRAY_DESCR_STACK *stack;
00323
00324 #ifdef _NEW_SYMTAB
00325 if ((ST_class(st) == CLASS_VAR) && !ST_is_not_used(st) &&
00326 ST_addr_not_saved(st) &&
00327 (TY_size(ST_type(st)) > 150000) &&
00328 #else
00329 if ((ST_symclass(st) == CLASS_VAR) && !ST_is_not_used(st) &&
00330 !ST_addr_taken_saved(st) &&
00331 (ST_size(st) > 150000) &&
00332 #endif
00333 (!ST_is_reshaped(st)) &&
00334 (TY_kind(ST_type(st)) == KIND_ARRAY) &&
00335 (!da_hash || !da_hash->Find(st))) {
00336 if (ST_sclass(st) == SCLASS_AUTO &&
00337 ST_base_idx(st) == ST_st_idx(st)) {
00338 if (!ST_has_nested_ref(st)) {
00339
00340 tree = _locals;
00341 stack = _locals_stack;
00342 } else {
00343 return;
00344 }
00345 } else if (ST_sclass(st) == SCLASS_COMMON ||
00346 #ifdef _NEW_SYMTAB
00347 ((ST_base_idx(st) != ST_st_idx(st)) &&
00348 #else
00349 ((ST_sclass(st) == SCLASS_BASED) &&
00350 #endif
00351 (ST_sclass(ST_base(st)) == SCLASS_COMMON))) {
00352
00353 tree = _globals;
00354 stack = _globals_stack;
00355 } else {
00356 return;
00357 }
00358 } else {
00359 return;
00360 }
00361
00362
00363 MEM_POOL_Push(&LNO_local_pool);
00364 INT num_dim = WN_num_dim(array);
00365 BIT_VECTOR *reference = CXX_NEW(BIT_VECTOR(num_dim,
00366 &LNO_local_pool),&LNO_local_pool);
00367 BOOL is_bad = FALSE;
00368 ACCESS_ARRAY *access_array =
00369 (ACCESS_ARRAY *) WN_MAP_Get(LNO_Info_Map,array);
00370 if (access_array->Num_Vec() != num_dim) is_bad = TRUE;
00371 if (access_array->Too_Messy) is_bad = TRUE;
00372
00373 for (INT i=0; i<num_dim && !is_bad; i++) {
00374 ACCESS_VECTOR *av = access_array->Dim(i);
00375 if (av->Too_Messy) {
00376 is_bad = TRUE;
00377 } else {
00378 INT num_loop_var = 0;
00379 INT mp_var = -1;
00380 for (INT j=0; j<av->Nest_Depth() &&!is_bad; j++) {
00381 if (av->Loop_Coeff(j) == 1) {
00382 if (Do_Loop_Is_Mp(_do_stack->Bottom_nth(j))) {
00383 num_loop_var++;
00384 mp_var = j;
00385 }
00386 } else if (av->Loop_Coeff(j)) {
00387 if (Do_Loop_Is_Mp(_do_stack->Bottom_nth(j))) {
00388 is_bad = TRUE;
00389 }
00390 }
00391 }
00392 if (mp_var != -1) {
00393 if (num_loop_var != 1 || av->Non_Const_Loops() > mp_var) {
00394 is_bad = TRUE;
00395 } else {
00396
00397
00398
00399
00400 ACCESS_ARRAY *lb = Get_Do_Loop_Info(_do_stack->Bottom_nth(mp_var))->LB;
00401 if (lb->Too_Messy || lb->Num_Vec() != 1) {
00402 is_bad = TRUE;
00403 } else {
00404 ACCESS_VECTOR *low = CXX_NEW(ACCESS_VECTOR(lb->Dim(0),&LNO_local_pool),&LNO_local_pool);
00405 if (abs(low->Const_Offset - av->Const_Offset) < epsilon) {
00406 low->Negate_Me();
00407 low->Const_Offset = av->Const_Offset;
00408 if (*low == *av) {
00409 reference->Set(i);
00410 } else {
00411 is_bad = TRUE;
00412 }
00413 } else {
00414 is_bad = TRUE;
00415 }
00416 }
00417 }
00418 }
00419 }
00420 }
00421 if (is_bad || reference->Pop_Count()) {
00422 ARRAY_DESCRIPTOR ad = ARRAY_DESCRIPTOR(st,reference,is_bad);
00423 BINARY_TREE_NODE<ARRAY_DESCRIPTOR> *find = tree->Find(ad);
00424 if (find) {
00425 find->Get_Data()->Union(&ad);
00426 } else {
00427 BIT_VECTOR *bv = CXX_NEW(BIT_VECTOR(reference->Size(),_pool),_pool);
00428 *bv = *reference;
00429 tree->Enter(ARRAY_DESCRIPTOR(st,bv,is_bad));
00430 stack->Push(st);
00431 }
00432 }
00433 MEM_POOL_Pop(&LNO_local_pool);
00434
00435 }
00436
00437
00438
00439
00440
00441
00442
00443
00444 void TRANSPOSE_DIRECTED_GRAPH16::Build(WN *func_nd,ARRAY_TRANSPOSE_TREE *arrays)
00445 {
00446 Gather_Arrays(func_nd,arrays);
00447 FIZ_FUSE_INFO* ffi=
00448 CXX_NEW(FIZ_FUSE_INFO(&LNO_local_pool), &LNO_local_pool);
00449 ffi->Build(func_nd);
00450 for (INT i = 0; i < ffi->Num_Snl() && !_is_bad; i++) {
00451 INT nloops = ffi->Get_Depth(i);
00452 if (nloops >=1 && nloops <= TRANSPOSE_MAX_SIZE) {
00453 if (ffi->Get_Type(i) == Inner || ffi->Get_Type(i) == Not_Inner) {
00454 WN *outer = ffi->Get_Wn(i);
00455 if (!Outermore_Parallelizable(LWN_Get_Parent(outer))) {
00456 WN *inner = SNL_Get_Inner_Snl_Loop(outer,nloops);
00457 if (Contains_Parallelizable(inner,nloops)) {
00458 Build_Snl(inner,nloops,arrays);
00459 }
00460 }
00461 }
00462 }
00463 }
00464 }
00465
00466
00467 void TRANSPOSE_DIRECTED_GRAPH16::Gather_Arrays(WN *wn,
00468 ARRAY_TRANSPOSE_TREE *arrays)
00469 {
00470 OPCODE opc = WN_opcode(wn);
00471 if (opc == OPC_BLOCK) {
00472 WN *kid=WN_first(wn);
00473 while (kid) {
00474 Gather_Arrays(kid,arrays);
00475 kid = WN_next(kid);
00476 }
00477 } else if (OPCODE_operator(opc) == OPR_LDA) {
00478 if (Local_Array(WN_st(wn))) {
00479 BOOL transposable = FALSE;
00480 WN *parent = LWN_Get_Parent(wn);
00481 TY_IDX array_ty = Get_Array_Type(WN_st(wn));
00482 if ((WN_operator(parent) == OPR_ARRAY) &&
00483 (wn == WN_array_base(parent)) &&
00484 (WN_element_size(parent) >= 1) &&
00485 (!WN_offset(wn)) &&
00486 TY_AR_ndims(array_ty) == WN_num_dim(parent)) {
00487
00488
00489
00490
00491
00492
00493 BOOL good_bounds = TRUE;
00494
00495 for (INT i=0; i<TY_AR_ndims(array_ty); i++) {
00496
00497
00498
00499
00500 if (TY_AR_const_ubnd(array_ty,i) &&
00501 TY_AR_const_lbnd(array_ty,i) &&
00502 WN_operator(WN_array_dim(parent,i)) == OPR_INTCONST &&
00503 (WN_const_val(WN_array_dim(parent,i)) ==
00504 (TY_AR_ubnd_val(array_ty,i)-TY_AR_lbnd_val(array_ty,i)+1))) {
00505 continue;
00506 }
00507
00508 good_bounds = FALSE;
00509 break;
00510 }
00511
00512 if (good_bounds) {
00513
00514 WN *grandparent = LWN_Get_Parent(parent);
00515 OPCODE gopc = WN_opcode(grandparent);
00516 if (OPCODE_is_load(gopc) ||
00517 ((OPCODE_operator(gopc) == OPR_ISTORE) &&
00518 (parent == WN_kid1(grandparent)))) {
00519 if (WN_offset(grandparent) == 0) {
00520 transposable = TRUE;
00521 }
00522 } else if (IO_element_read(grandparent)) {
00523 transposable = TRUE;
00524 }
00525 }
00526 }
00527 ARRAY_TRANSPOSE_DESCRIPTOR tmp = ARRAY_TRANSPOSE_DESCRIPTOR(WN_st(wn));
00528 BINARY_TREE_NODE<ARRAY_TRANSPOSE_DESCRIPTOR> *find = arrays->Find(tmp);
00529 if (find) {
00530 ARRAY_TRANSPOSE_DESCRIPTOR *atd = find->Get_Data();
00531 if (!transposable) atd->Reset_Transposable();
00532 } else {
00533 arrays->Enter(ARRAY_TRANSPOSE_DESCRIPTOR(WN_st(wn),transposable));
00534 }
00535 }
00536 } else {
00537 for (INT kidno=0; kidno<WN_kid_count(wn); kidno++) {
00538 Gather_Arrays(WN_kid(wn,kidno),arrays);
00539 }
00540 }
00541 }
00542
00543
00544 BOOL TRANSPOSE_DIRECTED_GRAPH16::IO_element_read(WN *item)
00545 {
00546 if (WN_operator(item) == OPR_IO_ITEM) {
00547 if (WN_io_item(item) == IOL_VAR) {
00548 WN *parent = LWN_Get_Parent(item);
00549 if (WN_opcode(parent) == OPC_IO) {
00550 if (WN_io_statement(parent) == IOS_READ) {
00551 return TRUE;
00552 } else if (WN_io_statement(parent) == IOS_CR_FRF) {
00553 return TRUE;
00554 } else if (WN_io_statement(parent) == IOS_CR_FRU) {
00555 return TRUE;
00556 }
00557 }
00558 }
00559 }
00560 return FALSE;
00561 }
00562
00563
00564
00565 void TRANSPOSE_DIRECTED_GRAPH16::Build_Snl(WN *inner, INT nloops,
00566 ARRAY_TRANSPOSE_TREE *arrays)
00567 {
00568 VINDEX16 snl_v = Add_Vertex(nloops,inner);
00569 if (!snl_v) {
00570 _is_bad = TRUE;
00571 return;
00572 }
00573 WN *wn = inner;
00574 WN *outer;
00575 for (INT i=0; i<nloops; i++) {
00576 outer=wn;
00577 if (Get_Do_Loop_Info(wn)->Parallelizable) {
00578 Set_Can_Be_Parallel(snl_v,nloops-1-i);
00579 } else {
00580 Reset_Can_Be_Parallel(snl_v,nloops-1-i);
00581 }
00582 wn = LWN_Get_Parent(LWN_Get_Parent(wn));
00583 }
00584 Build_Snl_Arrays(outer,arrays,Do_Loop_Depth(outer),Do_Loop_Depth(inner),snl_v);
00585 if (_is_bad) return;
00586
00587 }
00588
00589
00590 void TRANSPOSE_DIRECTED_GRAPH16::Build_Snl_Arrays(WN *wn,
00591 ARRAY_TRANSPOSE_TREE *arrays, INT outer_depth,INT inner_depth,VINDEX16 snl_v)
00592 {
00593 OPCODE opc = WN_opcode(wn);
00594 if (opc == OPC_BLOCK) {
00595 WN *kid=WN_first(wn);
00596 while (kid) {
00597 Build_Snl_Arrays(kid,arrays,outer_depth,inner_depth,snl_v);
00598 if (_is_bad) return;
00599 kid = WN_next(kid);
00600 }
00601 } else {
00602 for (INT kidno=0; kidno<WN_kid_count(wn); kidno++) {
00603 Build_Snl_Arrays(WN_kid(wn,kidno),arrays,outer_depth,inner_depth,snl_v);
00604 if (_is_bad) return;
00605 }
00606 if (OPCODE_operator(opc) == OPR_ARRAY) {
00607 if (WN_num_dim(wn) > 1) {
00608 Build_Snl_Array(wn,arrays,outer_depth,inner_depth,snl_v);
00609 }
00610 }
00611 }
00612 }
00613
00614
00615 void TRANSPOSE_DIRECTED_GRAPH16::Build_Snl_Array(WN *array,
00616 ARRAY_TRANSPOSE_TREE *arrays, INT outer_depth,INT inner_depth,VINDEX16 snl_v)
00617 {
00618 WN *base = WN_array_base(array);
00619 ACCESS_ARRAY *access_array =
00620 (ACCESS_ARRAY *) WN_MAP_Get(LNO_Info_Map,array);
00621 if (!WN_has_sym(base) ||
00622 access_array->Too_Messy ||
00623 access_array->Num_Vec() != WN_num_dim(array)) {
00624 return;
00625 }
00626
00627 ARRAY_TRANSPOSE_DESCRIPTOR atd = ARRAY_TRANSPOSE_DESCRIPTOR(WN_st(base), 0);
00628 BINARY_TREE_NODE<ARRAY_TRANSPOSE_DESCRIPTOR> *find = arrays->Find(atd);
00629 if (find && find->Get_Data()->Transposable()) {
00630 VINDEX16 array_v = find->Get_Data()->Get_Vertex();
00631 if (!array_v) {
00632 array_v = Add_Vertex(WN_num_dim(array),WN_st(base));
00633 if (!array_v) {
00634 _is_bad = TRUE;
00635 return;
00636 }
00637 find->Get_Data()->Set_Vertex(array_v);
00638 }
00639 EINDEX16 e1 = Get_Edge(snl_v,array_v);
00640 EINDEX16 e2 = Get_Edge(array_v,snl_v);
00641 for (INT i=0; i<access_array->Num_Vec(); i++) {
00642 ACCESS_VECTOR *av = access_array->Dim(i);
00643 if (!av->Too_Messy) {
00644 for (INT j=outer_depth; j<MIN(inner_depth+1,av->Nest_Depth()); j++) {
00645 if (av->Loop_Coeff(j)) {
00646 if (!e1) e1 = Add_Edge(snl_v,array_v,inner_depth-outer_depth+1);
00647 if (!e2) e2 = Add_Edge(array_v,snl_v,access_array->Num_Vec());
00648 if (!e1 || !e2) {
00649 _is_bad = TRUE;
00650 return;
00651 }
00652
00653 Set_Constraint(e1,j-outer_depth,i);
00654
00655 Set_Constraint(e2,i,j-outer_depth);
00656 }
00657 }
00658 }
00659 }
00660 } else {
00661
00662 ACCESS_ARRAY *access_array =
00663 (ACCESS_ARRAY *) WN_MAP_Get(LNO_Info_Map,array);
00664 if (!access_array->Too_Messy) {
00665 ACCESS_VECTOR *av = access_array->Dim(access_array->Num_Vec()-1);
00666 if (!av->Too_Messy) {
00667 for (INT i=outer_depth; i<MIN(inner_depth+1,av->Nest_Depth()); i++) {
00668 if (av->Loop_Coeff(i)) {
00669 Reset_Can_Be_Parallel(snl_v,i-outer_depth);
00670 }
00671 }
00672 }
00673 }
00674 }
00675 }
00676
00677
00678 void TRANSPOSE_DIRECTED_GRAPH16::Solve(ARRAY_TRANSPOSE_TREE *arrays)
00679 {
00680
00681 VINDEX16 v=Get_Loop_Vertex();
00682 while (v) {
00683 BOOL consistent = FALSE;
00684 for (INT i=0; i<_v[v].size && !consistent; i++) {
00685 if (Can_Be_Parallel(v,i)) {
00686 Clear_Values();
00687 _v[v].value = i;
00688 if (Propogate_V(v)) {
00689 consistent=TRUE;
00690 Record(arrays);
00691 }
00692 }
00693 }
00694 if (!consistent) {
00695 _is_bad = TRUE;
00696 return;
00697 }
00698 v=Get_Loop_Vertex();
00699 }
00700 }
00701
00702
00703
00704 void TRANSPOSE_DIRECTED_GRAPH16::Record(ARRAY_TRANSPOSE_TREE *arrays)
00705 {
00706 for (INT i=1; i<_v.Lastidx()+1; i++) {
00707 if (!_v[i].Is_Free()) {
00708 if (_v[i].value != -1) {
00709 if (_v[i].value > 0 && !_v[i].is_loop) {
00710 ARRAY_TRANSPOSE_DESCRIPTOR atd =
00711 ARRAY_TRANSPOSE_DESCRIPTOR(_v[i].tvertex_union.st, 0);
00712 BINARY_TREE_NODE<ARRAY_TRANSPOSE_DESCRIPTOR> *find = arrays->Find(atd);
00713 find->Get_Data()->Set_Dimension(_v[i].value);
00714 Transpose_Array(_v[i].tvertex_union.st,_v[i].value);
00715 if (LNO_Verbose) {
00716 fprintf(stderr,"Transposing array %s \n",
00717 ST_name(_v[i].tvertex_union.st));
00718 }
00719 _did_transpose = TRUE;
00720 }
00721 Delete_Vertex(i);
00722 }
00723 }
00724 }
00725 }
00726
00727
00728 void TRANSPOSE_DIRECTED_GRAPH16::Transpose(WN *wn, ARRAY_TRANSPOSE_TREE *arrays)
00729 {
00730 OPCODE opc = WN_opcode(wn);
00731 if (opc == OPC_BLOCK) {
00732 WN *kid = WN_first(wn);
00733 while (kid) {
00734 Transpose(kid,arrays);
00735 kid = WN_next(kid);
00736 }
00737 } else if (OPCODE_operator(opc) == OPR_LDA) {
00738 WN *parent = LWN_Get_Parent(wn);
00739 if ((WN_operator(parent) == OPR_ARRAY) &&
00740 (wn == WN_array_base(parent))) {
00741 ARRAY_TRANSPOSE_DESCRIPTOR atd = ARRAY_TRANSPOSE_DESCRIPTOR(WN_st(wn),
00742 0);
00743 BINARY_TREE_NODE<ARRAY_TRANSPOSE_DESCRIPTOR> *find = arrays->Find(atd);
00744 if (find && (find->Get_Data()->Get_Dimension() != -1)) {
00745 Transpose_Array(parent,find->Get_Data()->Get_Dimension());
00746 }
00747 }
00748 } else {
00749 for (INT kidno=0; kidno<WN_kid_count(wn); kidno++) {
00750 Transpose(WN_kid(wn,kidno),arrays);
00751 }
00752 }
00753 }
00754
00755
00756 void TRANSPOSE_DIRECTED_GRAPH16::Transpose_Array(WN *array,INT dim)
00757 {
00758 WN *zero_dim = WN_array_dim(array,dim);
00759 WN *zero_index = WN_array_index(array,dim);
00760 for (INT i=dim; i>0; i--) {
00761 WN_array_dim(array,i) = WN_array_dim(array,i-1);
00762 WN_array_index(array,i) = WN_array_index(array,i-1);
00763 }
00764 WN_array_dim(array,0) = zero_dim;
00765 WN_array_index(array,0) = zero_index;
00766 }
00767
00768
00769 void TRANSPOSE_DIRECTED_GRAPH16::Transpose_Array(ST *st,INT dim)
00770 {
00771 INT ndims = TY_AR_ndims(ST_type(st));
00772 INT element_size = TY_size(TY_AR_etype(ST_type(st)));
00773
00774 TY_IDX old_ty = ST_type(st);
00775 TY_IDX new_ty = Create_New_Array_Type(old_ty);
00776 Set_ST_type(st,new_ty);
00777 Set_TY_AR_lbnd_val(new_ty,0, TY_AR_lbnd_val(old_ty,dim));
00778 Set_TY_AR_ubnd_val(new_ty,0, TY_AR_ubnd_val(old_ty,dim));
00779 INT i;
00780 for (i=1; i<=dim; i++) {
00781 Set_TY_AR_lbnd_val(new_ty,i, TY_AR_lbnd_val(old_ty,i-1));
00782 Set_TY_AR_ubnd_val(new_ty,i, TY_AR_ubnd_val(old_ty,i-1));
00783 }
00784
00785 for (i=0; i<ndims; i++) {
00786 INT stride = element_size;
00787 for (INT j=i+1; j<ndims; j++) {
00788 stride = (stride * (TY_AR_ubnd_val(new_ty, j) -
00789 TY_AR_lbnd_val(new_ty, j) + 1));
00790 }
00791 Set_TY_AR_stride_val(new_ty,i,stride);
00792 }
00793 }
00794
00795
00796
00797
00798
00799 BOOL TRANSPOSE_DIRECTED_GRAPH16::Propogate_V(VINDEX16 v)
00800 {
00801 EINDEX16 e = _v[v].Get_Out_Edge();
00802 INT v_value = _v[v].value;
00803 while (e) {
00804 INT constraint = Get_Constraint(e,v_value);
00805 if (constraint != -1) {
00806 VINDEX16 v2 = _e[e].Get_Sink();
00807 if (_v[v2].is_loop && !Can_Be_Parallel(v2,constraint)) return 0;
00808 if (_v[v2].value != -1) {
00809 if (_v[v2].value != constraint) return 0;
00810 } else {
00811 _v[v2].value = constraint;
00812 if (!Propogate_V(v2)) {
00813 return 0;
00814 }
00815 }
00816 }
00817 e = _e[e].Get_Next_Out_Edge();
00818 }
00819 return 1;
00820 }
00821
00822 VINDEX16 TRANSPOSE_DIRECTED_GRAPH16::Get_Loop_Vertex()
00823 {
00824 for (INT i=1; i<_v.Lastidx()+1; i++) {
00825 if (!_v[i].Is_Free() && _v[i].is_loop) {
00826 return i;
00827 }
00828 }
00829 return 0;
00830 }
00831
00832 void TRANSPOSE_DIRECTED_GRAPH16::Clear_Values()
00833 {
00834 for (INT i=1; i<_v.Lastidx()+1; i++) {
00835 if (!_v[i].Is_Free()) {
00836 _v[i].value = -1;
00837 }
00838 }
00839 }
00840
00841 BOOL TRANSPOSE_DIRECTED_GRAPH16::Local_Array(ST *st)
00842 {
00843 #ifdef _NEW_SYMTAB
00844 if ((ST_class(st) == CLASS_VAR) &&
00845 (TY_size(ST_type(st)) > 0) &&
00846 (TY_kind(ST_type(st)) == KIND_ARRAY) &&
00847 (ST_sclass(st) == SCLASS_AUTO) &&
00848 (!ST_is_initialized(st)) &&
00849 (!ST_has_nested_ref(st)) &&
00850 (!ST_is_equivalenced(st)) &&
00851 (!da_hash || !da_hash->Find(st))) {
00852 #else
00853 if ((ST_symclass(st) == CLASS_VAR) &&
00854 (ST_size(st) > 0) &&
00855 (TY_kind(ST_type(st)) == KIND_ARRAY) &&
00856 (ST_sclass(st) == SCLASS_AUTO) &&
00857 (!ST_is_initialized(st)) &&
00858 (!ST_has_nested_ref(st)) &&
00859 (!ST_is_non_contiguous(st)) &&
00860 (!ST_is_equivalenced(st)) &&
00861 (!da_hash || !da_hash->Find(st))) {
00862 #endif
00863 return TRUE;
00864 } else {
00865 return FALSE;
00866 }
00867 }
00868
00869
00870 BOOL TRANSPOSE_DIRECTED_GRAPH16::Outermore_Parallelizable(WN *wn)
00871 {
00872 if (!wn) return FALSE;
00873 OPCODE opc = WN_opcode(wn);
00874 if (opc == OPC_DO_LOOP && Get_Do_Loop_Info(wn)->Parallelizable) {
00875 return TRUE;
00876 }
00877 return Outermore_Parallelizable(LWN_Get_Parent(wn));
00878 }
00879
00880
00881 BOOL TRANSPOSE_DIRECTED_GRAPH16::Contains_Parallelizable(WN *wn, INT nloops)
00882 {
00883 for (INT i=0; i<nloops; i++) {
00884 if (Get_Do_Loop_Info(wn)->Parallelizable) return TRUE;
00885 wn = LWN_Get_Parent(LWN_Get_Parent(wn));
00886 }
00887 return FALSE;
00888 }
00889
00890 void TRANSPOSE_DIRECTED_GRAPH16::Print(FILE *fp)
00891 {
00892 for (INT i=1; i<_v.Lastidx()+1; i++) {
00893 if (!_v[i].Is_Free()) {
00894 if (_v[i].is_loop) {
00895 fprintf(fp,"Vertex %d for loop ",i);
00896 Dump_WN(_v[i].tvertex_union.inner_loop,fp,TRUE,0,0);
00897 fprintf(fp,"\n");
00898 fprintf(fp,"Can be parallel is ");
00899 for (INT j=0; j<_v[i].size; j++) {
00900 fprintf(fp," %d ",_v[i].can_be_parallel[j]);
00901 }
00902 fprintf(fp,"\n");
00903 } else {
00904 fprintf(fp,"Vertex %d for array %s",i,
00905 ST_name(_v[i].tvertex_union.st));
00906 fprintf(fp,"\n");
00907 }
00908 EINDEX16 e = _v[i].Get_Out_Edge();
00909 while (e) {
00910 fprintf(fp,"Edge %d to vertex %d ",e,_e[e].Get_Sink());
00911 fprintf(fp,"Constraint is ");
00912 for (INT j=0; j<_v[i].size; j++) {
00913 fprintf(fp," %d ",_e[e].constraint[j]);
00914 }
00915 fprintf(fp,"\n");
00916 e = _e[e].Get_Next_Out_Edge();
00917 }
00918 }
00919 }
00920 }
00921