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 #define __STDC_LIMIT_MACROS
00066 #include <stdint.h>
00067 #ifdef USE_PCH
00068 #include "be_com_pch.h"
00069 #endif
00070 #pragma hdrstop
00071 #ifdef _KEEP_RCS_ID
00072 static char *rcs_id = "$Source: be/com/SCCS/s.dep_graph.cxx $ $Revision: 1.7 $";
00073 #endif
00074
00075 #include <sys/types.h>
00076 #if defined(BUILD_OS_DARWIN)
00077 #include <darwin_elf.h>
00078 #else
00079 #include <elf.h>
00080 #endif
00081
00082 #define USE_STANDARD_TYPES
00083
00084 #include <bstring.h>
00085 #include "wn.h"
00086 #include "erglob.h"
00087 #include "errors.h"
00088 #include "strtab.h"
00089 #include "stab.h"
00090 #include "irbdata.h"
00091 #include "dwarf_DST_mem.h"
00092 #include "pu_info.h"
00093 #ifdef __MINGW32__
00094 #include <WINDOWS.h>
00095 #endif
00096 #include "ir_bwrite.h"
00097 #include "ir_bcom.h"
00098
00099 #include "dep_graph.h"
00100 #include "stab.h"
00101
00102 #ifdef LNO
00103 #include "call_info.h"
00104 #include "config.h"
00105 #include "config_cache.h"
00106 #include "errors.h"
00107 #include "erbe.h"
00108
00109 #include "lnopt_main.h"
00110 #include "soe.h"
00111 #include "lwn_util.h"
00112 #include "opt_alias_interface.h"
00113 #include "lego_util.h"
00114 #include "opt_du.h"
00115
00116
00117 static BOOL LNO_Erase_Dg_From_Here_In_X(WN* wn, ARRAY_DIRECTED_GRAPH16* dg)
00118 {
00119 BOOL erased_vertices = FALSE;
00120
00121 if (WN_opcode(wn) == OPC_BLOCK) {
00122 for (WN* w = WN_first(wn); w; w = WN_next(w))
00123 if (LNO_Erase_Dg_From_Here_In_X(w, dg))
00124 erased_vertices = TRUE;
00125 }
00126 else {
00127 for (INT k = 0; k < WN_kid_count(wn); k++)
00128 if (LNO_Erase_Dg_From_Here_In_X(WN_kid(wn,k), dg))
00129 erased_vertices = TRUE;
00130 }
00131
00132 OPCODE op = WN_opcode(wn);
00133 OPERATOR opr = OPCODE_operator(op);
00134
00135 VINDEX16 v = dg->Get_Vertex(wn);
00136 if (OPCODE_is_load(op) || OPCODE_is_store(op) ||
00137 OPCODE_is_call(op) || (OPCODE_operator(op) == OPR_INTRINSIC_OP)
00138 #ifdef KEY
00139 || (OPCODE_operator(op) == OPR_PURE_CALL_OP)
00140 #endif
00141 ) {
00142 if (v) {
00143 EINDEX16 enext = 0;
00144 EINDEX16 e;
00145 for (e = dg->Get_In_Edge(v); e; e = enext) {
00146 enext = dg->Get_Next_In_Edge(e);
00147 dg->Delete_Array_Edge(e);
00148 }
00149 for (e = dg->Get_Out_Edge(v); e; e = enext) {
00150 enext = dg->Get_Next_Out_Edge(e);
00151 dg->Delete_Array_Edge(e);
00152 }
00153 dg->Delete_Vertex(v);
00154
00155 erased_vertices = TRUE;
00156 }
00157 }
00158 if (opr == OPR_DO_LOOP) {
00159 DO_LOOP_INFO* dli = Get_Do_Loop_Info(wn);
00160 if (dli->Has_Bad_Mem == TRUE)
00161 erased_vertices = TRUE;
00162 dli->Has_Bad_Mem = erased_vertices;
00163 }
00164
00165 return erased_vertices;
00166 }
00167
00168 void Unmapped_Vertices_Here_Out(WN* wn)
00169 {
00170 for ( ; wn; wn = LWN_Get_Parent(wn)) {
00171 if (WN_opcode(wn) == OPC_DO_LOOP) {
00172 DO_LOOP_INFO* dli = Get_Do_Loop_Info(wn);
00173 dli->Has_Bad_Mem = 1;
00174 }
00175 }
00176 }
00177
00178 void LNO_Erase_Dg_From_Here_In(WN* wn, ARRAY_DIRECTED_GRAPH16* dg)
00179 {
00180 WN *outer_do = wn;
00181 WN *tmp = wn;
00182 while (tmp) {
00183 if (WN_opcode(tmp) == OPC_DO_LOOP) {
00184 outer_do = tmp;
00185 }
00186 tmp = LWN_Get_Parent(tmp);
00187 }
00188 if (LNO_Erase_Dg_From_Here_In_X(outer_do, dg))
00189 Unmapped_Vertices_Here_Out(outer_do);
00190 }
00191
00192 extern WN* Get_Only_Loop_Inside(const WN* wn, BOOL regions_ok);
00193 #endif
00194
00195
00196 #ifndef LNO
00197 ARRAY_DIRECTED_GRAPH16 *Current_Dep_Graph = NULL;
00198
00199 void *C_Dep_Graph(void)
00200 {
00201 return Current_Dep_Graph;
00202 }
00203
00204
00205 void
00206 Init_Dep_Graph(void *g)
00207 {
00208 if (Current_Dep_Graph != NULL)
00209 Dealloc_Dep_Graph ();
00210
00211 Current_Dep_Graph = (ARRAY_DIRECTED_GRAPH16 *)g;
00212 }
00213
00214
00215 void
00216 Dealloc_Dep_Graph(void)
00217 {
00218
00219 if (Current_Dep_Graph) {
00220 CXX_DELETE(Current_Dep_Graph, Malloc_Mem_Pool);
00221 Current_Dep_Graph = NULL;
00222 }
00223 }
00224
00225 void LNOPruneMapsUsingParity(void)
00226 {
00227 if (Current_Dep_Graph)
00228 Current_Dep_Graph->PruneMapsUsingParity();
00229 }
00230
00231 void LNOPreserveMapPair(WN *orig, WN *wn1, WN *wn2)
00232 {
00233 if (Current_Dep_Graph)
00234 Current_Dep_Graph->PreserveMapPair(orig, wn1, wn2);
00235 }
00236
00237 void LNOPrintDepGraph(FILE *fp)
00238 {
00239 if (Current_Dep_Graph)
00240 Current_Dep_Graph->Print(fp);
00241 }
00242
00243
00244 BOOL LnoDependenceEdge(WN *wn1, WN *wn2, EINDEX16 *distance, DIRECTION *direction, BOOL *is_must, BOOL *status)
00245 {
00246 VINDEX16 v1, v2;
00247 EINDEX16 edge;
00248
00249 *status= FALSE;
00250
00251 if (Current_Dep_Graph == NULL)
00252 return FALSE;
00253
00254 v1 = Current_Dep_Graph->Get_Vertex(wn1);
00255 v2 = Current_Dep_Graph->Get_Vertex(wn2);
00256
00257 if (v1 == 0 || v2 == 0)
00258 return FALSE;
00259
00260 *status = TRUE;
00261 edge = Current_Dep_Graph->Get_Edge(v1, v2);
00262
00263 if (edge)
00264 {
00265 DEP dep = Current_Dep_Graph->Dep(edge);
00266
00267 *direction = DEP_Direction(dep);
00268
00269 *is_must = Current_Dep_Graph->Is_Must(edge);
00270
00271 *distance = DEP_IsDistance(dep) ? DEP_Distance(dep) : DEP_DistanceBound(dep);
00272
00273 return TRUE;
00274 }
00275 return FALSE;
00276 }
00277
00278
00279 VINDEX16 LNOGetVertex(WN *wn)
00280 {
00281 if (Current_Dep_Graph)
00282 return Current_Dep_Graph->Get_Vertex(wn);
00283 return 0;
00284 }
00285
00286 #endif
00287
00288
00289 void ARRAY_DIRECTED_GRAPH16::Erase_Graph()
00290 {
00291 for(VINDEX16 v= Get_Vertex(); v; v= Get_Next_Vertex(v)) {
00292 WN *wn = Get_Wn(v);
00293 if (wn != NULL)
00294 WN_MAP_Set(_map,wn,0);
00295 }
00296 #ifdef LNO
00297 if (_type==DEPV_ARRAY_ARRAY_GRAPH) {
00298 for(EINDEX16 e= Get_Edge(); e; e= Get_Next_Edge(e)) {
00299 Delete_DEPV_ARRAY(_e[e].Depv_Array,_pool);
00300 }
00301 }
00302 #endif
00303 }
00304
00305 void ARRAY_DIRECTED_GRAPH16::PruneMapsUsingParity(void)
00306 {
00307
00308
00309
00310
00311 for(VINDEX16 v= Get_Vertex(); v; v= Get_Next_Vertex(v))
00312 {
00313 EINDEX16 e= Get_Out_Edge(v);
00314 WN *tree= Get_Wn(v);
00315
00316 while(e)
00317 {
00318 EINDEX16 e1= Get_Next_Out_Edge(e);
00319
00320 if (WN_parity_independent(tree, Get_Wn(Get_Sink(e))))
00321 {
00322 Remove_Edge(e);
00323 }
00324 e = e1;
00325 }
00326
00327 e = Get_In_Edge(v);
00328 while(e)
00329 {
00330 EINDEX16 e1= Get_Next_In_Edge(e);
00331
00332 if (WN_parity_independent(tree, Get_Wn(Get_Sink(e))))
00333 {
00334 Remove_Edge(e);
00335 }
00336 e = e1;
00337 }
00338 }
00339 }
00340
00341 void ARRAY_DIRECTED_GRAPH16::Print(FILE *fp)
00342 {
00343 VINDEX16 i;
00344 EINDEX16 e;
00345 if (_type==DEPV_ARRAY_ARRAY_GRAPH) {
00346 fprintf(fp,"Printing an ARRAY_DIRECTED_GRAPH16 of type DEPV_ARRAY \n");
00347 } else if (_type == LEVEL_ARRAY_GRAPH) {
00348 fprintf(fp,"Printing an ARRAY_DIRECTED_GRAPH16 of type level \n");
00349 } else {
00350 fprintf(fp,"Printing an ARRAY_DIRECTED_GRAPH16 of type DEP \n");
00351 }
00352 for (i=1; i<_v.Lastidx()+1; i++) {
00353 if (!_v[i].Is_Free()) {
00354 if (_type==DEPV_ARRAY_ARRAY_GRAPH) {
00355 #ifdef LNO
00356 BOOL is_load = FALSE;
00357 BOOL is_call = FALSE;
00358 WN *wn = _v[i].Wn;
00359 if (OPCODE_is_load(WN_opcode(wn))) {
00360 is_load = TRUE;
00361 if (WN_kid_count(wn) >= 1) {
00362 wn = WN_kid0(wn);
00363 }
00364 } else if (OPCODE_is_store(WN_opcode(wn))) {
00365 if (WN_kid_count(wn) >= 2) {
00366 wn = WN_kid1(wn);
00367 }
00368 } else {
00369 is_call = TRUE;
00370 }
00371 if (WN_operator(wn) == OPR_ARRAY) {
00372 WN *base = WN_array_base(wn);
00373 if (OPCODE_has_sym(WN_opcode(base)) && WN_st(base)) {
00374 if (is_load) {
00375 fprintf(fp,"Vertex %d for load from Wn = %s",i,
00376 ST_name(WN_st(WN_array_base(wn))));
00377 } else {
00378 fprintf(fp,"Vertex %d for store into Wn = %s",i,
00379 ST_name(WN_st(WN_array_base(wn))));
00380 }
00381 } else {
00382 if (is_load) {
00383 fprintf(fp,"Vertex %d for load from Wn = ??? ",i);
00384 } else {
00385 fprintf(fp,"Vertex %d for store into Wn = ??? ",i);
00386 }
00387 }
00388 ACCESS_ARRAY *array = (ACCESS_ARRAY *) WN_MAP_Get(LNO_Info_Map,wn);
00389 array->Print(fp);
00390 } else {
00391 if (is_load) {
00392 fprintf(fp,"Vertex %d for load from Wn = ",i);
00393 } else if (is_call) {
00394 fprintf(fp,"Vertex %d for call into Wn = ",i);
00395 } else {
00396 fprintf(fp,"Vertex %d for store into Wn = ",i);
00397 }
00398 Dump_WN(wn,fp,TRUE,0,0);
00399 }
00400 #endif
00401 } else {
00402 fprintf(fp,"Vertex %d for Wn = 0x%p",i,_v[i].Wn);
00403 #ifdef LNO
00404
00405 Dump_WN(_v[i].Wn,fp,TRUE,0,0);
00406 #endif
00407 fprintf(fp,"\n");
00408 }
00409 e = _v[i].Get_Out_Edge();
00410 while (e) {
00411 fprintf(fp,"Edge %d to vertex %d ",e,_e[e].Get_Sink());
00412 if (_type==DEPV_ARRAY_ARRAY_GRAPH) {
00413 #ifdef LNO
00414 fprintf(fp," has DEPV_ARRAY = ");
00415 _e[e].Depv_Array->Print(fp);
00416 #endif
00417 } else if (_type == LEVEL_ARRAY_GRAPH) {
00418 #ifdef LNO
00419 fprintf(fp," has level %d \n",_e[e].Level_Info.Level);
00420 #endif
00421 } else {
00422 fprintf(fp," has dep ");
00423 DEP_Print(_e[e].DEP_Struct.Dep,fp);
00424 fprintf(fp," and Is_Must is %d\n",_e[e].DEP_Struct.Is_Must);
00425 }
00426 e = _e[e].Get_Next_Out_Edge();
00427 }
00428 }
00429 }
00430
00431 }
00432
00433 #ifndef LNO
00434
00435 extern "C" void
00436 Depgraph_Write (void *depgraph, Output_File *fl, WN_MAP off_map)
00437 {
00438 ARRAY_DIRECTED_GRAPH16 *g = (ARRAY_DIRECTED_GRAPH16 *)depgraph;
00439 VINDEX16 vmax, new_vmax, v, ve, x;
00440 EINDEX16 emax, e;
00441 Elf64_Word wn_off;
00442 DEP_STRUCT dep;
00443 VINDEX16 *vertex_map;
00444
00445
00446 vmax = g->_v.Lastidx();
00447
00448 emax = g->_e.Lastidx();
00449
00450
00451 vertex_map = CXX_NEW_ARRAY(VINDEX16, vmax + 1, Malloc_Mem_Pool);
00452 x = 1;
00453 for (v = 1; v <= vmax; v++) {
00454
00455 if (g->Vertex_Is_In_Graph(v) && g->Get_Wn(v) != NULL) {
00456 vertex_map[v] = x;
00457 x += 1;
00458 } else {
00459 vertex_map[v] = 0;
00460 }
00461 }
00462 new_vmax = x - 1;
00463
00464 ir_b_save_buf((void *)&new_vmax, sizeof(VINDEX16), sizeof(VINDEX16), 0, fl);
00465 ir_b_save_buf((void *)&emax, sizeof(EINDEX16), sizeof(EINDEX16), 0, fl);
00466
00467
00468 for (v = 1; v <= vmax; v++) {
00469
00470
00471 if (vertex_map[v] == 0) continue;
00472
00473
00474 wn_off = (Elf64_Word)WN_MAP32_Get(off_map, g->Get_Wn(v));
00475 ir_b_save_buf((void *)&wn_off, sizeof(Elf64_Word), sizeof(Elf64_Word),
00476 0, fl);
00477 }
00478
00479
00480 for (v = 1; v <= vmax; v++) {
00481
00482
00483 if (vertex_map[v] == 0) continue;
00484
00485
00486 e = g->Get_Out_Edge(v);
00487 while (e) {
00488
00489
00490 ve = vertex_map[g->Get_Sink(e)];
00491 if (ve) {
00492 ir_b_save_buf((void *)&ve, sizeof(VINDEX16), sizeof(VINDEX16),0,fl);
00493
00494
00495 dep = g->_e[e].DEP_Struct;
00496 ir_b_save_buf((void *)&dep, sizeof(DEP_STRUCT),
00497 MAX(4,sizeof(DEP_STRUCT)), 0, fl);
00498
00499 } else {
00500 DevWarn("Missing sink \n");
00501 }
00502 e = g->Get_Next_Out_Edge(e);
00503 }
00504
00505
00506 ve = 0;
00507 ir_b_save_buf((void *)&ve, sizeof(VINDEX16), sizeof(VINDEX16), 0, fl);
00508 }
00509
00510 CXX_DELETE_ARRAY(vertex_map, Malloc_Mem_Pool);
00511 }
00512
00513
00514 #define WORD_ALIGNED(sz) (((sz) % 4) == 0 ? (sz) : (sz)+(4-((sz)%4)))
00515
00516 extern "C" void *
00517 Depgraph_Read (char *cur_addr, char *end_addr, char *wn_base)
00518 {
00519 ARRAY_DIRECTED_GRAPH16 *g;
00520 VINDEX16 vmax, v, ve;
00521 EINDEX16 emax;
00522 Elf64_Word node_offset;
00523 DEP_STRUCT dep;
00524 WN *node;
00525
00526
00527 vmax = *(VINDEX16 *)cur_addr;
00528 cur_addr += (sizeof(VINDEX16));
00529 emax = *(EINDEX16 *)cur_addr;
00530 cur_addr += (sizeof(EINDEX16));
00531
00532 g = CXX_NEW(ARRAY_DIRECTED_GRAPH16(vmax+1, emax+1, WN_MAP_DEPGRAPH,
00533 DEP_ARRAY_GRAPH), Malloc_Mem_Pool);
00534
00535
00536 cur_addr = (char*) WORD_ALIGNED((INTPTR)cur_addr);
00537 for (v = 1; v <= vmax; v++) {
00538
00539 node_offset = *(Elf64_Word *)cur_addr;
00540 cur_addr += (sizeof(Elf64_Word));
00541
00542 node = (WN *)(wn_base + node_offset);
00543 BOOL result = g->Add_Vertex(node);
00544 Is_True((result == v), ("New vertex not in order\n"));
00545 }
00546
00547
00548 for (v = 1; v <= vmax; v++) {
00549
00550 while (1) {
00551 ve = *(VINDEX16 *)cur_addr;
00552 cur_addr += (sizeof(VINDEX16));
00553 if (ve == 0) break;
00554
00555 cur_addr = (char *)WORD_ALIGNED((INTPTR)cur_addr);
00556
00557 dep = *(DEP_STRUCT *)cur_addr;
00558 cur_addr += (sizeof(DEP_STRUCT));
00559
00560
00561
00562 if ((ve > vmax) || (cur_addr > end_addr)) {
00563 CXX_DELETE(g, Malloc_Mem_Pool);
00564 return 0;
00565 }
00566
00567 g->Add_Edge(v, ve, dep.Dep,dep.Is_Must);
00568 }
00569 }
00570
00571 return (void *)g;
00572 }
00573 #endif
00574
00575
00576
00577
00578 #ifdef LNO
00579
00580 extern MEM_POOL LNO_local_pool;
00581 extern MEM_POOL LNO_default_pool;
00582 static MEM_POOL DEP_local_pool;
00583 static BOOL dep_mempool_initialized = FALSE;
00584 static INT Common_Nest(const DOLOOP_STACK *s1, const DOLOOP_STACK *s2);
00585 static INT Num_Bad(const DOLOOP_STACK *s1);
00586 static DOLOOP_STACK *Copy_Doloop_Stack(DOLOOP_STACK *orig,MEM_POOL *pool);
00587
00588
00589
00590
00591 static void Set_Bad_Mem(WN *wn)
00592 {
00593 while (wn) {
00594 if (WN_opcode(wn) == OPC_DO_LOOP) {
00595 DO_LOOP_INFO *dli = (DO_LOOP_INFO *) WN_MAP_Get(LNO_Info_Map,wn);
00596 if (dli->Has_Bad_Mem) {
00597 return;
00598 }
00599 dli->Has_Bad_Mem = TRUE;
00600 }
00601 wn = LWN_Get_Parent(wn);
00602 }
00603 }
00604
00605
00606 INT ARRAY_DIRECTED_GRAPH16::Build(WN *func_nd, MEM_POOL *pool)
00607 {
00608 Is_True(_type!=LEVEL_ARRAY_GRAPH,
00609 ("Build called on a LEVEL_ARRAY_GRAPH"));
00610 _pool = pool;
00611 if (!dep_mempool_initialized) {
00612 MEM_POOL_Initialize(&DEP_local_pool,"DEP_local_pool",FALSE);
00613 dep_mempool_initialized = TRUE;
00614 }
00615 MEM_POOL_Push(&LNO_local_pool);
00616 DOLOOP_STACK *stack=CXX_NEW(DOLOOP_STACK(&LNO_local_pool),&LNO_local_pool);
00617 INT res=Find_Region(func_nd,stack);
00618 MEM_POOL_Pop(&LNO_local_pool);
00619
00620
00621 if (res && _type == DEP_ARRAY_GRAPH) Add_Must();
00622
00623 return(res);
00624 }
00625
00626
00627
00628
00629
00630
00631
00632 INT ARRAY_DIRECTED_GRAPH16::Find_Region(WN *wn, DOLOOP_STACK *stack)
00633 {
00634 WN *kid;
00635
00636 if (OPCODE_is_leaf(WN_opcode(wn))) return(1);
00637
00638 if (WN_opcode(wn) == OPC_BLOCK) {
00639 kid = WN_first (wn);
00640 while (kid) {
00641 if (!Find_Region(kid,stack)) return(0);
00642 kid = WN_next(kid);
00643 }
00644 } else if (WN_opcode(wn) == OPC_DO_LOOP) {
00645 DO_LOOP_INFO *dli = (DO_LOOP_INFO *) WN_MAP_Get(LNO_Info_Map,wn);
00646 dli->Has_Bad_Mem = FALSE;
00647 stack->Push(wn);
00648 if (Do_Loop_Is_Good(wn) &&
00649 (!dli->Has_Unsummarized_Calls || dli->Is_Concurrent_Call) &&
00650 !dli->Has_Exits && !dli->Has_Barriers &&
00651 ((_type == DEPV_ARRAY_ARRAY_GRAPH) ||
00652 (Do_Loop_Is_Inner(wn) && !dli->Has_Gotos && !dli->Has_Barriers))) {
00653 if (!Build_Region(WN_do_body(wn),WN_do_body(wn),stack)) {
00654 #ifdef KEY
00655 if (_type == DEPV_ARRAY_ARRAY_GRAPH)
00656 #endif
00657 LNO_Erase_Dg_From_Here_In(wn, this);
00658 return(0);
00659 }
00660 if (dli->Has_Bad_Mem) LNO_Erase_Vertices_In_Loop(wn,this);
00661 } else {
00662 Set_Bad_Mem(wn);
00663 for (INT kidno=0; kidno<WN_kid_count(wn); kidno++) {
00664 kid = WN_kid(wn,kidno);
00665 if (!Find_Region(kid,stack))
00666 return(0);
00667 }
00668 }
00669 stack->Pop();
00670 } else {
00671 for (INT kidno=0; kidno<WN_kid_count(wn); kidno++) {
00672 kid = WN_kid(wn,kidno);
00673 if (!Find_Region(kid,stack)) return(0);
00674 }
00675 }
00676 return(1);
00677 }
00678
00679
00680 static BOOL Loop_Var(WN *wn, DOLOOP_STACK *stack1, DOLOOP_STACK *stack2)
00681 {
00682 SYMBOL sym(wn);
00683 INT common_nest = Common_Nest(stack1,stack2);
00684 for (INT i=0; i<common_nest; i++) {
00685 if (sym == SYMBOL(WN_index(stack1->Top_nth(i)))) {
00686 return TRUE;
00687 }
00688 }
00689 return FALSE;
00690 }
00691
00692
00693 static UINT statement_number;
00694
00695
00696
00697
00698
00699
00700
00701
00702 INT ARRAY_DIRECTED_GRAPH16::Build_Region(WN *start, WN* end,
00703 DOLOOP_STACK *stack, BOOL rebuild, BOOL skip_bad)
00704 {
00705 REF_LIST_STACK *writes = CXX_NEW(REF_LIST_STACK(&LNO_local_pool),
00706 &LNO_local_pool);
00707 REF_LIST_STACK *reads = CXX_NEW(REF_LIST_STACK(&LNO_local_pool),
00708 &LNO_local_pool);
00709 CALL_STACK *calls = CXX_NEW(CALL_STACK(&LNO_local_pool),
00710 &LNO_local_pool);
00711
00712 SCALAR_STACK *scalar_writes = CXX_NEW(SCALAR_STACK(&LNO_local_pool),
00713 &LNO_local_pool);
00714 SCALAR_STACK *scalar_reads = CXX_NEW(SCALAR_STACK(&LNO_local_pool),
00715 &LNO_local_pool);
00716
00717 statement_number = 0;
00718
00719 for (WN* wn=start; wn!=WN_next(end); wn=WN_next(wn)) {
00720 if (!Gather_References(wn,writes,reads,stack,scalar_writes,scalar_reads,
00721 calls,skip_bad))
00722 return(0);
00723 }
00724 Is_True(!calls->Elements() || Has_Call_Info(calls->Bottom_nth(0)->_call) ||
00725 Do_Loop_Is_Concurrent_Call(Enclosing_Do_Loop(start)),
00726 ("Unexpected call in Build_Region"));
00727
00728
00729
00730 if (Permutation_Arrays->Elements()) {
00731 INT i;
00732 for (i=0; i<Permutation_Arrays->Elements(); i++) {
00733 Permutation_Arrays->Bottom_nth(i)._is_good = TRUE;
00734 }
00735 for (i=0; i<reads->Elements(); i++) {
00736 REFERENCE_ITER iter1(reads->Bottom_nth(i));
00737 for (REFERENCE_NODE *n1=iter1.First(); !iter1.Is_Empty();
00738 n1=iter1.Next()) {
00739 WN *read = n1->Wn;
00740 WN *array = WN_kid0(read);
00741 if (WN_operator(array) == OPR_ADD) {
00742 WN *kid0 = WN_kid0(array);
00743 WN *kid1 = WN_kid1(array);
00744 if (WN_operator(kid0) == OPR_ARRAY) {
00745 array = kid0;
00746 } else {
00747 Is_True(WN_operator(kid1) == OPR_ARRAY,
00748 ("Bad ref in Build_Region"));
00749 array = kid1;
00750 }
00751 }
00752 Is_True(WN_operator(array) == OPR_ARRAY,
00753 ("Bad ref in Build_Region"));
00754 WN *base = WN_array_base(array);
00755 ST *read_st = WN_st(base);
00756 for (INT j=0; j<Permutation_Arrays->Elements(); j++) {
00757 if (read_st == Permutation_Arrays->Bottom_nth(j)._st) {
00758
00759 BOOL is_bad = FALSE;
00760 for (INT k=0; k<writes->Elements() &&!is_bad; k++) {
00761 REFERENCE_ITER iter2(writes->Bottom_nth(k));
00762 for (REFERENCE_NODE *n2=iter2.First(); !iter2.Is_Empty() &&
00763 !is_bad; n2=iter2.Next()) {
00764 WN *write = n2->Wn;
00765 if (Overlapped_base(Alias_Mgr,write,read)!=NOT_ALIASED){
00766 is_bad = TRUE;
00767 }
00768 }
00769 }
00770 for (INT si=0; si<scalar_writes->Elements(); si++) {
00771 SCALAR_NODE *snode = scalar_writes->Bottom_nth(si);
00772 WN *scalar_write = snode->Bottom_nth(0)->Wn;
00773 if (Overlapped_base(Alias_Mgr,scalar_write,read)!=NOT_ALIASED){
00774 is_bad = TRUE;
00775 }
00776 }
00777 if (is_bad) Permutation_Arrays->Bottom_nth(j)._is_good = FALSE;
00778 }
00779 }
00780 }
00781 }
00782 }
00783
00784
00785
00786
00787 INT i;
00788 for (i=0; i<writes->Elements(); i++) {
00789 for (INT j=i; j<writes->Elements(); j++) {
00790
00791
00792 if (i==j || !writes->Bottom_nth(i)->ST_Base ||
00793 !writes->Bottom_nth(j)->ST_Base) {
00794 REFERENCE_ITER iter1(writes->Bottom_nth(i));
00795 for (REFERENCE_NODE *n1=iter1.First(); !iter1.Is_Empty();
00796 n1=iter1.Next()) {
00797 VINDEX16 v1=Get_Vertex(n1->Wn);
00798 if (v1) {
00799 REFERENCE_ITER iter2;
00800 if (i == j) iter2.Init(n1);
00801 else iter2.Init(writes->Bottom_nth(j));
00802 for (REFERENCE_NODE *n2=iter2.First(); !iter2.Is_Empty();
00803 n2=iter2.Next()) {
00804 VINDEX16 v2=Get_Vertex(n2->Wn);
00805 if (v2) {
00806 if (rebuild) {
00807 EINDEX16 e=Get_Edge(v1,v2);
00808 if (e)
00809 Delete_Edge(e);
00810 e=Get_Edge(v2,v1);
00811 if (e)
00812 Delete_Edge(e);
00813 }
00814 if (!Add_Edge(n1->Wn,n1->Stack,n2->Wn,n2->Stack,
00815 n1->Statement_Number < n2->Statement_Number)) {
00816 return(0);
00817 }
00818 }
00819 }
00820 }
00821 }
00822 }
00823 }
00824 }
00825
00826
00827 for (i=0; i<writes->Elements(); i++) {
00828 for (INT j=0; j<reads->Elements(); j++) {
00829 ST *base1 = writes->Bottom_nth(i)->ST_Base;
00830 ST *base2 = reads->Bottom_nth(j)->ST_Base;
00831 if (!base1 || !base2 || (base1 == base2)) {
00832 REFERENCE_ITER iter1(writes->Bottom_nth(i));
00833 for (REFERENCE_NODE *n1=iter1.First(); !iter1.Is_Empty();
00834 n1=iter1.Next()) {
00835 VINDEX16 v1=Get_Vertex(n1->Wn);
00836 if (v1) {
00837 REFERENCE_ITER iter2(reads->Bottom_nth(j));
00838 for (REFERENCE_NODE *n2=iter2.First();!iter2.Is_Empty();
00839 n2=iter2.Next()) {
00840 VINDEX16 v2=Get_Vertex(n2->Wn);
00841 if (v2) {
00842 if (rebuild) {
00843 EINDEX16 e=Get_Edge(v1,v2);
00844 if (e)
00845 Delete_Edge(e);
00846 e=Get_Edge(v2,v1);
00847 if (e)
00848 Delete_Edge(e);
00849 }
00850 if (!Add_Edge(n1->Wn,n1->Stack,n2->Wn,n2->Stack,
00851 n1->Statement_Number < n2->Statement_Number)) {
00852 return(0);
00853 }
00854 }
00855 }
00856 }
00857 }
00858 }
00859 }
00860 }
00861
00862
00863 for (i=0; i<Permutation_Arrays->Elements(); i++) {
00864 Permutation_Arrays->Bottom_nth(i)._is_good = FALSE;
00865 }
00866
00867
00868
00869
00870
00871 for (i=0; i<calls->Elements(); i++) {
00872 if (calls->Bottom_nth(i)->_is_concurrent_call) {
00873 WN *call = calls->Bottom_nth(i)->_call;
00874 DOLOOP_STACK *call_stack = calls->Bottom_nth(i)->_stack;
00875 UINT call_statement_number = calls->Bottom_nth(i)->_statement_number;
00876 VINDEX16 vcall = Get_Vertex(call);
00877 INT j;
00878 for (j=i; j<calls->Elements(); j++) {
00879 if (calls->Bottom_nth(j)->_is_concurrent_call) {
00880 WN *call2 = calls->Bottom_nth(j)->_call;
00881 DOLOOP_STACK *call_stack2 = calls->Bottom_nth(j)->_stack;
00882 UINT call_statement_number2 = calls->Bottom_nth(j)->_statement_number;
00883 VINDEX16 vcall2 = Get_Vertex(call2);
00884 if (call_statement_number < call_statement_number2) {
00885 if (rebuild) {
00886 EINDEX16 e=Get_Edge(vcall,vcall2);
00887 if (e) Delete_Edge(e);
00888 }
00889 if (!Add_Edge_Equals(call,call_stack,call2,call_stack2)) {
00890 return 0;
00891 }
00892 } else {
00893 if (rebuild) {
00894 EINDEX16 e=Get_Edge(vcall2,vcall);
00895 if (e) Delete_Edge(e);
00896 }
00897 if (!Add_Edge_Equals(call2,call_stack2,call,call_stack)) {
00898 return 0;
00899 }
00900 }
00901 }
00902 }
00903 for (j=0; j<writes->Elements(); j++) {
00904 REFERENCE_ITER iter1(writes->Bottom_nth(j));
00905 for (REFERENCE_NODE *n1=iter1.First(); !iter1.Is_Empty();
00906 n1=iter1.Next()) {
00907 VINDEX16 v1=Get_Vertex(n1->Wn);
00908 if (call_statement_number < n1->Statement_Number) {
00909 if (rebuild) {
00910 EINDEX16 e=Get_Edge(vcall,v1);
00911 if (e) Delete_Edge(e);
00912 }
00913 if (!Add_Edge_Equals(call,call_stack,n1->Wn,n1->Stack)) {
00914 return 0;
00915 }
00916 } else {
00917 if (rebuild) {
00918 EINDEX16 e=Get_Edge(v1,vcall);
00919 if (e) Delete_Edge(e);
00920 }
00921 if (!Add_Edge_Equals(n1->Wn,n1->Stack,call,call_stack)) {
00922 return 0;
00923 }
00924 }
00925 }
00926 }
00927 for (j=0; j<reads->Elements(); j++) {
00928 REFERENCE_ITER iter1(reads->Bottom_nth(j));
00929 for (REFERENCE_NODE *n1=iter1.First(); !iter1.Is_Empty();
00930 n1=iter1.Next()) {
00931 VINDEX16 v1=Get_Vertex(n1->Wn);
00932 if (call_statement_number < n1->Statement_Number) {
00933 if (rebuild) {
00934 EINDEX16 e=Get_Edge(vcall,v1);
00935 if (e) Delete_Edge(e);
00936 }
00937 if (!Add_Edge_Equals(call,call_stack,n1->Wn,n1->Stack)) {
00938 return 0;
00939 }
00940 } else {
00941 if (rebuild) {
00942 EINDEX16 e=Get_Edge(v1,vcall);
00943 if (e) Delete_Edge(e);
00944 }
00945 if (!Add_Edge_Equals(n1->Wn,n1->Stack,call,call_stack)) {
00946 return 0;
00947 }
00948 }
00949 }
00950 }
00951 }
00952 }
00953
00954
00955 for (i=0; i<calls->Elements(); i++) {
00956 WN *call = calls->Bottom_nth(i)->_call;
00957 DOLOOP_STACK *call_stack = calls->Bottom_nth(i)->_stack;
00958 UINT call_statement_number = calls->Bottom_nth(i)->_statement_number;
00959 VINDEX16 vcall = Get_Vertex(call);
00960 for (INT j=i; j<calls->Elements(); j++) {
00961 WN *call2 = calls->Bottom_nth(j)->_call;
00962 if (!calls->Bottom_nth(i)->_is_concurrent_call ||
00963 !calls->Bottom_nth(j)->_is_concurrent_call) {
00964 DOLOOP_STACK *call_stack2 = calls->Bottom_nth(j)->_stack;
00965 UINT call_statement_number2 = calls->Bottom_nth(j)->_statement_number;
00966 VINDEX16 vcall2 = Get_Vertex(call2);
00967 if (rebuild) {
00968 EINDEX16 e=Get_Edge(vcall,vcall2);
00969 if (e) Delete_Edge(e);
00970 e=Get_Edge(vcall2,vcall);
00971 if (e) Delete_Edge(e);
00972 }
00973 if (!Add_Edge(call,call_stack,call2,call_stack2,
00974 call_statement_number < call_statement_number2)) {
00975 return(0);
00976 }
00977 }
00978 }
00979 if (!calls->Bottom_nth(i)->_is_concurrent_call) {
00980 INT j;
00981 for (j=0; j<writes->Elements(); j++) {
00982 REFERENCE_ITER iter1(writes->Bottom_nth(j));
00983 for (REFERENCE_NODE *n1=iter1.First(); !iter1.Is_Empty();
00984 n1=iter1.Next()) {
00985 VINDEX16 v1=Get_Vertex(n1->Wn);
00986 if (rebuild) {
00987 EINDEX16 e=Get_Edge(vcall,v1);
00988 if (e) Delete_Edge(e);
00989 }
00990 if (!Add_Edge(call,call_stack,n1->Wn,n1->Stack,
00991 call_statement_number < n1->Statement_Number)) {
00992 return 0;
00993 }
00994 }
00995 }
00996 for (j=0; j<reads->Elements(); j++) {
00997 REFERENCE_ITER iter1(reads->Bottom_nth(j));
00998 for (REFERENCE_NODE *n1=iter1.First(); !iter1.Is_Empty();
00999 n1=iter1.Next()) {
01000 VINDEX16 v1=Get_Vertex(n1->Wn);
01001 if (rebuild) {
01002 EINDEX16 e=Get_Edge(vcall,v1);
01003 if (e) Delete_Edge(e);
01004 }
01005 if (!Add_Edge(call,call_stack,n1->Wn,n1->Stack,
01006 call_statement_number < n1->Statement_Number)) {
01007 return 0;
01008 }
01009 }
01010 }
01011 }
01012 }
01013
01014 if (_type == DEPV_ARRAY_ARRAY_GRAPH) {
01015
01016
01017
01018 for (i=0; i<writes->Elements(); i++) {
01019 INT si;
01020 for (si=0; si<scalar_writes->Elements(); si++) {
01021 SCALAR_NODE *snode = scalar_writes->Bottom_nth(si);
01022 WN *scalar_write = snode->Bottom_nth(0)->Wn;
01023 ST *base = writes->Bottom_nth(i)->ST_Base;
01024 WN *array_write = writes->Bottom_nth(i)->Head()->Wn;
01025 if (!base ||
01026 Overlapped_base(Alias_Mgr,scalar_write,array_write) != NOT_ALIASED) {
01027 REFERENCE_ITER iter1(writes->Bottom_nth(i));
01028 for (REFERENCE_NODE *n1=iter1.First(); !iter1.Is_Empty();
01029 n1=iter1.Next()) {
01030 array_write = n1->Wn;
01031 VINDEX16 awv = Get_Vertex(array_write);
01032 if (awv) {
01033 if (base ||
01034 Overlapped_base(Alias_Mgr,scalar_write,array_write)!=NOT_ALIASED){
01035 for (INT sj=0; sj<snode->Elements(); sj++) {
01036 scalar_write = snode->Bottom_nth(sj)->Wn;
01037 DOLOOP_STACK *scalar_stack=CXX_NEW(DOLOOP_STACK(&LNO_local_pool),
01038 &LNO_local_pool);
01039 Build_Doloop_Stack(scalar_write, scalar_stack);
01040 if (!Loop_Var(scalar_write,scalar_stack,n1->Stack)) {
01041 VINDEX16 swv = Get_Vertex(scalar_write);
01042 if (!swv) {
01043 if (!Add_Vertex(scalar_write)) {
01044 return 0;
01045 }
01046 swv = Get_Vertex(scalar_write);
01047 }
01048 if (rebuild) {
01049 EINDEX16 e=Get_Edge(awv,swv);
01050 if (e)
01051 Delete_Edge(e);
01052 e=Get_Edge(swv,awv);
01053 if (e)
01054 Delete_Edge(e);
01055 }
01056 if (!Add_Edge_Stars(array_write,n1->Stack,
01057 scalar_write,scalar_stack,
01058 n1->Statement_Number < snode->Bottom_nth(sj)->Statement_Number,
01059 FALSE)) {
01060 return 0;
01061 }
01062 }
01063 }
01064 }
01065 }
01066 }
01067 }
01068 }
01069 for (si=0; si<scalar_reads->Elements(); si++) {
01070 SCALAR_NODE *snode = scalar_reads->Bottom_nth(si);
01071 WN *scalar_read = snode->Bottom_nth(0)->Wn;
01072 ST *base = writes->Bottom_nth(i)->ST_Base;
01073 WN *array_write = writes->Bottom_nth(i)->Head()->Wn;
01074 if (!base ||
01075 Overlapped_base(Alias_Mgr,scalar_read,array_write) != NOT_ALIASED) {
01076 REFERENCE_ITER iter1(writes->Bottom_nth(i));
01077 for (REFERENCE_NODE *n1=iter1.First(); !iter1.Is_Empty();
01078 n1=iter1.Next()) {
01079 array_write = n1->Wn;
01080 VINDEX16 awv = Get_Vertex(array_write);
01081 if (awv) {
01082 if (base ||
01083 Overlapped_base(Alias_Mgr,scalar_read,array_write)!=NOT_ALIASED) {
01084 for (INT sj=0; sj<snode->Elements(); sj++) {
01085 scalar_read = snode->Bottom_nth(sj)->Wn;
01086 DOLOOP_STACK *scalar_stack=CXX_NEW(DOLOOP_STACK(&LNO_local_pool),
01087 &LNO_local_pool);
01088 Build_Doloop_Stack(scalar_read, scalar_stack);
01089 VINDEX16 srv = Get_Vertex(scalar_read);
01090 if (!srv) {
01091 if (!Add_Vertex(scalar_read)) {
01092 return 0;
01093 }
01094 srv = Get_Vertex(scalar_read);
01095 }
01096 if (rebuild) {
01097 EINDEX16 e=Get_Edge(awv,srv);
01098 if (e)
01099 Delete_Edge(e);
01100 e=Get_Edge(srv,awv);
01101 if (e)
01102 Delete_Edge(e);
01103 }
01104 if (!Add_Edge_Stars(array_write,n1->Stack,scalar_read,
01105 scalar_stack,
01106 n1->Statement_Number < snode->Bottom_nth(sj)->Statement_Number,
01107 FALSE)) {
01108 return 0;
01109 }
01110 }
01111 }
01112 }
01113 }
01114 }
01115 }
01116 }
01117
01118
01119 for (i=0; i<reads->Elements(); i++) {
01120 for (INT si=0; si<scalar_writes->Elements(); si++) {
01121 SCALAR_NODE *snode = scalar_writes->Bottom_nth(si);
01122 WN *scalar_write = snode->Bottom_nth(0)->Wn;
01123 ST *base = reads->Bottom_nth(i)->ST_Base;
01124 WN *array_read = reads->Bottom_nth(i)->Head()->Wn;
01125 if (!base ||
01126 Overlapped_base(Alias_Mgr,scalar_write,array_read) != NOT_ALIASED) {
01127 REFERENCE_ITER iter1(reads->Bottom_nth(i));
01128 for (REFERENCE_NODE *n1=iter1.First(); !iter1.Is_Empty();
01129 n1=iter1.Next()) {
01130 array_read = n1->Wn;
01131 VINDEX16 arv = Get_Vertex(array_read);
01132 if (arv) {
01133 if (base ||
01134 Overlapped_base(Alias_Mgr,scalar_write,array_read)!=NOT_ALIASED) {
01135 for (INT sj=0; sj<snode->Elements(); sj++) {
01136 scalar_write = snode->Bottom_nth(sj)->Wn;
01137 DOLOOP_STACK *scalar_stack=CXX_NEW(DOLOOP_STACK(&LNO_local_pool),
01138 &LNO_local_pool);
01139 Build_Doloop_Stack(scalar_write, scalar_stack);
01140 VINDEX16 swv = Get_Vertex(scalar_write);
01141 if (!swv) {
01142 if (!Add_Vertex(scalar_write)) {
01143 return 0;
01144 }
01145 swv = Get_Vertex(scalar_write);
01146 }
01147 if (rebuild) {
01148 EINDEX16 e=Get_Edge(arv,swv);
01149 if (e)
01150 Delete_Edge(e);
01151 e=Get_Edge(swv,arv);
01152 if (e)
01153 Delete_Edge(e);
01154 }
01155 if (!Add_Edge_Stars(array_read,n1->Stack,scalar_write,
01156 scalar_stack,
01157 n1->Statement_Number < snode->Bottom_nth(sj)->Statement_Number,
01158 FALSE)) {
01159 return 0;
01160 }
01161 }
01162 }
01163 }
01164 }
01165 }
01166 }
01167 }
01168 }
01169 return(1);
01170 }
01171
01172
01173
01174
01175 static BOOL Equiv_Memory(WN *wn1, WN *wn2)
01176 {
01177 if (!wn1 || !wn2) return FALSE;
01178 if (!WN_Equiv(wn1,wn2)) {
01179 return FALSE;
01180 }
01181 for (INT i=0; i<WN_kid_count(wn1); i++) {
01182 if (!Equiv_Memory(WN_kid(wn1,i),WN_kid(wn2,i))) {
01183 return FALSE;
01184 }
01185 }
01186 return TRUE;
01187 }
01188
01189
01190
01191 static BOOL Compiler_Generated(WN *wn)
01192 {
01193 Is_True(OPCODE_is_expression(WN_opcode(wn)),
01194 ("Bad wn for Compiler_Generated"));
01195 OPCODE opc = WN_opcode(wn);
01196 if (OPCODE_has_sym(opc) && ST_pt_to_compiler_generated_mem(WN_st(wn))) {
01197 return TRUE;
01198 } else {
01199 for (INT kidno=0; kidno<WN_kid_count(wn); kidno++) {
01200 if (Compiler_Generated(WN_kid(wn,kidno))) {
01201 return TRUE;
01202 }
01203 }
01204 }
01205 return FALSE;
01206 }
01207
01208
01209
01210 static BOOL Ref_Inner_Invar(WN *addr, WN *loop)
01211 {
01212 OPCODE opcode = WN_opcode(addr);
01213 OPERATOR oper = OPCODE_operator(opcode);
01214 if ((oper == OPR_LDID) || (oper == OPR_PARM)) {
01215 DEF_LIST *defs = Du_Mgr->Ud_Get_Def(addr);
01216 if (defs) {
01217 DEF_LIST_ITER iter(defs);
01218 for(DU_NODE *node=iter.First(); !iter.Is_Empty(); node=iter.Next()) {
01219 WN *def = node->Wn();
01220 WN *parent = def;
01221 while (parent && WN_opcode(parent) != OPC_DO_LOOP) {
01222 parent = LWN_Get_Parent(parent);
01223 }
01224 if (parent == loop) return FALSE;
01225 }
01226 }
01227 } else if (OPCODE_is_load(opcode)) {
01228 return FALSE;
01229 }
01230 for (INT kidno=0; kidno<WN_kid_count(addr); kidno++) {
01231 if (!Ref_Inner_Invar(WN_kid(addr,kidno),loop)) {
01232 return FALSE;
01233 }
01234 }
01235 return TRUE;
01236 }
01237
01238
01239 static SRCPOS Find_Line(WN *wn)
01240 {
01241 WN *tmp_wn = wn;
01242 while (OPCODE_is_expression(WN_opcode(tmp_wn))) {
01243 tmp_wn = LWN_Get_Parent(tmp_wn);
01244 }
01245 return WN_Get_Linenum(tmp_wn);
01246 }
01247
01248
01249 BOOL ARRAY_DIRECTED_GRAPH16::Add_Edge(WN *ref1, const DOLOOP_STACK *s1,
01250 WN *ref2, const DOLOOP_STACK *s2,
01251 BOOL s1_lex_before_s2, BOOL use_bounds)
01252 {
01253 OPCODE op1 = WN_opcode(ref1);
01254 OPCODE op2 = WN_opcode(ref2);
01255 OPERATOR oper1 = OPCODE_operator(op1);
01256 OPERATOR oper2 = OPCODE_operator(op2);
01257 Is_True(oper1 != OPR_ARRAY, ("ref 1 is an array in Add_Edge\n"));
01258 Is_True(oper2 != OPR_ARRAY, ("ref 2 is an array in Add_Edge\n"));
01259 if (!OPCODE_is_load(op1) && !OPCODE_is_store(op1) && !OPCODE_is_call(op1)) {
01260 return Add_Edge_Stars(ref1,s1,ref2,s2,s1_lex_before_s2);
01261 }
01262 if (!OPCODE_is_load(op2) && !OPCODE_is_store(op2) && !OPCODE_is_call(op2)) {
01263 return Add_Edge_Stars(ref1,s1,ref2,s2,s1_lex_before_s2);
01264 }
01265 if ((oper1 == OPR_LDID) || (oper1 == OPR_STID) ||
01266 (oper2 == OPR_LDID) || (oper2 == OPR_STID)) {
01267 return Add_Edge_Stars(ref1,s1,ref2,s2,s1_lex_before_s2);
01268 }
01269
01270 if (OPCODE_is_call(op1)) {
01271 if (Do_Loop_Is_Concurrent_Call(Enclosing_Do_Loop(ref1))) {
01272 if (s1_lex_before_s2) {
01273 return Add_Edge_Equals(ref1,s1,ref2,s2);
01274 } else {
01275 return Add_Edge_Equals(ref2,s2,ref1,s1);
01276 }
01277 } else if (!Has_Call_Info(ref1)) {
01278 return Add_Edge_Stars(ref1,s1,ref2,s2,s1_lex_before_s2);
01279 }
01280 } else if (OPCODE_is_call(op2)) {
01281 if (Do_Loop_Is_Concurrent_Call(Enclosing_Do_Loop(ref2))) {
01282 if (s1_lex_before_s2) {
01283 return Add_Edge_Equals(ref1,s1,ref2,s2);
01284 } else {
01285 return Add_Edge_Equals(ref2,s2,ref1,s1);
01286 }
01287 } else if (!Has_Call_Info(ref2)) {
01288 return Add_Edge_Stars(ref1,s1,ref2,s2,s1_lex_before_s2);
01289 }
01290 }
01291
01292 WN *addr1=NULL,*addr2=NULL;
01293 if (!OPCODE_is_call(op1) ) {
01294 addr1 = (OPCODE_is_store(op1) ? (WN_kid1(ref1)) : (WN_kid0(ref1))) ;
01295 }
01296 if (!OPCODE_is_call(op2)) {
01297 addr2 = (OPCODE_is_store(op2) ? (WN_kid1(ref2)) : (WN_kid0(ref2))) ;
01298 }
01299
01300 BOOL is_ivdep = FALSE;
01301 BOOL concurrent_directive = FALSE;
01302 BOOL s2_lex_before_s1 = ((!s1_lex_before_s2) && !(ref1 == ref2));
01303 Is_True(_type!=LEVEL_ARRAY_GRAPH,
01304 ("Add_Edge called on a graph of type level"));
01305 UINT8 common_nest;
01306 if (_type == DEPV_ARRAY_ARRAY_GRAPH) {
01307 common_nest = Common_Nest(s1,s2);
01308 if ((common_nest == s1->Elements()) &&
01309 Do_Loop_Is_Ivdep(s1->Top_nth(0))) {
01310 is_ivdep = TRUE;
01311 }
01312 for (INT i=0; i<common_nest; i++) {
01313 if (Do_Loop_Concurrent_Directive(s1->Bottom_nth(i))) {
01314 concurrent_directive = TRUE;
01315 }
01316 }
01317 } else {
01318 Is_True(s1->Elements() == s2->Elements(),
01319 ("Add_Edge called on a DEP graph with refs not in the same inner loop"));
01320 common_nest = s1->Elements();
01321 if (Do_Loop_Concurrent_Directive(s1->Top_nth(0))) {
01322 concurrent_directive = TRUE;
01323 }
01324 if (Do_Loop_Is_Ivdep(s1->Top_nth(0))) {
01325 is_ivdep = TRUE;
01326 }
01327 }
01328 if (is_ivdep) {
01329 if (Compiler_Generated(addr1) ||
01330 Compiler_Generated(addr2)) {
01331 is_ivdep = FALSE;
01332 }
01333 }
01334
01335 if (is_ivdep && !Cray_Ivdep && !Liberal_Ivdep &&
01336 !OPCODE_is_call(op1) && !OPCODE_is_call(op2) &&
01337 Ref_Inner_Invar(addr1,s1->Top_nth(0)) &&
01338 Ref_Inner_Invar(addr2,s1->Top_nth(0))) {
01339 is_ivdep = FALSE;
01340 }
01341
01342 UINT8 num_bad = Num_Bad(s1);
01343 if ((num_bad < common_nest) || (_type == DEP_ARRAY_GRAPH)) {
01344 MEM_POOL_Push(&DEP_local_pool);
01345
01346 INT dv_dim;
01347 if (_type == DEPV_ARRAY_ARRAY_GRAPH) {
01348 dv_dim = common_nest-num_bad;
01349 } else {
01350 dv_dim = 1;
01351 }
01352
01353 DEPV_LIST *tmp = CXX_NEW(DEPV_LIST(ref1,ref2,common_nest,
01354 dv_dim,use_bounds,&DEP_local_pool,s1,s2),&DEP_local_pool);
01355 if (!tmp->Is_Empty()) {
01356
01357 VINDEX16 v1 = Get_Vertex(ref1);
01358 VINDEX16 v2 = Get_Vertex(ref2);
01359 if (v1 == 0 || v2 == 0)
01360 return FALSE;
01361 if (_type == DEPV_ARRAY_ARRAY_GRAPH) {
01362 DEPV_LIST *pos = CXX_NEW(DEPV_LIST(tmp->Num_Dim(),tmp->Num_Unused_Dim(),
01363 &DEP_local_pool), &DEP_local_pool);
01364 DEPV_LIST *neg = CXX_NEW(DEPV_LIST(tmp->Num_Dim(),tmp->Num_Unused_Dim(),
01365 &DEP_local_pool),&DEP_local_pool);
01366 if (ref1 == ref2) {
01367 tmp->Lex_Pos_Decompose(&DEP_local_pool,pos,neg,FALSE,FALSE);
01368 } else if (s1_lex_before_s2) {
01369 tmp->Lex_Pos_Decompose(&DEP_local_pool,pos,neg,TRUE,FALSE);
01370 } else {
01371 tmp->Lex_Pos_Decompose(&DEP_local_pool,pos,neg,FALSE,TRUE);
01372 }
01373
01374
01375
01376 if (concurrent_directive) {
01377 if (!OPCODE_is_call(op1) && !OPCODE_is_call(op2)) {
01378 if (!Ref_Inner_Invar(addr1,s1->Top_nth(0)) &&
01379 !Ref_Inner_Invar(addr2,s2->Top_nth(0))) {
01380 for (INT i=0; i<dv_dim; i++) {
01381 if (Do_Loop_Concurrent_Directive(s1->Bottom_nth(i))) {
01382 pos->Eliminate_Non_Distance_Carried_By(i);
01383 neg->Eliminate_Non_Distance_Carried_By(i);
01384 }
01385 }
01386 }
01387 }
01388 }
01389 BOOL bad_ivdep = FALSE;
01390 if (is_ivdep) {
01391 if (Cray_Ivdep) {
01392 if (s1_lex_before_s2) {
01393 if (neg->Is_Inner_Non_Zero_Single_Distance()) bad_ivdep = TRUE;
01394 neg->Eliminate_Inner_Carried();
01395 } else if (s2_lex_before_s1) {
01396 if (pos->Is_Inner_Non_Zero_Single_Distance()) bad_ivdep = TRUE;
01397 pos->Eliminate_Inner_Carried();
01398 } else {
01399 if (neg->Is_Inner_Non_Zero_Single_Distance()) bad_ivdep = TRUE;
01400 if (pos->Is_Inner_Non_Zero_Single_Distance()) bad_ivdep = TRUE;
01401 pos->Eliminate_Inner_Carried();
01402 neg->Eliminate_Inner_Carried();
01403 }
01404 } else if (Liberal_Ivdep) {
01405 if ((ref1 != ref2) && Equiv_Memory(addr1,addr2)) bad_ivdep = TRUE;
01406 if (neg->Is_Inner_Non_Zero_Single_Distance()) bad_ivdep = TRUE;
01407 if (pos->Is_Inner_Non_Zero_Single_Distance()) bad_ivdep = TRUE;
01408 pos->Eliminate_Inner_Carried_Or_All_Equals();
01409 neg->Eliminate_Inner_Carried_Or_All_Equals();
01410 } else {
01411 if (neg->Is_Inner_Non_Zero_Single_Distance()) {
01412 bad_ivdep = TRUE;
01413 }
01414 if (pos->Is_Inner_Non_Zero_Single_Distance()) {
01415 bad_ivdep = TRUE;
01416 }
01417 pos->Eliminate_Inner_Carried();
01418 neg->Eliminate_Inner_Carried();
01419 }
01420 }
01421 if (bad_ivdep) {
01422 char error[120];
01423 sprintf(error,
01424 "IVDEP where there is an obvious dependence to ref on line %d. Dependence ignored.",
01425 Srcpos_To_Line(Find_Line(ref2)));
01426 ErrMsgSrcpos(EC_LNO_Generic,Find_Line(ref1),error);
01427 }
01428
01429 if (!pos->Is_Empty()) {
01430 DEPV_ARRAY *array = Create_DEPV_ARRAY(pos,_pool);
01431 if (!Add_Edge(v1, v2,array)) {
01432 MEM_POOL_Pop(&DEP_local_pool);
01433 return(FALSE);
01434 }
01435 }
01436 if (!neg->Is_Empty() && (ref2 != ref1)) {
01437 DEPV_ARRAY *array = Create_DEPV_ARRAY(neg,_pool);
01438 if (!Add_Edge(v2, v1,array)) {
01439 MEM_POOL_Pop(&DEP_local_pool);
01440 return(FALSE);
01441 }
01442 }
01443 } else {
01444 DEP tmp_dep = tmp->Convert_To_Dep();
01445 DEP *pos,*neg;
01446 if (ref1 == ref2) {
01447 DEP_Lex_Pos_Decompose(tmp_dep,&DEP_local_pool,&pos,&neg,0,0);
01448 } else if (s1_lex_before_s2) {
01449 DEP_Lex_Pos_Decompose(tmp_dep,&DEP_local_pool,&pos,&neg,TRUE,FALSE);
01450 } else {
01451 DEP_Lex_Pos_Decompose(tmp_dep,&DEP_local_pool,&pos,&neg,FALSE,TRUE);
01452 }
01453
01454 BOOL bad_ivdep = FALSE;
01455 if (is_ivdep) {
01456 if (Cray_Ivdep) {
01457 if (DEP_IsDistance(tmp_dep)&&DEP_Distance(tmp_dep)) bad_ivdep=TRUE;
01458 if (s1_lex_before_s2) {
01459 neg = NULL;
01460 } else if (s2_lex_before_s1) {
01461 pos = NULL;
01462 } else {
01463 neg = pos = NULL;
01464 }
01465 } else if (Liberal_Ivdep) {
01466 if ((ref1 != ref2) && Equiv_Memory(addr1,addr2)) bad_ivdep = TRUE;
01467 if (DEP_IsDistance(tmp_dep)&&DEP_Distance(tmp_dep)) bad_ivdep=TRUE;
01468 neg = pos = NULL;
01469 } else {
01470 if (DEP_IsDistance(tmp_dep)&&DEP_Distance(tmp_dep)) bad_ivdep=TRUE;
01471 if (!neg || (DEP_Direction(*neg) == DIR_POS)) {
01472 neg = NULL;
01473 } else {
01474 *neg = DEP_SetDistance(0);
01475 }
01476 if (!pos || (DEP_Direction(*pos) == DIR_POS)) {
01477 pos = NULL;
01478 } else {
01479 *pos = DEP_SetDistance(0);
01480 }
01481 }
01482 }
01483 if (bad_ivdep) {
01484 char error[120];
01485 sprintf(error,
01486 "IVDEP where there is an obvious dependence to ref on line %d. Dependence ignored.",
01487 Srcpos_To_Line(Find_Line(ref2)));
01488 ErrMsgSrcpos(EC_LNO_Generic,Find_Line(ref1),error);
01489 }
01490
01491 if (pos) {
01492 if (!Add_Edge(v1, v2,*pos)) {
01493 MEM_POOL_Pop(&DEP_local_pool);
01494 return(FALSE);
01495 }
01496 }
01497 if (neg && (ref2 != ref1)) {
01498 if (!Add_Edge(v2, v1,*neg)) {
01499 MEM_POOL_Pop(&DEP_local_pool);
01500 return(FALSE);
01501 }
01502 }
01503 }
01504 }
01505 MEM_POOL_Pop(&DEP_local_pool);
01506 }
01507 return(TRUE);
01508 }
01509
01510
01511
01512 BOOL ARRAY_DIRECTED_GRAPH16::Add_Edge_Stars(WN *ls1, const DOLOOP_STACK *s1,
01513 WN *ls2, const DOLOOP_STACK *s2,
01514 BOOL s1_lex_before_s2,
01515 BOOL pos_only)
01516 {
01517 Is_True(OPCODE_is_load(WN_opcode(ls1)) || OPCODE_is_store(WN_opcode(ls1))
01518 || OPCODE_is_call(WN_opcode(ls1)),
01519 ("bad ls1 in Add_Edge_Stars\n"));
01520 Is_True(OPCODE_is_load(WN_opcode(ls2)) || OPCODE_is_store(WN_opcode(ls2))
01521 || OPCODE_is_call(WN_opcode(ls2)),
01522 ("bad ls2 in Add_Edge_Stars\n"));
01523 UINT8 common_nest;
01524 if (_type == DEPV_ARRAY_ARRAY_GRAPH) {
01525 common_nest = Common_Nest(s1,s2);
01526 } else {
01527 Is_True(s1->Elements() == s2->Elements(),
01528 ("Add_Edge called on a DEP graph with refs not in the same inner loop"));
01529 common_nest = s1->Elements();
01530 }
01531 UINT8 num_bad = Num_Bad(s1);
01532 if (num_bad < common_nest) {
01533 MEM_POOL_Push(&DEP_local_pool);
01534
01535 INT dv_dim;
01536 if (_type == DEPV_ARRAY_ARRAY_GRAPH) {
01537 dv_dim = common_nest-num_bad;
01538 } else {
01539 dv_dim = 1;
01540 }
01541
01542 DEPV_ARRAY *dv_array = Create_DEPV_ARRAY(1, dv_dim, common_nest-dv_dim,
01543 &DEP_local_pool);
01544 for (INT ii = 0; ii < dv_dim; ii++)
01545 DEPV_Dep(dv_array->Depv(0), ii) = DEP_SetDirection(DIR_STAR);
01546 DEPV_LIST *tmp = CXX_NEW(DEPV_LIST(dv_array, &DEP_local_pool),
01547 &DEP_local_pool);
01548
01549 VINDEX16 v1 = Get_Vertex(ls1);
01550 VINDEX16 v2 = Get_Vertex(ls2);
01551 if (v1 == 0 || v2 == 0)
01552 return FALSE;
01553 if (_type == DEPV_ARRAY_ARRAY_GRAPH) {
01554 DEPV_LIST *pos = CXX_NEW(DEPV_LIST(tmp->Num_Dim(),tmp->Num_Unused_Dim(),
01555 &DEP_local_pool), &DEP_local_pool);
01556 DEPV_LIST *neg = CXX_NEW(DEPV_LIST(tmp->Num_Dim(),tmp->Num_Unused_Dim(),
01557 &DEP_local_pool),&DEP_local_pool);
01558 if (ls1 == ls2) {
01559 tmp->Lex_Pos_Decompose(&DEP_local_pool,pos,neg,FALSE,FALSE);
01560 } else if (s1_lex_before_s2) {
01561 tmp->Lex_Pos_Decompose(&DEP_local_pool,pos,neg,TRUE,FALSE);
01562 } else {
01563 tmp->Lex_Pos_Decompose(&DEP_local_pool,pos,neg,FALSE,TRUE);
01564 }
01565
01566 if (!pos->Is_Empty()) {
01567 DEPV_ARRAY *array = Create_DEPV_ARRAY(pos,_pool);
01568 if (!Add_Edge(v1, v2,array)) {
01569 MEM_POOL_Pop(&DEP_local_pool);
01570 return(FALSE);
01571 }
01572 }
01573 if (!pos_only && !neg->Is_Empty() && (ls2 != ls1)) {
01574 DEPV_ARRAY *array = Create_DEPV_ARRAY(neg,_pool);
01575 if (!Add_Edge(v2, v1,array)) {
01576 MEM_POOL_Pop(&DEP_local_pool);
01577 return(FALSE);
01578 }
01579 }
01580 } else {
01581 DEP tmp_dep = tmp->Convert_To_Dep();
01582 DEP *pos,*neg;
01583 if (ls1 == ls2) {
01584 DEP_Lex_Pos_Decompose(tmp_dep,&DEP_local_pool,&pos,&neg,0,0);
01585 } else if (s1_lex_before_s2) {
01586 DEP_Lex_Pos_Decompose(tmp_dep,&DEP_local_pool,&pos,&neg,TRUE,FALSE);
01587 } else {
01588 DEP_Lex_Pos_Decompose(tmp_dep,&DEP_local_pool,&pos,&neg,FALSE,TRUE);
01589 }
01590 if (pos) {
01591 if (!Add_Edge(v1, v2,*pos)) {
01592 MEM_POOL_Pop(&DEP_local_pool);
01593 return(FALSE);
01594 }
01595 }
01596 if (!pos_only && neg && (ls2 != ls1)) {
01597 if (!Add_Edge(v2, v1,*neg)) {
01598 MEM_POOL_Pop(&DEP_local_pool);
01599 return(FALSE);
01600 }
01601 }
01602 }
01603 MEM_POOL_Pop(&DEP_local_pool);
01604 }
01605 return(TRUE);
01606 }
01607
01608
01609 BOOL ARRAY_DIRECTED_GRAPH16::Add_Edge_Equals(WN *ls1, const DOLOOP_STACK *s1,
01610 WN *ls2, const DOLOOP_STACK *s2)
01611 {
01612 Is_True(OPCODE_is_load(WN_opcode(ls1)) || OPCODE_is_store(WN_opcode(ls1))
01613 || OPCODE_is_call(WN_opcode(ls1)),
01614 ("bad ls1 in Add_Edge_Equals\n"));
01615 Is_True(OPCODE_is_load(WN_opcode(ls2)) || OPCODE_is_store(WN_opcode(ls2))
01616 || OPCODE_is_call(WN_opcode(ls2)),
01617 ("bad ls2 in Add_Edge_Equals\n"));
01618 UINT8 common_nest;
01619 if (_type == DEPV_ARRAY_ARRAY_GRAPH) {
01620 common_nest = Common_Nest(s1,s2);
01621 } else {
01622 Is_True(s1->Elements() == s2->Elements(),
01623 ("Add_Edge called on a DEP graph with refs not in the same inner loop"));
01624 common_nest = s1->Elements();
01625 }
01626 UINT8 num_bad = Num_Bad(s1);
01627 if (num_bad < common_nest) {
01628 MEM_POOL_Push(&DEP_local_pool);
01629
01630 INT dv_dim;
01631 if (_type == DEPV_ARRAY_ARRAY_GRAPH) {
01632 dv_dim = common_nest-num_bad;
01633 } else {
01634 dv_dim = 1;
01635 }
01636
01637 VINDEX16 v1 = Get_Vertex(ls1);
01638 VINDEX16 v2 = Get_Vertex(ls2);
01639 if (v1 == 0 || v2 == 0)
01640 return FALSE;
01641 if (_type == DEPV_ARRAY_ARRAY_GRAPH) {
01642 DEPV_ARRAY *dv_array = Create_DEPV_ARRAY(1, dv_dim, common_nest-dv_dim,
01643 _pool);
01644 for (INT ii = 0; ii < dv_dim; ii++) {
01645 DEPV_Dep(dv_array->Depv(0), ii) = DEP_SetDirection(DIR_EQ);
01646 }
01647 if (!Add_Edge(v1, v2,dv_array)) {
01648 MEM_POOL_Pop(&DEP_local_pool);
01649 return(FALSE);
01650 }
01651 } else {
01652 DEP dep = DEP_SetDistance(0);
01653 if (!Add_Edge(v1, v2,dep)) {
01654 MEM_POOL_Pop(&DEP_local_pool);
01655 return(FALSE);
01656 }
01657 }
01658 }
01659 return(TRUE);
01660 }
01661
01662
01663
01664
01665
01666
01667
01668
01669
01670
01671
01672
01673
01674
01675
01676
01677
01678
01679
01680 INT ARRAY_DIRECTED_GRAPH16::Gather_References(WN *wn, REF_LIST_STACK *writes,
01681 REF_LIST_STACK *reads, DOLOOP_STACK *stack,
01682 SCALAR_STACK *scalar_writes, SCALAR_STACK *scalar_reads,
01683 CALL_STACK *calls, BOOL skip_bad)
01684 {
01685 WN *kid;
01686
01687 if (OPCODE_is_stmt(WN_opcode(wn)) || OPCODE_is_scf(WN_opcode(wn))) {
01688 statement_number++;
01689 }
01690
01691 if (WN_opcode(wn) == OPC_BLOCK) {
01692 kid = WN_first (wn);
01693 while (kid) {
01694 if (!Gather_References(kid,writes,reads,stack,scalar_writes,
01695 scalar_reads,calls,skip_bad)) return(0);
01696 kid = WN_next(kid);
01697 }
01698 return (1);
01699 }
01700
01701 if (WN_opcode(wn) == OPC_DO_LOOP) {
01702 if (!skip_bad || Do_Loop_Is_Good(wn)) {
01703 DO_LOOP_INFO *dli = (DO_LOOP_INFO *) WN_MAP_Get(LNO_Info_Map,wn);
01704 dli->Has_Bad_Mem = FALSE;
01705 WN *body = WN_do_body(wn);
01706 for (INT kidno=0; kidno<WN_kid_count(wn); kidno++) {
01707 kid = WN_kid(wn,kidno);
01708 if (kid != body) {
01709 if (!Gather_References(kid,writes,reads,stack,
01710 scalar_writes,scalar_reads,calls,skip_bad)) {
01711 return(0);
01712 }
01713 }
01714 }
01715 stack->Push(wn);
01716 if (!Gather_References(body,writes,reads,stack,scalar_writes,
01717 scalar_reads,calls,skip_bad)) {
01718 return(0);
01719 }
01720 stack->Pop();
01721 dli = (DO_LOOP_INFO *) WN_MAP_Get(LNO_Info_Map,wn);
01722 if (dli->Has_Bad_Mem && _type==DEPV_ARRAY_ARRAY_GRAPH) {
01723 LNO_Erase_Vertices_In_Loop (wn,this);
01724 }
01725 }
01726 } else if (OPCODE_is_call(WN_opcode(wn))) {
01727 VINDEX16 vindex = Get_Vertex(wn);
01728 if (!vindex) {
01729 vindex = Add_Vertex(wn);
01730 }
01731 if (!vindex) {
01732 DevWarn("Out of space for vertex?");
01733 Set_Bad_Mem(wn);
01734 return 0;
01735 }
01736 DOLOOP_STACK *s = Copy_Doloop_Stack(stack,&LNO_local_pool);
01737 calls->Push(wn,statement_number,s,
01738 Do_Loop_Is_Concurrent_Call(s->Top_nth(0)));
01739 } else if (WN_opcode(wn) == OPC_IO) {
01740 Set_Bad_Mem(wn);
01741 return 1;
01742 } else if (OPCODE_is_load(WN_opcode(wn))) {
01743 OPCODE opcode = WN_opcode(wn);
01744 if (OPCODE_has_1ty(opcode) && TY_is_volatile(WN_ty(wn))) {
01745 Set_Bad_Mem(wn);
01746 return 1;
01747 } else if (OPCODE_has_2ty(opcode)&&(TY_is_volatile(WN_ty(wn)) ||
01748 TY_is_volatile(WN_load_addr_ty(wn)))) {
01749 Set_Bad_Mem(wn);
01750 return 1;
01751 }
01752
01753 if ((WN_kid_count(wn) == 1)) {
01754
01755 if (stack->Elements()>0) {
01756 WN *array = WN_kid0(wn);
01757 if (WN_operator(array) == OPR_ADD) {
01758
01759 OPERATOR kid0 = WN_operator(WN_kid0(array));
01760 OPERATOR kid1 = WN_operator(WN_kid1(array));
01761 if ((kid0 == OPR_ARRAY) && (kid1 == OPR_INTCONST)) {
01762 array = WN_kid0(array);
01763 } else if ((kid1 == OPR_ARRAY) && (kid0 == OPR_INTCONST)) {
01764 array = WN_kid1(array);
01765 } else {
01766 Set_Bad_Mem(wn);
01767 return 1;
01768 }
01769 } else if (WN_operator(array) != OPR_ARRAY) {
01770 Set_Bad_Mem(wn);
01771 return 1;
01772 }
01773
01774
01775 DOLOOP_STACK *s = Copy_Doloop_Stack(stack,&LNO_local_pool);
01776
01777 VINDEX16 vindex = Get_Vertex(wn);
01778 if (!vindex) {
01779 vindex = Add_Vertex(wn);
01780 }
01781 if (!vindex) {
01782 DevWarn("Out of space for vertex?");
01783 if (WN_operator(wn) != OPR_LDID)
01784 Set_Bad_Mem(wn);
01785 return 0;
01786 }
01787 WN *base = WN_array_base(array);
01788 ST *st_base=Get_ST_Base(base);
01789 INT i;
01790 for (i=0;i<reads->Elements()&&
01791 !(reads->Bottom_nth(i)->ST_Base==st_base); i++);
01792 if (i==reads->Elements()) {
01793 REFERENCE_LIST *rl =
01794 CXX_NEW(REFERENCE_LIST(st_base, wn),&LNO_local_pool);
01795 reads->Push(rl);
01796 }
01797 reads->Bottom_nth(i)->Append(CXX_NEW(REFERENCE_NODE(wn,s,
01798 statement_number), &LNO_local_pool));
01799 } else {
01800 if (WN_operator(wn) != OPR_LDID)
01801 Set_Bad_Mem(wn);
01802 VINDEX16 vindex = Get_Vertex(wn);
01803 if (vindex)
01804 Delete_Vertex(vindex);
01805 }
01806 } else if (WN_operator(wn) == OPR_LDID) {
01807 if (ST_class(WN_st(wn)) != CLASS_PREG && stack->Elements()>0) {
01808 scalar_reads->Add_Scalar(wn,statement_number);
01809 }
01810 } else {
01811 Set_Bad_Mem(wn);
01812 }
01813 } else if (OPCODE_is_store(WN_opcode(wn))) {
01814 TY_IDX ty = WN_ty(wn);
01815 if (TY_is_volatile(ty)) {
01816 Set_Bad_Mem(wn);
01817 return 1;
01818 } else if ((WN_operator(wn) != OPR_STID) &&
01819 TY_is_volatile(TY_pointed(WN_ty(wn)))) {
01820 Set_Bad_Mem(wn);
01821 return 1;
01822 }
01823
01824
01825 if (WN_kid_count(wn) == 2) {
01826 DOLOOP_STACK *s = Copy_Doloop_Stack(stack,&LNO_local_pool);
01827 VINDEX16 vindex = Get_Vertex(wn);
01828 if (stack->Elements() > 0) {
01829 WN *array = WN_kid1(wn);
01830 if (WN_operator(array) == OPR_ADD) {
01831
01832 OPERATOR kid0 = WN_operator(WN_kid0(array));
01833 OPERATOR kid1 = WN_operator(WN_kid1(array));
01834 if ((kid0 == OPR_ARRAY) && (kid1 == OPR_INTCONST)) {
01835 array = WN_kid0(array);
01836 } else if ((kid1 == OPR_ARRAY) && (kid0 == OPR_INTCONST)) {
01837 array = WN_kid1(array);
01838 } else {
01839 Set_Bad_Mem(wn);
01840 return 1;
01841 }
01842 } else if (WN_operator(array) != OPR_ARRAY) {
01843 Set_Bad_Mem(wn);
01844 return 1;
01845 }
01846
01847
01848 if (!vindex) {
01849 vindex = Add_Vertex(wn);
01850 }
01851 if (!vindex) {
01852 DevWarn("Out of space for vertex?");
01853 if (WN_operator(wn) != OPR_STID)
01854 Set_Bad_Mem(wn);
01855 return 0;
01856 }
01857
01858 WN *base = WN_array_base(array);
01859 ST *st_base=Get_ST_Base(base);
01860 INT i;
01861 for (i=0;i<writes->Elements() &&
01862 !(writes->Bottom_nth(i)->ST_Base==st_base); i++);
01863 if (i==writes->Elements()) {
01864 REFERENCE_LIST *rl =
01865 CXX_NEW(REFERENCE_LIST(st_base,wn),&LNO_local_pool);
01866 writes->Push(rl);
01867 }
01868 writes->Bottom_nth(i)->Append(CXX_NEW(REFERENCE_NODE(wn,s,
01869 statement_number), &LNO_local_pool));
01870 } else {
01871 if (WN_operator(wn) != OPR_STID)
01872 Set_Bad_Mem(wn);
01873 VINDEX16 vindex = Get_Vertex(wn);
01874 if (vindex)
01875 Delete_Vertex(vindex);
01876 }
01877 } else if (WN_operator(wn) == OPR_STID) {
01878 if (ST_class(WN_st(wn)) != CLASS_PREG && stack->Elements()>0) {
01879 scalar_writes->Add_Scalar(wn,statement_number);
01880 }
01881 } else {
01882 Set_Bad_Mem(wn);
01883 }
01884 } else if (WN_operator(wn) == OPR_ARRAY) {
01885 WN *ancestor = LWN_Get_Parent(wn);
01886 while (ancestor && !OPCODE_is_store(WN_opcode(ancestor)) &&
01887 !OPCODE_is_load(WN_opcode(ancestor))) {
01888 if (WN_operator(ancestor) == OPR_PARM) {
01889 if (stack->Elements() > 0
01890 && !Do_Loop_Is_Concurrent_Call(stack->Top_nth(0))
01891 && !Has_Call_Info(LWN_Get_Parent(ancestor))) {
01892 Set_Bad_Mem(wn);
01893 }
01894 }
01895 ancestor = LWN_Get_Parent(ancestor);
01896 }
01897 }
01898
01899
01900 if (WN_opcode(wn) != OPC_DO_LOOP) {
01901 for (INT kidno=0; kidno<WN_kid_count(wn); kidno++) {
01902 kid = WN_kid(wn,kidno);
01903 if (!Gather_References(kid,writes,reads,stack,
01904 scalar_writes,scalar_reads,calls,skip_bad)) {
01905 return(0);
01906 }
01907 }
01908 }
01909 return(1);
01910 }
01911
01912
01913
01914 static WN *Get_Do(WN *wn)
01915 {
01916 while (wn && WN_opcode(wn) != OPC_DO_LOOP) {
01917 wn = LWN_Get_Parent(wn);
01918 }
01919 FmtAssert(wn, ("Missing enclosing do loop"));
01920 return (wn);
01921 }
01922
01923
01924
01925 INT ARRAY_DIRECTED_GRAPH16::Build(ARRAY_DIRECTED_GRAPH16 *da_graph)
01926 {
01927 MEM_POOL_Push(&LNO_local_pool);
01928 Is_True((_type==DEP_ARRAY_GRAPH) &&
01929 (da_graph->_type==DEPV_ARRAY_ARRAY_GRAPH),
01930 ("Build called on wrong types of graph"));
01931
01932
01933
01934
01935
01936
01937 for (VINDEX16 v=da_graph->Get_Vertex(); v; v=da_graph->Get_Next_Vertex(v)) {
01938 WN *wn = da_graph->Get_Wn(v);
01939 WN *do_wn = Get_Do(wn);
01940 if (Do_Loop_Is_Inner(do_wn) && !Do_Loop_Has_Gotos(do_wn)) {
01941 OPERATOR oper = WN_operator(wn);
01942 if ((oper != OPR_LDID) && (oper != OPR_STID) && (oper != OPR_CALL)) {
01943 if (!Add_Vertex(da_graph->Get_Wn(v))) {
01944 return(0);
01945 }
01946 } else {
01947 Set_Bad_Mem(wn);
01948 }
01949 }
01950 }
01951
01952
01953 for (VINDEX16 source_v=da_graph->Get_Vertex(); source_v;
01954 source_v=da_graph->Get_Next_Vertex(source_v)) {
01955 EINDEX16 e = da_graph->_v[source_v].Get_Out_Edge();
01956 WN *source_wn = da_graph->Get_Wn(source_v);
01957 WN *inner_do = Get_Do(source_wn);
01958 if (Do_Loop_Is_Inner(inner_do) && !Do_Loop_Has_Gotos(inner_do)) {
01959 OPERATOR source_oper = WN_operator(source_wn);
01960 if ((source_oper != OPR_LDID)&&(source_oper != OPR_STID)
01961 && (source_oper != OPR_CALL)) {
01962 while (e) {
01963 DEPV_ARRAY *da = da_graph->_e[e].Depv_Array;
01964
01965 VINDEX16 sink_v = da_graph->_e[e].Get_Sink();
01966 WN *sink_wn = da_graph->Get_Wn(sink_v);
01967 WN *inner_do2 = Get_Do(sink_wn);
01968 if (inner_do == inner_do2) {
01969 OPERATOR sink_oper = WN_operator(sink_wn);
01970 if ((sink_oper != OPR_LDID) && (sink_oper != OPR_STID)
01971 && (sink_oper != OPR_CALL)) {
01972
01973
01974 DEPV_ARRAY *da2=NULL;
01975 DEP *dep=NULL;
01976 DEP *dep2 = NULL;
01977
01978 EINDEX16 e2 = da_graph->Get_Edge(sink_v,source_v);
01979 if (e2 && (e < e2)) {
01980 dep = da->Shorten_To_Dep(&LNO_local_pool);
01981 da2 = da_graph->_e[e2].Depv_Array;
01982 dep2 = da2->Shorten_To_Dep(&LNO_local_pool);
01983 } else if (e == e2) {
01984 dep = da->Shorten_To_Dep(&LNO_local_pool);
01985 } else if (!e2) {
01986 dep = da->Shorten_To_Dep(&LNO_local_pool);
01987 }
01988 VINDEX16 source_v2 = Get_Vertex(source_wn);
01989
01990 WN *sink_wn = da_graph->Get_Wn(sink_v);
01991 VINDEX16 sink_v2 = Get_Vertex(sink_wn);
01992 if (dep && !Add_Edge(source_v2,sink_v2,*dep)) {
01993 MEM_POOL_Pop(&LNO_local_pool);
01994 return(0);
01995 }
01996 if (dep2 && !Add_Edge(sink_v2,source_v2,*dep2)) {
01997 MEM_POOL_Pop(&LNO_local_pool);
01998 return(0);
01999 }
02000 }
02001 }
02002 e = da_graph->_e[e].Get_Next_Out_Edge();
02003 }
02004 }
02005 }
02006 }
02007 MEM_POOL_Pop(&LNO_local_pool);
02008 Add_Must();
02009 return(1);
02010 }
02011
02012
02013 INT ARRAY_DIRECTED_GRAPH16::Add_Deps_To_Copy_Block(WN *orig, WN *copy,
02014 BOOL keep_internal_edge)
02015 {
02016 Is_True(_type==DEPV_ARRAY_ARRAY_GRAPH,
02017 ("Add_Deps_To_Copy_Block called on a non-DEPV_ARRAY graph"));
02018 INT result;
02019 MEM_POOL_Push(&LNO_local_pool);
02020 {
02021
02022
02023
02024 HASH_TABLE<VINDEX16,VINDEX16> hash_table(MIN(Get_Vertex_Count(),512),
02025 &LNO_local_pool);
02026
02027 result = Add_Deps_To_Copy_Block_V(orig, copy,&hash_table);
02028 if (result)
02029 result=Add_Deps_To_Copy_Block_E(orig,copy,&hash_table,keep_internal_edge);
02030
02031 }
02032 MEM_POOL_Pop(&LNO_local_pool);
02033 return result;
02034 }
02035
02036
02037
02038
02039
02040 INT ARRAY_DIRECTED_GRAPH16::Add_Deps_To_Copy_Block_V(WN *orig, WN *copy,
02041 HASH_TABLE<VINDEX16,VINDEX16> *hash_table)
02042 {
02043 if (orig) {
02044 if (OPCODE_is_load(WN_opcode(orig)) ||
02045 OPCODE_is_store(WN_opcode(orig)) ||
02046 OPCODE_is_call(WN_opcode(orig))) {
02047 VINDEX16 origv = Get_Vertex(orig);
02048 if (origv) {
02049 VINDEX16 newv = Add_Vertex(copy);
02050 if (!newv) return(0);
02051 hash_table->Enter(origv, newv);
02052 }
02053 }
02054
02055 if (WN_opcode(orig) == OPC_BLOCK) {
02056 WN *orig_kid = WN_first (orig);
02057 WN *copy_kid = WN_first (copy);
02058 while (orig_kid) {
02059 if (!Add_Deps_To_Copy_Block_V(orig_kid, copy_kid,hash_table)) {
02060 return 0;
02061 }
02062 orig_kid = WN_next(orig_kid);
02063 copy_kid = WN_next(copy_kid);
02064 }
02065 } else {
02066 for (INT kidno=0; kidno<WN_kid_count(orig); kidno++) {
02067 if (!Add_Deps_To_Copy_Block_V(WN_kid(orig,kidno), WN_kid(copy,kidno),
02068 hash_table)) {
02069 return 0;
02070 }
02071 }
02072 }
02073 }
02074 return 1;
02075 }
02076
02077
02078
02079
02080
02081
02082
02083
02084
02085
02086
02087 INT ARRAY_DIRECTED_GRAPH16::Add_Deps_To_Copy_Block_E(WN *orig, WN *copy,
02088 HASH_TABLE<VINDEX16,VINDEX16> *hash_table, BOOL keep_internal_edge)
02089 {
02090 VINDEX16 newv, new_sinkv;
02091
02092 if (orig) {
02093 if (OPCODE_is_load(WN_opcode(orig)) ||
02094 OPCODE_is_store(WN_opcode(orig)) ||
02095 OPCODE_is_call(WN_opcode(orig))) {
02096 VINDEX16 origv = Get_Vertex(orig);
02097
02098 if (origv) {
02099 newv = hash_table->Find(origv);
02100
02101 EINDEX16 edge = Get_Out_Edge(origv);
02102 while (edge) {
02103 VINDEX16 orig_sinkv = Get_Sink(edge);
02104 VINDEX16 hash_element = hash_table->Find( orig_sinkv);
02105 if (hash_element) {
02106 if (keep_internal_edge) {
02107
02108 new_sinkv = (VINDEX16) (UINT) hash_element;
02109 if (!Add_Edge(newv,new_sinkv,
02110 Create_DEPV_ARRAY(Depv_Array(edge),_pool))) {
02111 return 0;
02112 }
02113 }
02114 } else {
02115 new_sinkv = orig_sinkv;
02116 if (!Add_Edge(newv,new_sinkv,
02117 Create_DEPV_ARRAY(Depv_Array(edge),_pool))) {
02118 return 0;
02119 }
02120 }
02121 edge = Get_Next_Out_Edge(edge);
02122 }
02123
02124 edge = Get_In_Edge(origv);
02125 while (edge) {
02126 VINDEX16 orig_sourcev = Get_Source(edge);
02127 VINDEX16 hash_element = hash_table->Find(orig_sourcev);
02128 if (!hash_element) {
02129 if (!Add_Edge(orig_sourcev,newv,
02130 Create_DEPV_ARRAY(Depv_Array(edge),_pool))) {
02131 return 0;
02132 }
02133 }
02134 edge = Get_Next_In_Edge(edge);
02135 }
02136 }
02137 }
02138
02139 if (WN_opcode(orig) == OPC_BLOCK) {
02140 WN *orig_kid = WN_first (orig);
02141 WN *copy_kid = WN_first (copy);
02142 while (orig_kid) {
02143 if (!Add_Deps_To_Copy_Block_E(orig_kid,copy_kid,
02144 hash_table, keep_internal_edge)) {
02145 return 0;
02146 }
02147 orig_kid = WN_next(orig_kid);
02148 copy_kid = WN_next(copy_kid);
02149 }
02150 } else {
02151 for (INT kidno=0; kidno<WN_kid_count(orig); kidno++) {
02152 if (!Add_Deps_To_Copy_Block_E(WN_kid(orig,kidno), WN_kid(copy,kidno),
02153 hash_table, keep_internal_edge)) {
02154 return 0;
02155 }
02156 }
02157 }
02158 }
02159 return 1;
02160 }
02161
02162
02163
02164 static DOLOOP_STACK *Copy_Doloop_Stack(DOLOOP_STACK *orig,MEM_POOL *pool)
02165 {
02166 DOLOOP_STACK *copy = CXX_NEW(DOLOOP_STACK(pool),pool);
02167 INT elements = orig->Elements();
02168 for (INT i=0; i<elements; i++) {
02169 copy->Push(orig->Bottom_nth(i));
02170 }
02171 return(copy);
02172 }
02173
02174
02175 static INT Common_Nest(const DOLOOP_STACK *s1, const DOLOOP_STACK *s2)
02176 {
02177 INT i;
02178 for (i=0; i<MIN(s1->Elements(),s2->Elements()); i++) {
02179 if (s1->Bottom_nth(i) != s2->Bottom_nth(i)) return(i);
02180 }
02181 return(i);
02182 }
02183
02184
02185 static INT Num_Bad(const DOLOOP_STACK *s1)
02186 {
02187 INT i;
02188 for (i=0; i<s1->Elements() && !Do_Loop_Is_Good(s1->Bottom_nth(i)); i++);
02189 return(i);
02190 }
02191
02192 static INT lex_count;
02193
02194
02195
02196
02197
02198
02199
02200
02201
02202
02203
02204
02205
02206 INT ARRAY_DIRECTED_GRAPH16::Unrolled_Dependences_Update(
02207 WN** bodies, UINT u, UINT loopno)
02208 {
02209 Is_True(_type==DEPV_ARRAY_ARRAY_GRAPH,
02210 ("Unrolled_Dependences_Update called on a non-DEPV_ARRAY graph"));
02211 INT result;
02212 MEM_POOL_Push(&LNO_local_pool);
02213
02214
02215
02216
02217
02218
02219 typedef HASH_TABLE<VINDEX16,VINDEX16P_LEX_COUNT *> HTABLE_TYPE;
02220 HTABLE_TYPE *hash_table =
02221 CXX_NEW(HTABLE_TYPE(MIN(Get_Vertex_Count(),512),&LNO_local_pool),
02222 &LNO_local_pool);
02223
02224
02225 VINDEX16_STACK *orig_vertices =
02226 CXX_NEW(VINDEX16_STACK(&LNO_local_pool),&LNO_local_pool);
02227
02228 lex_count=0;
02229 result = Unrolled_Dependences_Update_V(bodies,u,hash_table,orig_vertices);
02230 if (!result) {
02231 CXX_DELETE(hash_table, &LNO_local_pool);
02232 MEM_POOL_Pop(&LNO_local_pool);
02233 return(0);
02234 }
02235
02236 result = Unrolled_Dependences_Update_E(u,loopno,hash_table,orig_vertices);
02237
02238 CXX_DELETE(hash_table, &LNO_local_pool);
02239 CXX_DELETE(orig_vertices, &LNO_local_pool);
02240 MEM_POOL_Pop(&LNO_local_pool);
02241 return(result);
02242 }
02243
02244
02245
02246
02247
02248 INT ARRAY_DIRECTED_GRAPH16::Unrolled_Dependences_Update_V(WN **bodies,
02249 UINT u, HASH_TABLE<VINDEX16,VINDEX16P_LEX_COUNT *> *hash_table,
02250 VINDEX16_STACK *orig_vertices)
02251 {
02252 if (bodies[0]) {
02253
02254 if (WN_opcode(bodies[0]) == OPC_BLOCK) {
02255 WN **new_bodies = CXX_NEW_ARRAY(WN *,u,&LNO_local_pool);
02256 for (INT i=0; i<u; i++) {
02257 new_bodies[i] = WN_first(bodies[i]);
02258 }
02259 while (new_bodies[0]) {
02260 if (!Unrolled_Dependences_Update_V(new_bodies, u,hash_table,
02261 orig_vertices)) {
02262 return 0;
02263 }
02264 for (INT i=0; i<u; i++) {
02265 new_bodies[i] = WN_next(new_bodies[i]);
02266 }
02267 }
02268 } else if (WN_kid_count(bodies[0])) {
02269 WN **new_bodies = CXX_NEW_ARRAY(WN *,u,&LNO_local_pool);
02270 for (INT kidno=0; kidno<WN_kid_count(bodies[0]); kidno++) {
02271 for (INT i=0; i<u; i++) {
02272 new_bodies[i] = WN_kid(bodies[i],kidno);
02273 }
02274 if (!Unrolled_Dependences_Update_V(new_bodies, u,hash_table,
02275 orig_vertices)) {
02276 return 0;
02277 }
02278 }
02279 }
02280
02281 if (OPCODE_is_load(WN_opcode(bodies[0])) ||
02282 OPCODE_is_store(WN_opcode(bodies[0])) ||
02283 OPCODE_is_call(WN_opcode(bodies[0]))) {
02284 VINDEX16 origv = Get_Vertex(bodies[0]);
02285 if (origv) {
02286 orig_vertices->Push(origv);
02287 VINDEX16 *newv = CXX_NEW_ARRAY(VINDEX16,u,&LNO_local_pool);
02288 newv[0] = origv;
02289 for (INT i=1; i<u; i++) {
02290 newv[i] = Add_Vertex(bodies[i]);
02291 if (!newv[i]) return(0);
02292 }
02293 VINDEX16P_LEX_COUNT *vlp = CXX_NEW(VINDEX16P_LEX_COUNT(newv,lex_count),
02294 &LNO_local_pool);
02295 hash_table->Enter(origv,vlp);
02296 }
02297 lex_count++;
02298 }
02299 }
02300 return 1;
02301 }
02302
02303
02304 class VERTEX_PAIR
02305 {
02306 public:
02307 VINDEX16 _v1;
02308 VINDEX16 _v2;
02309 VERTEX_PAIR(VINDEX16 v1, VINDEX16 v2) { _v1=v1; _v2=v2; };
02310 };
02311
02312 struct VERTEX_PAIR_HASH
02313 {
02314 INT operator() ( VERTEX_PAIR vp) const {
02315 return vp._v1 + 64*1024*vp._v2;
02316 }
02317 };
02318
02319 struct VERTEX_PAIR_EQ
02320 {
02321 BOOL operator() ( VERTEX_PAIR vp1, VERTEX_PAIR vp2) const
02322 { return vp1._v1 == vp2._v1 && vp1._v2 == vp2._v2; }
02323 };
02324
02325 typedef USER_HASH_TABLE<VERTEX_PAIR,BOOL,VERTEX_PAIR_HASH,VERTEX_PAIR_EQ> PAIR_TABLE;
02326
02327
02328
02329
02330
02331
02332
02333 INT ARRAY_DIRECTED_GRAPH16::Unrolled_Dependences_Update_E(UINT u,
02334 UINT loopno, HASH_TABLE<VINDEX16,VINDEX16P_LEX_COUNT *> *hash_table,
02335 VINDEX16_STACK *orig_vertices)
02336 {
02337
02338 INT v;
02339 for (v=0; v<orig_vertices->Elements(); v++) {
02340 VINDEX16 origv = orig_vertices->Bottom_nth(v);
02341
02342 VINDEX16 *newv = hash_table->Find(origv)->_vp;
02343
02344
02345 EINDEX16 edge = Get_Out_Edge(origv);
02346 while (edge) {
02347 VINDEX16 orig_sinkv = Get_Sink(edge);
02348 VINDEX16P_LEX_COUNT *hash_element = hash_table->Find(orig_sinkv);
02349 if (!hash_element) {
02350 for (INT i=1; i<u; i++) {
02351 if (!Add_Edge(newv[i],orig_sinkv,
02352 Create_DEPV_ARRAY(Depv_Array(edge),_pool))) {
02353 return 0;
02354 }
02355 }
02356 }
02357 edge = Get_Next_Out_Edge(edge);
02358 }
02359 edge = Get_In_Edge(origv);
02360 while (edge) {
02361 VINDEX16 orig_sourcev = Get_Source(edge);
02362 VINDEX16P_LEX_COUNT *hash_element = hash_table->Find(orig_sourcev);
02363 if (!hash_element) {
02364 for (INT i=1; i<u; i++) {
02365 if (!Add_Edge(orig_sourcev,newv[i],
02366 Create_DEPV_ARRAY(Depv_Array(edge),_pool))) {
02367 return 0;
02368 }
02369 }
02370 }
02371 edge = Get_Next_In_Edge(edge);
02372 }
02373 }
02374
02375
02376
02377
02378 PAIR_TABLE *pair_table = CXX_NEW(PAIR_TABLE(200,&LNO_local_pool),
02379 &LNO_local_pool);
02380 for (v=0; v<orig_vertices->Elements(); v++) {
02381 VINDEX16 origv = orig_vertices->Bottom_nth(v);
02382 VINDEX16P_LEX_COUNT *vlc = hash_table->Find(origv);
02383 VINDEX16 *newv = vlc->_vp;
02384 INT lex_count = vlc->_lex_count;
02385
02386 EINDEX16 edge = Get_Out_Edge(origv);
02387 while (edge) {
02388 EINDEX16 next_out = Get_Next_Out_Edge(edge);
02389 VINDEX16 orig_sinkv = Get_Sink(edge);
02390 VINDEX16P_LEX_COUNT *vlc_sink = hash_table->Find(orig_sinkv);
02391 if (vlc_sink) {
02392 VINDEX16 *new_sinkv = vlc_sink->_vp;
02393 INT sink_lex_count = vlc_sink->_lex_count;
02394
02395
02396 if ((origv <= orig_sinkv) ||
02397 (!Get_Edge(orig_sinkv,origv) &&
02398 !pair_table->Find(VERTEX_PAIR(origv,orig_sinkv)))) {
02399 if (origv < orig_sinkv) {
02400 pair_table->Enter(VERTEX_PAIR(orig_sinkv,origv),1);
02401 }
02402 if (!Unrolled_Dependences_Update_E(
02403 newv,new_sinkv,edge,Get_Edge(orig_sinkv,origv),u,loopno,
02404 lex_count,sink_lex_count)) {
02405 return 0;
02406 }
02407 }
02408 }
02409 edge = next_out;
02410 }
02411 }
02412
02413 return(1);
02414 }
02415
02416
02417
02418
02419
02420
02421
02422
02423 INT ARRAY_DIRECTED_GRAPH16::Unrolled_Dependences_Update_E(VINDEX16 *sources,
02424 VINDEX16 *sinks, EINDEX16 fedge, EINDEX16 bedge,
02425 UINT u, UINT loopno, INT lex_count, INT sink_lex_count)
02426 {
02427 DEPV_ARRAY *farray = Depv_Array(fedge);
02428 DEPV_ARRAY *barray = 0;
02429 if (bedge) barray=Depv_Array(bedge);
02430
02431 DEPV_LIST *fl = CXX_NEW(DEPV_LIST(farray,&LNO_local_pool),&LNO_local_pool);
02432 DEPV_LIST *bl;
02433 if (bedge) {
02434 bl=CXX_NEW(DEPV_LIST(barray,&LNO_local_pool),&LNO_local_pool);
02435 } else {
02436 bl=CXX_NEW(DEPV_LIST(fl->Num_Dim(),fl->Num_Unused_Dim(),&LNO_local_pool),
02437 &LNO_local_pool);
02438 }
02439 DEPV_LIST *dl = Lex_Pos_Compose(&LNO_local_pool,fl,bl);
02440
02441 if (farray == barray) {
02442 Is_True(fedge==bedge,
02443 ("same array different edge in Unrolled_Dependences_Update_E"));
02444 Delete_DEPV_ARRAY(farray,_pool);
02445 Remove_Edge(fedge);
02446 } else {
02447 Delete_DEPV_ARRAY(farray,_pool);
02448 Delete_DEPV_ARRAY(barray,_pool);
02449 Remove_Edge(fedge);
02450 if (bedge) Remove_Edge(bedge);
02451 }
02452
02453
02454
02455
02456 for (INT c1=0; c1<u; c1++) {
02457 for (INT c2=0; c2<(sources[0]==sinks[0] ? (c1+1) : u); c2++) {
02458
02459 INT diff = c1-c2;
02460 DEPV_LIST *result = CXX_NEW(DEPV_LIST(dl->Num_Dim(),dl->Num_Unused_Dim(),
02461 &LNO_local_pool), &LNO_local_pool);
02462 UINT ln_pos = loopno-dl->Num_Unused_Dim();
02463 DEPV_ITER iter(dl);
02464 for (DEPV_NODE *node=iter.First(); !iter.Is_Empty();node=iter.Next()) {
02465 DEPV *Depv = node->Depv;
02466 DEP dep = DEPV_Dep(Depv,ln_pos);
02467 if (DEP_IsDistance(dep)) {
02468 INT dist = DEP_Distance(dep);
02469 if ((abs(dist+diff) % u) == 0) {
02470 DEPV *r = DEPV_Copy(&LNO_local_pool,Depv,dl->Num_Dim());
02471 DEPV_Dep(r,ln_pos) = DEP_SetDistance((dist+diff)/u);
02472 result->Append(CXX_NEW(DEPV_NODE(r), &LNO_local_pool));
02473 }
02474 } else {
02475 DEPV *r = DEPV_Copy(&LNO_local_pool,Depv,dl->Num_Dim());
02476 if ((diff != 0) && DEP_Direction(dep) != DIR_STAR) {
02477 if (DEP_Direction(dep) == DIR_POSNEG) {
02478 DEPV_Dep(r,ln_pos) = DEP_SetDirection(DIR_STAR);
02479 } else if (DEP_Direction(dep) == DIR_POS) {
02480 if (diff < 0) DEPV_Dep(r,ln_pos) = DEP_SetDirection(DIR_POSEQ);
02481 } else if (DEP_Direction(dep) == DIR_NEG) {
02482 if (diff > 0) DEPV_Dep(r,ln_pos) = DEP_SetDirection(DIR_NEGEQ);
02483 } else if (DEP_Direction(dep) == DIR_NEGEQ) {
02484 if (diff > 0) DEPV_Dep(r,ln_pos) = DEP_SetDirection(DIR_STAR);
02485 if (diff < 0) DEPV_Dep(r,ln_pos) = DEP_SetDirection(DIR_NEG);
02486 } else if (DEP_Direction(dep) == DIR_POSEQ) {
02487 if (diff < 0) DEPV_Dep(r,ln_pos) = DEP_SetDirection(DIR_STAR);
02488 if (diff > 0) DEPV_Dep(r,ln_pos) = DEP_SetDirection(DIR_POS);
02489 }
02490 }
02491 result->Append(CXX_NEW(DEPV_NODE(r), &LNO_local_pool));
02492 }
02493 }
02494 DEPV_LIST *pos = CXX_NEW(DEPV_LIST(result->Num_Dim(),
02495 result->Num_Unused_Dim(),&LNO_local_pool), &LNO_local_pool);
02496 DEPV_LIST *neg = CXX_NEW(DEPV_LIST(result->Num_Dim(),
02497 result->Num_Unused_Dim(),&LNO_local_pool),&LNO_local_pool);
02498 if (c1 < c2) {
02499 result->Lex_Pos_Decompose(&LNO_local_pool,pos,neg,TRUE,FALSE);
02500 } else if (c2 < c1) {
02501 result->Lex_Pos_Decompose(&LNO_local_pool,pos,neg,FALSE,TRUE);
02502 } else {
02503 result->Lex_Pos_Decompose(&LNO_local_pool,pos,neg,
02504 lex_count < sink_lex_count,sink_lex_count < lex_count);
02505 }
02506 if (!pos->Is_Empty()) {
02507 DEPV_ARRAY *array = Create_DEPV_ARRAY(pos,_pool);
02508 if (!Add_Edge(sources[c1],sinks[c2],array)) {
02509 return(0);
02510 }
02511 }
02512 if ((sources[c1] != sinks[c2]) && !neg->Is_Empty()) {
02513 DEPV_ARRAY *array = Create_DEPV_ARRAY(neg,_pool);
02514 if (!Add_Edge(sinks[c2],sources[c1],array)) {
02515 return(0);
02516 }
02517 }
02518 }
02519 }
02520 return 1;
02521 }
02522
02523
02524
02525 void REFERENCE_LIST::Print(FILE *fp)
02526 {
02527 REFERENCE_ITER iter(this);
02528 REFERENCE_NODE *first = iter.First();
02529 for (REFERENCE_NODE *node=first; !iter.Is_Empty(); node = iter.Next()) {
02530 node->Print(fp);
02531 }
02532 fprintf(fp,"\n");
02533 }
02534
02535
02536
02537
02538
02539
02540
02541
02542
02543
02544
02545 void ARRAY_DIRECTED_GRAPH16::Fission_Dep_Update(WN* in_loop, UINT32 total_loops)
02546 {
02547 Is_True(_type==DEPV_ARRAY_ARRAY_GRAPH,
02548 ("Fission_Dep_Update called on a non-DEPV_ARRAY graph"));
02549
02550 UINT depth = Do_Loop_Depth(in_loop);
02551 for (INT i=0; i<total_loops; i++) {
02552 Is_True(WN_opcode(in_loop) == OPC_DO_LOOP,
02553 ("Non do loop in Fission_Dep_Update"));
02554 Fission_Dep_Update_R(WN_do_body(in_loop),in_loop,depth);
02555 in_loop = WN_next(in_loop);
02556 }
02557 }
02558
02559
02560 void ARRAY_DIRECTED_GRAPH16::Fission_Dep_Update_R(WN *wn, WN *in_loop,
02561 UINT depth)
02562 {
02563 OPCODE opcode = WN_opcode(wn);
02564 VINDEX16 v;
02565
02566 if (opcode == OPC_BLOCK) {
02567 WN *kid = WN_first (wn);
02568 while (kid) {
02569 Fission_Dep_Update_R(kid,in_loop,depth);
02570 kid = WN_next(kid);
02571 }
02572 return;
02573 }
02574 if ((v=Get_Vertex(wn)) != 0) {
02575 Fission_Dep_Update_V(v,in_loop,depth);
02576 }
02577 for (INT kidno=0; kidno<WN_kid_count(wn); kidno++) {
02578 WN *kid = WN_kid(wn,kidno);
02579 Fission_Dep_Update_R(kid,in_loop,depth);
02580 }
02581 }
02582
02583
02584
02585 static WN *Find_Ancestor_WN1_Child_WN2(WN *wn1, WN *wn2)
02586 {
02587 while (wn1) {
02588 WN *parent = LWN_Get_Parent(wn1);
02589 if (parent == wn2) return(wn1);
02590 wn1 = parent;
02591 }
02592 return NULL;
02593 }
02594
02595
02596 void ARRAY_DIRECTED_GRAPH16::Fission_Dep_Update_V(VINDEX16 v,WN *in_loop,
02597 UINT depth)
02598 {
02599
02600 EINDEX16 e = _v[v].Get_Out_Edge();
02601 while (e) {
02602 EINDEX16 next_e = _e[e].Get_Next_Out_Edge();
02603 WN *sink = _v[_e[e].Get_Sink()].Wn;
02604 WN *sink_loop = Find_Ancestor_WN1_Child_WN2(sink,LWN_Get_Parent(in_loop));
02605 if (sink_loop && (sink_loop != in_loop)) {
02606 INT unused = _e[e].Depv_Array->Num_Unused_Dim();
02607 if (unused >= depth) {
02608 Delete_Array_Edge(e);
02609 } else {
02610 if (_e[e].Depv_Array->Num_Dim() > depth-unused) {
02611 DEPV_ARRAY *da = _e[e].Depv_Array->Shorten(depth-unused,_pool);
02612 Delete_DEPV_ARRAY(_e[e].Depv_Array,_pool);
02613 _e[e].Depv_Array = da;
02614 }
02615 }
02616 }
02617 e = next_e;
02618 }
02619 }
02620
02621
02622
02623
02624
02625
02626
02627
02628
02629
02630
02631
02632
02633
02634
02635
02636
02637
02638
02639
02640
02641
02642
02643
02644
02645
02646 INT ARRAY_DIRECTED_GRAPH16::Fission_Dep_Update(WN* in_loop,
02647 UINT32 total_loops, UINT fission_depth)
02648 {
02649 Is_True(_type==LEVEL_ARRAY_GRAPH,
02650 ("Fission_Dep_Update called on a non-level graph"));
02651 MEM_POOL_Push(&LNO_local_pool);
02652
02653 BOOL outer_good_do = TRUE;
02654 WN *tmp = LWN_Get_Parent(in_loop);
02655 while (tmp && (WN_opcode(tmp) != OPC_DO_LOOP)) tmp = LWN_Get_Parent(tmp);
02656 if (tmp && Do_Loop_Is_Good(tmp)) outer_good_do = FALSE;
02657
02658 VINDEX16 *do_loop_vertices =
02659 CXX_NEW_ARRAY(VINDEX16,total_loops,&LNO_local_pool);
02660
02661 tmp = in_loop;
02662 INT i;
02663 for (i=0; i<total_loops; i++) {
02664
02665 do_loop_vertices[i] = Get_Vertex(tmp);
02666 tmp = WN_next(tmp);
02667 }
02668
02669 for (INT j=0; j<fission_depth; j++) {
02670
02671 if (!Copy_Do_Loop_Deps(do_loop_vertices,total_loops)) {
02672 MEM_POOL_Pop(&LNO_local_pool);
02673 return 0;
02674 }
02675
02676 if (j<fission_depth-1)
02677 for (INT i=0; i<total_loops; i++) {
02678 WN* wn=Get_Only_Loop_Inside(Get_Wn(do_loop_vertices[i]),FALSE);
02679
02680 do_loop_vertices[i] = Get_Vertex(wn);
02681 }
02682
02683 }
02684
02685 UINT depth = Do_Loop_Depth(in_loop);
02686 for (i=0; i<total_loops; i++) {
02687 Is_True(WN_opcode(in_loop) == OPC_DO_LOOP,
02688 ("Non do loop in Fission_Dep_Update"));
02689
02690 if (!Fission_Dep_Update_R(in_loop,fission_depth,depth,outer_good_do)) {
02691 return(0);
02692 }
02693 in_loop = WN_next(in_loop);
02694 }
02695 MEM_POOL_Pop(&LNO_local_pool);
02696 return(1);
02697 }
02698
02699
02700 INT ARRAY_DIRECTED_GRAPH16::Copy_Do_Loop_Deps(VINDEX16 *do_loop_vertices,
02701 INT num_loops)
02702 {
02703 EINDEX16 e = _v[do_loop_vertices[0]].Get_Out_Edge();
02704 while (e) {
02705 for (INT i=1; i<num_loops; i++) {
02706 Add_Edge(do_loop_vertices[i],_e[e].Get_Sink(),Level(e));
02707 }
02708 e = _e[e].Get_Next_Out_Edge();
02709 }
02710
02711 e = _v[do_loop_vertices[0]].Get_In_Edge();
02712 while (e) {
02713 for (INT i=1; i<num_loops; i++) {
02714 if (!Add_Edge(_e[e].Get_Source(),do_loop_vertices[i],Level(e))) {
02715 return(0);
02716 }
02717 }
02718 e = _e[e].Get_Next_In_Edge();
02719 }
02720 return(1);
02721 }
02722
02723
02724
02725
02726
02727
02728
02729
02730 INT ARRAY_DIRECTED_GRAPH16::Fission_Dep_Update_R(WN *in_loop,
02731 UINT fission_depth, UINT depth, BOOL outer_good_do)
02732 {
02733 VINDEX16 in_loop_v = Get_Vertex(in_loop);
02734 Is_True(in_loop_v,("No vertex for one of the fission copies"));
02735
02736
02737 WN *statement, *parent;
02738 WN* loop = in_loop;
02739 for (INT i=0; i<fission_depth; i++) {
02740 parent = WN_do_body(loop);
02741 statement = WN_first(parent);
02742
02743 EINDEX16 e=0;
02744 while (statement) {
02745 if (WN_opcode(statement) == OPC_DO_LOOP)
02746 loop=statement;
02747 VINDEX16 v = Get_Vertex(statement);
02748 Is_True(v,("No vertex for one of the fission copies"));
02749 if (v) {
02750 e = _v[v].Get_Out_Edge();
02751 } else
02752 while (e) {
02753 EINDEX16 next_e = _e[e].Get_Next_Out_Edge();
02754 UINT level = MIN(Level(e),depth);
02755 VINDEX16 v2 = _e[e].Get_Sink();
02756 WN *wn2 = Get_Wn(v2);
02757 if (LWN_Get_Parent(wn2) != parent) {
02758 if (!outer_good_do) {
02759
02760 WN *parent2 = wn2;
02761 for (INT j=0; j<=i; j++) {
02762 parent2 = LWN_Get_Parent(LWN_Get_Parent(parent2));
02763 }
02764 VINDEX16 sinkv = Get_Vertex(parent2);
02765 Is_True(sinkv,("No vertex for one of the fission copies"));
02766 EINDEX16 new_e = Get_Edge(in_loop_v,sinkv);
02767 if (new_e) {
02768 _e[new_e].Level_Info.Level = MAX(Level(new_e),level);
02769 } else {
02770 if (!Add_Edge(in_loop_v,sinkv,level)) {
02771 return 0;
02772 }
02773 }
02774 }
02775 Remove_Edge(e);
02776 }
02777 e = next_e;
02778 }
02779 statement = WN_next(statement);
02780 }
02781 }
02782 return 1;
02783 }
02784
02785
02786
02787
02788
02789 static WN *Find_Inner(WN *wn)
02790 {
02791 if (WN_opcode(wn) == OPC_DO_LOOP) {
02792 return(wn);
02793 } else {
02794 return(Find_Inner(LWN_Get_Parent(wn)));
02795 }
02796 }
02797
02798
02799 static BOOL Inner_Loop_Invariant(ACCESS_ARRAY *a)
02800 {
02801 if (a->Too_Messy) return FALSE;
02802 for (INT i=0; i<a->Num_Vec(); i++) {
02803 ACCESS_VECTOR *av = a->Dim(i);
02804 if (av->Too_Messy) {
02805 return FALSE;
02806 }
02807 if (av->Non_Const_Loops() >= av->Nest_Depth()) {
02808 return FALSE;
02809 }
02810 if (av->Loop_Coeff(av->Nest_Depth()-1)) {
02811 return FALSE;
02812 }
02813 }
02814 return TRUE;
02815 }
02816
02817
02818
02819
02820
02821
02822
02823
02824
02825
02826
02827 void ARRAY_DIRECTED_GRAPH16::Add_Must()
02828 {
02829 MEM_POOL_Push(&LNO_local_pool);
02830 Is_True(_type==DEP_ARRAY_GRAPH,
02831 ("Add_Must called on non-CG dependence graph"));
02832
02833
02834 VINDEX16 v;
02835 for (v = Get_Vertex(); v; v = Get_Next_Vertex(v)) {
02836 WN *source = _v[v].Wn;
02837 WN *array1=0,*array2=0;
02838 ACCESS_ARRAY *a1=0,*a2=0;
02839 if (OPCODE_is_load(WN_opcode(source)) ||
02840 OPCODE_is_store(WN_opcode(source))) {
02841 if (OPCODE_is_load(WN_opcode(source))) {
02842 if (WN_kid_count(source) >= 1) {
02843 array1 = WN_kid0(source);
02844 }
02845 } else {
02846 if (WN_kid_count(source) >= 2) {
02847 array1 = WN_kid1(source);
02848 }
02849 }
02850 if (WN_operator(array1) == OPR_ADD) {
02851 if (WN_operator(WN_kid0(array1)) == OPR_ARRAY) {
02852 array1 = WN_kid0(array1);
02853 } else {
02854 array1 = WN_kid1(array1);
02855 }
02856 }
02857 if (array1) a1=(ACCESS_ARRAY *) WN_MAP_Get(LNO_Info_Map,array1);
02858 if (a1) {
02859 BOOL a1_invar = Inner_Loop_Invariant(a1);
02860 EINDEX16 e = Get_Out_Edge(v);
02861 while (e) {
02862 EINDEX16 new_e = Get_Next_Out_Edge(e);
02863 VINDEX16 v2 = Get_Sink(e);
02864 WN *sink = _v[v2].Wn;
02865 if (OPCODE_is_load(WN_opcode(sink)) ||
02866 OPCODE_is_store(WN_opcode(sink))) {
02867 if (DEPV_COMPUTE::Base_Test(source,NULL,sink,NULL)==DEP_CONTINUE) {
02868 if (OPCODE_is_load(WN_opcode(sink))) {
02869 if (WN_kid_count(sink) >= 1) {
02870 array2 = WN_kid0(sink);
02871 }
02872 } else {
02873 if (WN_kid_count(sink) >= 2) {
02874 array2 = WN_kid1(sink);
02875 }
02876 }
02877 if (WN_operator(array2) == OPR_ADD) {
02878 if (WN_operator(WN_kid0(array2)) == OPR_ARRAY) {
02879 array2 = WN_kid0(array2);
02880 } else {
02881 array2 = WN_kid1(array2);
02882 }
02883 }
02884 if (array2) a2=(ACCESS_ARRAY *) WN_MAP_Get(LNO_Info_Map,array2);
02885 if (a2) {
02886 DEP dep = Dep(e);
02887 if (DEP_IsDistance(dep)) {
02888 DEP dep2;
02889 if (Is_Must(a1,a2,Find_Inner(source),&dep2)) {
02890 if (DEP_IsDistance(dep2)) {
02891 if (DEP_Distance(dep) == DEP_Distance(dep2)) {
02892 Set_Must(e);
02893 } else {
02894 Delete_Edge(e);
02895 }
02896 }
02897 }
02898 } else if (DEPV_COMPUTE::Base_Test(source,NULL,sink,NULL)
02899 == DEP_CONTINUE) {
02900 DEP dep2;
02901 if (a1_invar && (*a1 == *a2)) {
02902 Set_Must(e);
02903 } else if (!a1_invar &&
02904 Is_Must(a1,a2,Find_Inner(source),&dep2)) {
02905 if (DEP_Distance(dep2) > 0) {
02906 if ((DEP_Direction(dep) == DIR_POS) ||
02907 (DEP_Direction(dep) == DIR_POSEQ) ||
02908 (DEP_Direction(dep) == DIR_STAR) ||
02909 (DEP_Direction(dep) == DIR_POSNEG)) {
02910 Set_Dep(e,dep2,TRUE);
02911 } else {
02912 Delete_Edge(e);
02913 }
02914 } else if (DEP_Distance(dep2) == 0) {
02915 if ((DEP_Direction(dep) == DIR_EQ) ||
02916 (DEP_Direction(dep) == DIR_POSEQ) ||
02917 (DEP_Direction(dep) == DIR_STAR) ||
02918 (DEP_Direction(dep) == DIR_NEGEQ)) {
02919 Set_Dep(e,dep2,TRUE);
02920 } else {
02921 Delete_Edge(e);
02922 }
02923 }
02924 }
02925 }
02926 }
02927 }
02928 }
02929 e = new_e;
02930 }
02931 }
02932 }
02933 }
02934
02935
02936
02937
02938
02939
02940
02941
02942 REF_LIST_STACK *reads = CXX_NEW(REF_LIST_STACK(&LNO_local_pool),
02943 &LNO_local_pool);
02944 for (v = Get_Vertex(); v; v = Get_Next_Vertex(v)) {
02945 WN *source = _v[v].Wn;
02946 OPCODE opcode = WN_opcode(source);
02947 if (OPCODE_is_load(opcode)) {
02948 if (WN_kid_count(source) == 1) {
02949 WN *inner_loop = Find_Inner(source);
02950 WN *array = WN_kid0(source);
02951 if (WN_operator(array) == OPR_ADD) {
02952 if (WN_operator(WN_kid0(array)) == OPR_ARRAY) {
02953 array = WN_kid0(array);
02954 } else {
02955 array = WN_kid1(array);
02956 }
02957 }
02958 if (WN_operator(array) == OPR_ARRAY) {
02959 WN *base = WN_array_base(array);
02960 ST *st_base = Get_ST_Base(base);
02961 INT i;
02962 for (i=0;i<reads->Elements() &&
02963 !((reads->Bottom_nth(i)->ST_Base==st_base) &&
02964 (reads->Bottom_nth(i)->Inner_Loop==inner_loop)); i++);
02965 if (i==reads->Elements()) {
02966 REFERENCE_LIST *rl =
02967 CXX_NEW(REFERENCE_LIST(st_base,source,inner_loop),&LNO_local_pool);
02968 reads->Push(rl);
02969 }
02970 reads->Bottom_nth(i)->Append(CXX_NEW(REFERENCE_NODE(source,0, 0),
02971 &LNO_local_pool));
02972 }
02973 }
02974 }
02975 }
02976
02977
02978
02979
02980 for (INT i=0; i<reads->Elements(); i++) {
02981 INT num_iterations = 0;
02982 WN *trip_count = WN_LOOP_TripCount(reads->Bottom_nth(i)->Inner_Loop);
02983 if (trip_count) {
02984 LWN_Parentize(trip_count);
02985 LWN_Set_Parent(trip_count, NULL);
02986 }
02987 BOOL const_trip = (trip_count) &&
02988 (WN_operator(trip_count) == OPR_INTCONST);
02989 if (const_trip) num_iterations = WN_const_val(trip_count);
02990 LWN_Delete_Tree(trip_count);
02991
02992 REFERENCE_ITER iter1(reads->Bottom_nth(i));
02993 for (REFERENCE_NODE *n1=iter1.First(); !iter1.Is_Empty();
02994 n1=iter1.Next()) {
02995 WN *wn1 = n1->Wn;
02996 WN *array1 = WN_kid0(wn1);
02997 if (WN_operator(array1) == OPR_ADD) {
02998 if (WN_operator(WN_kid0(array1)) == OPR_ARRAY) {
02999 array1 = WN_kid0(array1);
03000 } else {
03001 array1 = WN_kid1(array1);
03002 }
03003 }
03004 ACCESS_ARRAY *a1=(ACCESS_ARRAY *) WN_MAP_Get(LNO_Info_Map,array1);
03005 BOOL a1_invar = Inner_Loop_Invariant(a1);
03006 REFERENCE_ITER iter2(n1);
03007 REFERENCE_NODE *n2 = iter2.First();
03008 for (n2=iter2.Next(); !iter2.Is_Empty(); n2=iter2.Next()) {
03009 WN *wn2 = n2->Wn;
03010 WN *array2 = WN_kid0(wn2);
03011 if (WN_operator(array2) == OPR_ADD) {
03012 if (WN_operator(WN_kid0(array2)) == OPR_ARRAY) {
03013 array2 = WN_kid0(array2);
03014 } else {
03015 array2 = WN_kid1(array2);
03016 }
03017 }
03018
03019 if (DEPV_COMPUTE::Base_Test(wn1,NULL,wn2,NULL) == DEP_CONTINUE) {
03020 ACCESS_ARRAY *a2=(ACCESS_ARRAY *) WN_MAP_Get(LNO_Info_Map,array2);
03021 DEP dep;
03022 if (a1_invar && (*a1 == *a2)) {
03023 VINDEX16 v1 = Get_Vertex(wn1);
03024 VINDEX16 v2 = Get_Vertex(wn2);
03025 if (!Add_Edge(v1,v2,DEP_SetDirection(DIR_POSEQ),TRUE)) {
03026 MEM_POOL_Pop(&LNO_local_pool);
03027 return;
03028 }
03029 if (!Add_Edge(v2,v1,DEP_SetDirection(DIR_POS),TRUE)) {
03030 MEM_POOL_Pop(&LNO_local_pool);
03031 return;
03032 }
03033 } else if (Is_Must(a1,a2,reads->Bottom_nth(i)->Inner_Loop,&dep)) {
03034 VINDEX16 v1 = Get_Vertex(wn1);
03035 VINDEX16 v2 = Get_Vertex(wn2);
03036 if (!num_iterations || (abs(DEP_Distance(dep)) < num_iterations)) {
03037 if (DEP_Distance(dep) >= 0) {
03038 if (!Add_Edge(v1,v2,dep,TRUE)) {
03039 MEM_POOL_Pop(&LNO_local_pool);
03040 return;
03041 }
03042 } else {
03043 if (!Add_Edge(v2,v1,DEP_SetDistance(-DEP_Distance(dep)),TRUE)) {
03044 MEM_POOL_Pop(&LNO_local_pool);
03045 return;
03046 }
03047 }
03048 }
03049 }
03050 }
03051 }
03052 }
03053 }
03054 MEM_POOL_Pop(&LNO_local_pool);
03055 }
03056
03057
03058
03059
03060
03061
03062
03063 BOOL ARRAY_DIRECTED_GRAPH16::Is_Must(ACCESS_ARRAY *a1, ACCESS_ARRAY *a2,
03064 WN *inner_loop,DEP *dep)
03065 {
03066 if (a1->Too_Messy || a2->Too_Messy) return(FALSE);
03067 if (a1->Num_Vec() != a2->Num_Vec()) return(FALSE);
03068
03069 DO_LOOP_INFO *dli = (DO_LOOP_INFO *) WN_MAP_Get(LNO_Info_Map,inner_loop);
03070 INT depth = dli->Depth;
03071
03072 ACCESS_VECTOR *ac_step = dli->Step;
03073 if (!ac_step->Is_Const()) {
03074 return(FALSE);
03075 }
03076 INT64 step = ac_step->Const_Offset;
03077
03078 BOOL seen_mult = FALSE;
03079 INT diff=0;
03080
03081
03082 for (INT i=0; i<a1->Num_Vec(); i++) {
03083 ACCESS_VECTOR *av1 = a1->Dim(i);
03084 ACCESS_VECTOR *av2 = a2->Dim(i);
03085 if (av1->Too_Messy || av2->Too_Messy) return(FALSE);
03086
03087
03088 if (av1->Non_Const_Loops() == (depth + 1)) return(FALSE);
03089 if (av2->Non_Const_Loops() == (depth + 1)) return(FALSE);
03090
03091 INT dist = av1->Const_Offset - av2->Const_Offset;
03092
03093
03094 if (!av1->Has_Loop_Coeff() || !av2->Has_Loop_Coeff()) {
03095 if (dist) return(FALSE);
03096 }
03097
03098
03099 if (av1->Lin_Symb!=NULL && !av1->Lin_Symb->Is_Empty()) {
03100 if (av2->Lin_Symb == NULL || av2->Lin_Symb->Is_Empty() ||
03101 !(*av1->Lin_Symb == *av2->Lin_Symb)) {
03102 return(FALSE);
03103 }
03104 } else if (av2->Lin_Symb != NULL && !av2->Lin_Symb->Is_Empty()) {
03105 return(FALSE);
03106 }
03107 if (av1->Non_Lin_Symb != NULL && !av1->Non_Lin_Symb->Is_Empty()) {
03108 if (av2->Non_Lin_Symb == NULL || av2->Non_Lin_Symb->Is_Empty() ||
03109 !(*av1->Non_Lin_Symb == *av2->Non_Lin_Symb)) {
03110 return(FALSE);
03111 }
03112 } else if (av2->Non_Lin_Symb != NULL && !av2->Non_Lin_Symb->Is_Empty()) {
03113 return(FALSE);
03114 }
03115
03116
03117 for (INT ii=0; ii<av1->Nest_Depth(); ii++) {
03118 if (av1->Loop_Coeff(ii) != av2->Loop_Coeff(ii)) {
03119 return(FALSE);
03120 }
03121 }
03122 INT mult = av1->Loop_Coeff(depth);
03123 if (mult) {
03124 if ((dist % (step*mult)) != 0) {
03125 return(FALSE);
03126 }
03127 INT this_diff = (dist / (step*mult));
03128 if (seen_mult && (this_diff != diff)) {
03129 return(FALSE);
03130 }
03131 seen_mult = TRUE;
03132 diff = this_diff;
03133 } else {
03134 if (dist != 0) {
03135 return(FALSE);
03136 }
03137 }
03138 }
03139 if (dep) {
03140 *dep = DEP_SetDistance(diff);
03141 if (!DEP_IsDistance(*dep)) return FALSE;
03142 }
03143 return(TRUE);
03144 }
03145
03146
03147
03148
03149
03150
03151
03152 static BOOL Node_In_Tree (WN* wn, WN* root) {
03153 while (1) {
03154 if (wn == root) return TRUE;
03155 if (wn == NULL) return FALSE;
03156 wn = LWN_Get_Parent (wn);
03157 }
03158 }
03159
03160
03161
03162
03163
03164
03165
03166
03167
03168
03169 BOOL ARRAY_DIRECTED_GRAPH16::Versioned_Dependences_Update(WN* body_orig,
03170 WN* body_new,
03171 UINT loopno,
03172 WN_MAP version_map)
03173 {
03174 Is_True(_type==DEPV_ARRAY_ARRAY_GRAPH,
03175 ("Unrolled_Dependences_Update called on a non-DEPV_ARRAY graph"));
03176 MEM_POOL_Push(&LNO_local_pool);
03177
03178
03179 Versioned_Create_Vertices (body_orig, body_new);
03180
03181 BOOL ok = Versioned_Dependences_Update_E (body_orig, body_new,
03182 body_orig, body_new,
03183 loopno, version_map);
03184
03185 MEM_POOL_Pop(&LNO_local_pool);
03186 return ok;
03187 }
03188
03189
03190
03191
03192
03193
03194
03195
03196 void ARRAY_DIRECTED_GRAPH16::Versioned_Create_Vertices (WN* body_orig, WN* body_new) {
03197
03198 if (body_orig == NULL) {
03199 Is_True (body_new == NULL, ("mismatch in body_orig and body_new\n"));
03200 return;
03201 }
03202 if (Get_Vertex (body_orig)) Add_Vertex (body_new);
03203
03204 if (WN_opcode(body_new) == OPC_BLOCK) {
03205 WN* kid_new = WN_first(body_new);
03206 WN* kid_orig = WN_first(body_orig);
03207 while (kid_new) {
03208 Versioned_Create_Vertices (kid_orig, kid_new);
03209 kid_orig = WN_next (kid_orig);
03210 kid_new = WN_next (kid_new);
03211 }
03212 }
03213 else if (WN_kid_count(body_new)) {
03214 for (INT kidno=0; kidno<WN_kid_count(body_new); kidno++) {
03215 Versioned_Create_Vertices (WN_kid(body_orig, kidno), WN_kid(body_new, kidno));
03216 }
03217 }
03218 }
03219
03220
03221
03222
03223
03224
03225
03226
03227
03228
03229 BOOL ARRAY_DIRECTED_GRAPH16::Versioned_Dependences_Update_E(WN* body_orig,
03230 WN* body_new,
03231 WN* root_orig,
03232 WN* root_new,
03233 UINT loopno,
03234 WN_MAP version_map) {
03235
03236 if (body_orig == NULL) {
03237 Is_True (body_new == NULL, ("mismatch in body_orig and body_new\n"));
03238 return TRUE;
03239 }
03240
03241 if (OPCODE_is_load(WN_opcode(body_orig)) ||
03242 OPCODE_is_store(WN_opcode(body_orig)) ||
03243 OPCODE_is_call(WN_opcode(body_orig))) {
03244 VINDEX16 origv = Get_Vertex(body_orig);
03245 if (origv) {
03246 VINDEX16 newv = Get_Vertex (body_new);
03247
03248
03249
03250
03251 EINDEX16 edge = Get_Out_Edge(origv);
03252 while (edge) {
03253 VINDEX16 orig_sinkv = Get_Sink(edge);
03254 WN* orig_sinkwn = Get_Wn(orig_sinkv);
03255 if (!Node_In_Tree (orig_sinkwn, root_orig) &&
03256 !Node_In_Tree (orig_sinkwn, root_new)) {
03257
03258
03259
03260
03261
03262 if (Add_Edge(newv,orig_sinkv,
03263 Create_DEPV_ARRAY(Depv_Array(edge),_pool)) == 0) {
03264 LNO_Erase_Dg_From_Here_In(LWN_Get_Parent(root_orig), this);
03265 LNO_Erase_Dg_From_Here_In(LWN_Get_Parent(body_orig), this);
03266 return FALSE;
03267 }
03268 }
03269 edge = Get_Next_Out_Edge(edge);
03270 }
03271
03272 edge = Get_In_Edge (origv);
03273 while (edge) {
03274 VINDEX16 orig_sourcev = Get_Source(edge);
03275 WN* orig_sourcewn = Get_Wn(orig_sourcev);
03276 VINDEX16 new_sourcev;
03277 if (!Node_In_Tree (orig_sourcewn, root_orig) &&
03278 !Node_In_Tree (orig_sourcewn, root_new)) {
03279 new_sourcev = orig_sourcev;
03280 if (Add_Edge(new_sourcev,newv,
03281 Create_DEPV_ARRAY(Depv_Array(edge),_pool)) == 0) {
03282 LNO_Erase_Dg_From_Here_In(LWN_Get_Parent(root_orig), this);
03283 LNO_Erase_Dg_From_Here_In(LWN_Get_Parent(body_orig), this);
03284 return FALSE;
03285 }
03286 }
03287 edge = Get_Next_In_Edge(edge);
03288 }
03289
03290
03291
03292
03293
03294
03295 edge = Get_Out_Edge(origv);
03296 while (edge) {
03297 VINDEX16 orig_sinkv = Get_Sink(edge);
03298 WN* orig_sinkwn = Get_Wn(orig_sinkv);
03299 VINDEX16 new_sinkv;
03300 if (Node_In_Tree (orig_sinkwn, root_orig)) {
03301
03302
03303 new_sinkv = Get_Vertex((WN*) WN_MAP_Get (version_map, orig_sinkwn));
03304 if (Add_Edge(newv,new_sinkv,
03305 Create_DEPV_ARRAY(Depv_Array(edge),_pool)) == 0) {
03306 LNO_Erase_Dg_From_Here_In(LWN_Get_Parent(root_orig), this);
03307 LNO_Erase_Dg_From_Here_In(LWN_Get_Parent(body_orig), this);
03308 return FALSE;
03309 }
03310
03311
03312 if (Depv_Array(edge)->Equal_Through_Depth (loopno) == FALSE) {
03313
03314 INT unused = _e[edge].Depv_Array->Num_Unused_Dim();
03315 if (loopno > unused) {
03316
03317
03318
03319 DEPV_ARRAY* tmp = Depv_Array (edge)->Shorten (loopno-unused, _pool);
03320 if (Add_Edge (origv, new_sinkv, tmp) == 0) {
03321 LNO_Erase_Dg_From_Here_In(LWN_Get_Parent(root_orig), this);
03322 LNO_Erase_Dg_From_Here_In(LWN_Get_Parent(body_orig), this);
03323 return FALSE;
03324 }
03325 tmp = Depv_Array (edge)->Shorten (loopno-unused, _pool);
03326 if (Add_Edge (newv, orig_sinkv, tmp) == 0) {
03327 LNO_Erase_Dg_From_Here_In(LWN_Get_Parent(root_orig), this);
03328 LNO_Erase_Dg_From_Here_In(LWN_Get_Parent(body_orig), this);
03329 return FALSE;
03330 }
03331 }
03332 }
03333 }
03334 edge = Get_Next_Out_Edge(edge);
03335 }
03336 }
03337 }
03338
03339 if (WN_opcode(body_new) == OPC_BLOCK) {
03340 WN* kid_new = WN_first(body_new);
03341 WN* kid_orig = WN_first(body_orig);
03342 while (kid_new) {
03343 if (!Versioned_Dependences_Update_E (kid_orig, kid_new,
03344 root_orig, root_new, loopno,
03345 version_map))
03346 return FALSE;
03347 kid_orig = WN_next (kid_orig);
03348 kid_new = WN_next (kid_new);
03349 }
03350 }
03351 else if (WN_kid_count(body_new)) {
03352 for (INT kidno=0; kidno<WN_kid_count(body_new); kidno++) {
03353 if (!Versioned_Dependences_Update_E (WN_kid(body_orig, kidno),
03354 WN_kid(body_new, kidno),
03355 root_orig, root_new,
03356 loopno, version_map))
03357 return FALSE;
03358 }
03359 }
03360 return TRUE;
03361 }
03362
03363 #ifdef Is_True_On
03364 void ARRAY_DIRECTED_GRAPH16::Check_Graph()
03365 {
03366 MEM_POOL_Push(&LNO_local_pool);
03367 {
03368 HASH_TABLE<VINDEX16,INT> vertices(200, &LNO_local_pool);
03369 for (VINDEX16 v = Get_Vertex(); v; v = Get_Next_Vertex(v)) {
03370 WN *wn = Get_Wn(v);
03371 FmtAssert(wn, ("Missing wn for vertex %d", v));
03372 FmtAssert(Get_Do(wn), ("Missing enclosing loop for vertex %d", v));
03373 vertices.Enter(v, 1);
03374 }
03375 for (EINDEX16 e = Get_Edge(); e; e = Get_Next_Edge(e)) {
03376 FmtAssert(_e[e].Depv_Array,("Null Array for edge %d \n",e));
03377 VINDEX16 v1 = Get_Source(e);
03378 FmtAssert(vertices.Find(v1),
03379 ("Edge %d has source vertex %d not in graph", e, v1));
03380 VINDEX16 v2 = Get_Sink(e);
03381 FmtAssert(vertices.Find(v2),
03382 ("Edge %d has sink vertex %d not in graph", e, v2));
03383 }
03384 }
03385 MEM_POOL_Pop(&LNO_local_pool);
03386 }
03387
03388
03389 #endif
03390
03391
03392 void SCALAR_STACK::Add_Scalar(WN *wn, UINT snumber)
03393 {
03394 Is_True((WN_operator(wn) == OPR_LDID) ||
03395 (WN_operator(wn) == OPR_STID),
03396 ("Non scalar passed to SCALAR_STACK::Add_Scalar"));
03397 SYMBOL symbol(wn);
03398 SCALAR_REF sref(wn,snumber);
03399
03400 for (INT i=0; i<_stack->Elements(); i++) {
03401 if (symbol == _stack->Top_nth(i)._scalar) {
03402 _stack->Top_nth(i)._scalar_ref_stack->Push(sref);
03403 return;
03404 }
03405 }
03406 _stack->Push(SCALAR_NODE(_pool,symbol));
03407 _stack->Top_nth(0)._scalar_ref_stack->Push(sref);
03408 }
03409
03410
03411 void SCALAR_STACK::Add_Scalar(WN *wn_call, SYMBOL* symbol, UINT snumber)
03412 {
03413 Is_True(WN_operator(wn_call) == OPR_CALL
03414 || WN_operator(wn_call) == OPR_LDID
03415 || WN_operator(wn_call) == OPR_LDA,
03416 ("Non scalar passed to SCALAR_STACK::Add_Scalar"));
03417 SCALAR_REF sref(wn_call, snumber);
03418
03419 for (INT i=0; i<_stack->Elements(); i++) {
03420 if (*symbol == _stack->Top_nth(i)._scalar) {
03421 _stack->Top_nth(i)._scalar_ref_stack->Push(sref);
03422 return;
03423 }
03424 }
03425 _stack->Push(SCALAR_NODE(_pool,*symbol));
03426 _stack->Top_nth(0)._scalar_ref_stack->Push(sref);
03427 }
03428
03429 void SCALAR_STACK::Print(FILE *fp)
03430 {
03431 for (INT i=0; i<_stack->Elements(); i++) {
03432 SCALAR_NODE *node = &_stack->Bottom_nth(i);
03433 fprintf(fp,"The symbol is "); node->_scalar.Print(fp); fprintf(fp,"\n");
03434 for (INT j=0; j<node->Elements(); j++) {
03435 fprintf(fp,"One with statement number %d \n",
03436 node->Bottom_nth(j)->Statement_Number);
03437 }
03438 }
03439 }
03440
03441 void SCALAR_STACK::Clear_Formal(INT i)
03442 {
03443 STACK<SCALAR_NODE> temp_stack(_pool);
03444 INT j;
03445 for (j = 0; j < _stack->Elements(); j++) {
03446 SCALAR_NODE* sn = &_stack->Bottom_nth(j);
03447 if (!(sn->_scalar.Is_Formal() && sn->_scalar.Formal_Number() == i))
03448 temp_stack.Push(*sn);
03449 }
03450 _stack->Clear();
03451 for (j = 0; j < temp_stack.Elements(); j++)
03452 _stack->Push(temp_stack.Bottom_nth(j));
03453 }
03454
03455 #endif
03456
03457
03458