00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115 #ifdef USE_PCH
00116 #include "lno_pch.h"
00117 #endif // USE_PCH
00118 #pragma hdrstop
00119
00120 static char *source_file = __FILE__;
00121 static char *rcs_id = "$Source: be/lno/SCCS/s.aequiv.cxx $ $Revision: 1.5 $";
00122
00123 #include <sys/types.h>
00124 #include "pu_info.h"
00125 #include "lnopt_main.h"
00126 #include "aequiv.h"
00127 #include "stab.h"
00128 #include "lwn_util.h"
00129 #include "stblock.h"
00130 #include "opt_alias_interface.h"
00131 #include "lego_pragma.h"
00132
00133 MEM_POOL AEQUIV_pool;
00134 static BOOL AEQUIV_pool_initialized = FALSE;
00135
00136
00137 void AEQUIV::Equivalence_Arrays()
00138 {
00139 if (Get_Trace(TP_LNOPT,TT_LNO_AEQUIV)) {
00140 fprintf(TFile,"Equivalencing local arrays \n");
00141 }
00142
00143 if (!AEQUIV_pool_initialized) {
00144 MEM_POOL_Initialize(_pool, "AEQUIV_pool", FALSE);
00145 AEQUIV_pool_initialized = TRUE;
00146 }
00147 MEM_POOL_Push(_pool);
00148 _la_stack = CXX_NEW(LOCAL_ARRAY_STACK(_pool),_pool);
00149
00150
00151 Enter_Locals_Stack();
00152 if (_la_stack->Elements() == 0) {
00153 if (Get_Trace(TP_LNOPT,TT_LNO_AEQUIV)) {
00154 fprintf(TFile,"no local arrays\n");
00155 }
00156 CXX_DELETE(_la_stack,_pool);
00157 MEM_POOL_Pop(_pool);
00158 return;
00159 }
00160 _la_hash_table =
00161 CXX_NEW(LOCAL_ARRAY_HASH_TABLE(2*_la_stack->Elements(),_pool),_pool);
00162 Enter_Locals_Hash();
00163
00164 _cyclic_bit_vector = CXX_NEW(BIT_VECTOR_STACK(_pool),_pool);
00165
00166 if (Build_CFG() == -1) {
00167 CXX_DELETE(_la_stack,_pool);
00168 CXX_DELETE(_la_hash_table,_pool);
00169 CXX_DELETE(_cfg,_pool);
00170 MEM_POOL_Pop(_pool);
00171 return;
00172 }
00173
00174 if (_la_stack->Elements() == 1) {
00175
00176 if (_la_stack->Elements() == 1){
00177 if (Get_Trace(TP_LNOPT,TT_LNO_AEQUIV)) {
00178 fprintf(TFile,"Only one local array\n");
00179 }
00180 LOCAL_ARRAY_DESC *lad = _la_hash_table->Find(_la_stack->Bottom_nth(0));
00181 if (!lad->_is_read){
00182 mBOOL equiv_array = TRUE;
00183 Update_Code(_func_nd,&equiv_array);
00184 }
00185 CXX_DELETE(_la_stack,_pool);
00186 CXX_DELETE(_la_hash_table,_pool);
00187 CXX_DELETE(_cfg,_pool);
00188 MEM_POOL_Pop(_pool);
00189 return;
00190 }
00191 }
00192
00193 if (Get_Trace(TP_LNOPT,TT_LNO_AEQUIV)) {
00194 fprintf(TFile,"The cfg graph is \n");
00195 Print_Graph(TFile,_cfg);
00196 }
00197
00198 Set_Acyclic();
00199 if (Get_Trace(TP_LNOPT,TT_LNO_AEQUIV)) {
00200 fprintf(TFile,"The acfg graph is \n");
00201 Print_Graph(TFile,_acfg);
00202 }
00203
00204 Do_Dataflow();
00205 if (Get_Trace(TP_LNOPT,TT_LNO_AEQUIV)) {
00206 fprintf(TFile,"After dataflow the acfg graph is \n");
00207 Print_Graph(TFile,_acfg);
00208 }
00209
00210 Set_Array_Bit_Vector();
00211 if (Get_Trace(TP_LNOPT,TT_LNO_AEQUIV)) {
00212 fprintf(TFile,"the array bit vector is \n");
00213 for (INT i=0; i<Num_Arrays(); i++) {
00214 fprintf(TFile,"a[%d] =",i);
00215 _array_bit_vector->Bottom_nth(i)->Print(TFile);
00216 }
00217 }
00218
00219 mBOOL *equivalenced_array = CXX_NEW_ARRAY(mBOOL,Num_Arrays(),_pool);
00220 if (Do_Color(equivalenced_array)) {
00221 Update_Code(_func_nd,equivalenced_array);
00222 }
00223
00224
00225 CXX_DELETE(_cfg,_pool);
00226 CXX_DELETE(_acfg,_pool);
00227 CXX_DELETE_ARRAY(equivalenced_array,_pool);
00228 CXX_DELETE(_la_hash_table,_pool);
00229 CXX_DELETE(_la_stack,_pool);
00230 CXX_DELETE(_cyclic_bit_vector,_pool);
00231 CXX_DELETE(_acyclic_bit_vector,_pool);
00232 MEM_POOL_Pop(_pool);
00233 }
00234
00235
00236 void AEQUIV::Enter_Locals_Stack()
00237 {
00238 ST *st;
00239 INT i;
00240 FOREACH_SYMBOL (CURRENT_SYMTAB,st,i) {
00241 if ((ST_class(st) == CLASS_VAR) && !ST_is_not_used(st) &&
00242 (ST_sclass(st) == SCLASS_AUTO) &&
00243 !ST_addr_saved(st) && !ST_addr_passed(st) &&
00244 ST_base_idx(st) == ST_st_idx(st) &&
00245 !ST_has_nested_ref(st) &&
00246 (TY_size(ST_type(st)) > 0) &&
00247 (!ST_is_initialized(st)) &&
00248 (!ST_is_reshaped(st)) &&
00249 (!da_hash || !da_hash->Find(st)) &&
00250 (TY_kind(ST_type(st)) == KIND_ARRAY)) {
00251 _la_stack->Push(st);
00252 }
00253 }
00254 Sort_Stack();
00255 }
00256
00257
00258
00259
00260
00261 void AEQUIV::Sort_Stack()
00262 {
00263 INT num_var = _la_stack->Elements();
00264 for (INT i=0; i<num_var; i++) {
00265 INT best_var = i;
00266 INT best_size = TY_size(ST_type(_la_stack->Bottom_nth(i)));
00267 for (INT j=i+1; j<num_var; j++) {
00268 ST *st = _la_stack->Bottom_nth(j);
00269 INT size = TY_size(ST_type(st));
00270 if (size > best_size) {
00271 best_var = j;
00272 best_size = size;
00273 }
00274 }
00275 if (best_var != i) {
00276 ST *temp = _la_stack->Bottom_nth(best_var);
00277 _la_stack->Bottom_nth(best_var) = _la_stack->Bottom_nth(i);
00278 _la_stack->Bottom_nth(i) = temp;
00279 }
00280 }
00281 if (Get_Trace(TP_LNOPT,TT_LNO_AEQUIV)) {
00282 for (INT i=0; i<_la_stack->Elements(); i++) {
00283 fprintf(TFile,"local array %d is %s \n",i,
00284 ST_name(ST_base(_la_stack->Bottom_nth(i))));
00285 }
00286 }
00287 }
00288
00289
00290 void AEQUIV::Enter_Locals_Hash()
00291 {
00292 ST *st;
00293 for (INT id=0; id<_la_stack->Elements(); id++) {
00294 ST *st = _la_stack->Bottom_nth(id);
00295 LOCAL_ARRAY_DESC *array = CXX_NEW(LOCAL_ARRAY_DESC(id),_pool);
00296 _la_hash_table->Enter(st,array);
00297 }
00298 }
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316 INT AEQUIV::Build_CFG()
00317 {
00318 _cfg = CXX_NEW(SCC_DIRECTED_GRAPH16(200,200),_pool);
00319 GOTO_VERTEX_STACK goto_stack(_pool);
00320 LABEL_STACK label_stack(_pool);
00321 LABEL_VERTEX_HASH label_hash(200,_pool);
00322
00323 _head_vertex =
00324 Add_CFG_Vertex(CXX_NEW(BIT_VECTOR(Num_Arrays(),_pool),_pool));
00325 _tail_vertex =
00326 Add_CFG_Vertex(CXX_NEW(BIT_VECTOR(Num_Arrays(),_pool),_pool));
00327
00328 if (Build_CFG_Rec(WN_func_body(_func_nd),
00329 &_head_vertex,_tail_vertex,&goto_stack,&label_stack, &label_hash)==-1) {
00330 return -1;
00331 }
00332
00333 if (Backpatch_CFG(&goto_stack,&label_stack,&label_hash) == -1) {
00334 return -1;
00335 }
00336 return 1;
00337 }
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350 INT AEQUIV::Build_CFG_Rec(WN *wn, VINDEX16 *current_v,
00351 VINDEX16 next_v,GOTO_VERTEX_STACK *goto_stack,LABEL_STACK *label_stack,
00352 LABEL_VERTEX_HASH *label_hash)
00353 {
00354 OPCODE opcode = WN_opcode(wn);
00355
00356 if ((opcode == OPC_DO_LOOP) || (opcode == OPC_DO_WHILE) ||
00357 (opcode == OPC_WHILE_DO)) {
00358
00359
00360 VINDEX16 loop_v =
00361 Add_CFG_Vertex(CXX_NEW(BIT_VECTOR(Num_Arrays(),_pool),_pool));
00362 if (!loop_v) return -1;
00363
00364
00365 if (!Add_CFG_Edge(*current_v,loop_v)) return -1;
00366
00367
00368 if (Build_CFG_Loop(wn,loop_v,goto_stack,label_stack,label_hash) == -1) {
00369 return -1;
00370 }
00371
00372
00373 *current_v =
00374 Add_CFG_Vertex(CXX_NEW(BIT_VECTOR(Num_Arrays(),_pool),_pool));
00375 if (!*current_v) return -1;
00376
00377
00378 if (!Add_CFG_Edge(loop_v,*current_v)) return -1;
00379
00380 } else if (opcode == OPC_BLOCK) {
00381 WN *kid = WN_first(wn);
00382 while (kid) {
00383 if (Build_CFG_Rec(kid,current_v,next_v,goto_stack,label_stack,label_hash)
00384 == -1) {
00385 return -1;
00386 }
00387 kid = WN_next(kid);
00388 }
00389 if (!Add_CFG_Edge(*current_v,next_v)) return -1;
00390 } else if (opcode == OPC_IF) {
00391 Handle_Rhs(WN_if_test(wn),*current_v);
00392 VINDEX16 old_current = *current_v;
00393
00394
00395 VINDEX16 newv=
00396 Add_CFG_Vertex(CXX_NEW(BIT_VECTOR(Num_Arrays(),_pool),_pool));
00397 if (!newv) return -1;
00398
00399 BOOL if_then_else=TRUE;
00400 if (WN_first(WN_then(wn))) {
00401 *current_v=Add_CFG_Vertex(CXX_NEW(BIT_VECTOR(Num_Arrays(),_pool),_pool));
00402 if (!*current_v) return -1;
00403 if (!Add_CFG_Edge(old_current,*current_v)) return -1;
00404 if (Build_CFG_Rec(WN_then(wn),current_v,newv,
00405 goto_stack,label_stack,label_hash) == -1) {
00406 return -1;
00407 }
00408 } else {
00409 if_then_else = FALSE;
00410 }
00411 if (WN_first(WN_else(wn))) {
00412 *current_v=Add_CFG_Vertex(CXX_NEW(BIT_VECTOR(Num_Arrays(),_pool),_pool));
00413 if (!*current_v) return -1;
00414 if (!Add_CFG_Edge(old_current,*current_v)) return -1;
00415 if (Build_CFG_Rec(WN_else(wn),current_v,newv,goto_stack,
00416 label_stack,label_hash) == -1) {
00417 return -1;
00418 }
00419 } else {
00420 if_then_else = FALSE;
00421 }
00422 if (!if_then_else) {
00423 if (!Add_CFG_Edge(old_current,newv)) return -1;
00424 }
00425 *current_v = newv;
00426 } else if ((opcode == OPC_GOTO) || (opcode == OPC_AGOTO)) {
00427 GOTO_VERTEX gv;
00428 gv._wn = wn;
00429 gv._vindex = *current_v;
00430 goto_stack->Push(gv);
00431 *current_v = Add_CFG_Vertex(CXX_NEW(BIT_VECTOR(Num_Arrays(),_pool),_pool));
00432 if (!*current_v) return -1;
00433 } else if (opcode == OPC_IO) {
00434 Handle_Call(wn,*current_v);
00435 for (INT32 i = 0; i < WN_kid_count(wn); i++) {
00436 WN *kid = WN_kid(wn, i);
00437 OPCODE kid_opcode = WN_opcode(kid);
00438 Is_True(OPCODE_has_inumber(kid_opcode),
00439 ("illegal OPC_IO_ITEM within iostmt"));
00440 if (kid_opcode == OPC_IO_ITEM) {
00441 if (WN_io_item(kid) == IOC_END || WN_io_item(kid) == IOC_ERR ||
00442 WN_io_item(kid) == IOC_EOR) {
00443 WN *kid0 = WN_kid0(kid);
00444 Is_True(WN_operator(kid0) == OPR_GOTO,
00445 ("IOC_END/ERR with non-GOTO kid"));
00446 GOTO_VERTEX gv;
00447 gv._wn = kid0;
00448 gv._vindex = *current_v;
00449 goto_stack->Push(gv);
00450 VINDEX16 old_current = *current_v;
00451 *current_v = Add_CFG_Vertex(CXX_NEW(BIT_VECTOR(
00452 Num_Arrays(),_pool),_pool));
00453 if (!*current_v) return -1;
00454 if (!Add_CFG_Edge(old_current,*current_v)) return -1;
00455 }
00456 }
00457 }
00458 } else if (opcode == OPC_COMPGOTO) {
00459 GOTO_VERTEX gv;
00460 Handle_Rhs(WN_kid0(wn),*current_v);
00461 WN *goto_wn= WN_first(WN_kid1(wn));
00462 while (goto_wn) {
00463 gv._wn = goto_wn;
00464 gv._vindex = *current_v;
00465 goto_stack->Push(gv);
00466 goto_wn = WN_next(goto_wn);
00467 }
00468 *current_v =
00469 Add_CFG_Vertex(CXX_NEW(BIT_VECTOR(Num_Arrays(),_pool),_pool));
00470 if (!*current_v) return -1;
00471 } else if (opcode == OPC_ALTENTRY) {
00472 if (!Add_CFG_Edge(_head_vertex,*current_v)) return -1;
00473 *current_v = Add_CFG_Vertex(CXX_NEW(BIT_VECTOR(Num_Arrays(),_pool),_pool));
00474 if (!*current_v) return -1;
00475 } else if (opcode == OPC_TRUEBR || opcode == OPC_FALSEBR) {
00476 for (INT kidno=0; kidno < WN_kid_count(wn); kidno++) {
00477 Handle_Rhs(WN_kid(wn,kidno),*current_v);
00478 }
00479 GOTO_VERTEX gv;
00480 gv._wn = wn;
00481 gv._vindex = *current_v;
00482 goto_stack->Push(gv);
00483 VINDEX16 old_current = *current_v;
00484 *current_v = Add_CFG_Vertex(CXX_NEW(BIT_VECTOR(Num_Arrays(),_pool),_pool));
00485 if (!*current_v) return -1;
00486 if (!Add_CFG_Edge(old_current,*current_v)) return -1;
00487 } else if (opcode == OPC_RETURN
00488 #ifdef KEY
00489 || opcode == OPC_GOTO_OUTER_BLOCK
00490 #endif
00491 ) {
00492 if (!Add_CFG_Edge(*current_v,_tail_vertex)) return -1;
00493 } else if (opcode == OPC_LABEL) {
00494 VINDEX16 old_current = *current_v;
00495 *current_v = Add_CFG_Vertex(CXX_NEW(BIT_VECTOR(Num_Arrays(),_pool),_pool));
00496 if (!*current_v) return -1;
00497 if (!Add_CFG_Edge(old_current,*current_v)) return -1;
00498 label_hash->Enter(WN_label_number(wn),*current_v);
00499 label_stack->Push(*current_v);
00500 } else if (OPCODE_is_store(opcode)) {
00501 Handle_Store(wn,*current_v);
00502 } else if (OPCODE_is_load(opcode)) {
00503 ST *st = NULL;
00504 if (OPCODE_operator(opcode) == OPR_LDID) st = WN_st(wn);
00505 else {
00506
00507 if (WN_operator(WN_kid0(wn)) == OPR_LDID) {
00508 st = WN_st(WN_kid0(wn));
00509 } else if (WN_operator(WN_kid0(wn)) == OPR_ARRAY &&
00510 (WN_operator(WN_array_base(WN_kid0(wn))) == OPR_LDID ||
00511 WN_operator(WN_array_base(WN_kid0(wn))) == OPR_LDA)) {
00512 st = WN_st(WN_array_base(WN_kid0(wn)));
00513 }
00514 }
00515
00516 LOCAL_ARRAY_DESC *lad = _la_hash_table->Find(st);
00517 if (lad && TY_is_volatile(WN_ty(wn))) {
00518 lad->_address_taken=TRUE;
00519 }
00520 } else if (OPCODE_is_call(opcode)) {
00521 Handle_Call(wn,*current_v);
00522 } else if (!OPCODE_is_expression(opcode)) {
00523 for (INT kidno=0; kidno < WN_kid_count(wn); kidno++) {
00524 if (Build_CFG_Rec(WN_kid(wn,kidno),current_v,next_v,
00525 goto_stack,label_stack,label_hash) == -1) {
00526 return -1;
00527 }
00528 }
00529 } else {
00530 Handle_Rhs(wn,*current_v);
00531 }
00532 return 1;
00533 }
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543 static void Build_St_Stack_And_Skip(WN* wn_tree,
00544 STACK<ST*>* st_stack)
00545 {
00546
00547 if (WN_operator(wn_tree) == OPR_ILOAD
00548 && WN_operator(WN_kid0(wn_tree)) == OPR_ARRAY
00549 && OPCODE_has_sym(WN_opcode(WN_array_base(WN_kid0(wn_tree)))))
00550 return;
00551
00552 if (OPCODE_has_sym(WN_opcode(wn_tree)))
00553 st_stack->Push(WN_st(wn_tree));
00554
00555 if (WN_operator(wn_tree) == OPR_BLOCK) {
00556 for (WN* wn = WN_first(wn_tree); wn != NULL; wn = WN_next(wn))
00557 Build_St_Stack_And_Skip(wn, st_stack);
00558 } else {
00559 for (INT i = 0; i < WN_kid_count(wn_tree); i++)
00560 Build_St_Stack_And_Skip(WN_kid(wn_tree, i), st_stack);
00561 }
00562 }
00563
00564
00565
00566
00567
00568 void AEQUIV::Handle_Store(WN *store, VINDEX16 v)
00569 {
00570 Handle_Rhs(WN_kid0(store),v);
00571 if (TY_is_volatile(WN_ty(store)) ||
00572 ((WN_operator(store) != OPR_STID) &&
00573 TY_is_volatile(TY_pointed(WN_ty(store))))) {
00574
00575 ST *st = NULL;
00576 if (WN_operator(store) == OPR_STID) {
00577 st = WN_st(store);
00578 LOCAL_ARRAY_DESC *lad = _la_hash_table->Find(st);
00579 if (lad)
00580 lad->_address_taken = TRUE;
00581 } else {
00582
00583
00584 WN *addr = WN_kid1(store);
00585 STACK<ST*> st_stack(_pool);
00586 Build_St_Stack_And_Skip(addr, &st_stack);
00587 for (INT i = 0; i < st_stack.Elements(); i++) {
00588 ST* st = st_stack.Bottom_nth(i);
00589 LOCAL_ARRAY_DESC *lad = _la_hash_table->Find(st);
00590 if (lad)
00591 lad->_address_taken = TRUE;
00592 }
00593 }
00594 }
00595 if (WN_kid_count(store) >= 2) {
00596 Handle_Lhs(WN_kid1(store),v);
00597 } else if (WN_operator(store) == OPR_STID) {
00598 LOCAL_ARRAY_DESC *lad = _la_hash_table->Find(WN_st(store));
00599 if (lad ) {
00600 lad->_address_taken = TRUE;
00601 }
00602 }
00603 }
00604
00605 void AEQUIV::Handle_Lhs(WN *wn, VINDEX16 v)
00606 {
00607 if (WN_operator(wn) == OPR_LDA) {
00608 LOCAL_ARRAY_DESC *lad = _la_hash_table->Find(WN_st(wn));
00609 if (lad) {
00610 lad->_is_written = TRUE;
00611 _cyclic_bit_vector->Bottom_nth(v)->Set(lad->_id);
00612 }
00613 } else if (WN_operator(wn) == OPR_LDID) {
00614 LOCAL_ARRAY_DESC *lad = _la_hash_table->Find(WN_st(wn));
00615 if (lad) {
00616 lad->_address_taken = TRUE;
00617 }
00618 } else if (OPCODE_is_load(WN_opcode(wn))) {
00619 for (INT kidno=0; kidno < WN_kid_count(wn); kidno++) {
00620 Handle_Rhs(WN_kid(wn,kidno),v);
00621 }
00622 } else {
00623 for (INT kidno=0; kidno < WN_kid_count(wn); kidno++) {
00624 Handle_Lhs(WN_kid(wn,kidno),v);
00625 }
00626 }
00627 }
00628
00629 void AEQUIV::Handle_Rhs(WN *wn, VINDEX16 v)
00630 {
00631 if (WN_operator(wn) == OPR_LDA) {
00632 LOCAL_ARRAY_DESC *lad = _la_hash_table->Find(WN_st(wn));
00633 if (lad) {
00634 WN *parent = LWN_Get_Parent(wn);
00635 if (WN_operator(parent) == OPR_ARRAY) {
00636 OPCODE grandparent_opcode = (WN_opcode(LWN_Get_Parent(parent)));
00637 OPERATOR grandparent = OPCODE_operator(grandparent_opcode);
00638 if ((grandparent == OPR_ILOAD) ||
00639 (OPCODE_is_prefetch(grandparent_opcode)) ||
00640 ((grandparent == OPR_ISTORE) &&
00641 (parent = WN_kid1(LWN_Get_Parent(parent))))) {
00642 lad->_is_read = TRUE;
00643 _cyclic_bit_vector->Bottom_nth(v)->Set(lad->_id);
00644 } else {
00645 lad->_address_taken = TRUE;
00646 }
00647 } else {
00648 lad->_address_taken = TRUE;
00649 }
00650 }
00651 } else if (WN_operator(wn) == OPR_LDID) {
00652 LOCAL_ARRAY_DESC *lad = _la_hash_table->Find(WN_st(wn));
00653 if (lad) {
00654 lad->_address_taken = TRUE;
00655 }
00656 } else {
00657 for (INT kidno=0; kidno < WN_kid_count(wn); kidno++) {
00658 Handle_Rhs(WN_kid(wn,kidno),v);
00659 }
00660 }
00661 }
00662
00663
00664
00665 void AEQUIV::Handle_Call(WN *wn, VINDEX16 v)
00666 {
00667 if (WN_operator(wn) == OPR_LDA) {
00668 LOCAL_ARRAY_DESC *lad = _la_hash_table->Find(WN_st(wn));
00669 if (lad) {
00670 if (WN_operator(LWN_Get_Parent(wn)) == OPR_ARRAY) {
00671 #ifndef KEY
00672 lad->_is_read = TRUE;
00673 lad->_is_written = TRUE;
00674 _cyclic_bit_vector->Bottom_nth(v)->Set(lad->_id);
00675 #else
00676
00677
00678
00679
00680
00681 if (WN_operator(LWN_Get_Parent(LWN_Get_Parent(wn))) == OPR_PARM &&
00682
00683 !(WN_flag(LWN_Get_Parent(LWN_Get_Parent(wn))) &
00684 WN_PARM_PASSED_NOT_SAVED)) {
00685 FmtAssert(WN_flag(LWN_Get_Parent(LWN_Get_Parent(wn))) &
00686 WN_PARM_BY_REFERENCE, ("Handle this case"));
00687 lad->_address_taken = TRUE;
00688 } else {
00689 lad->_is_read = TRUE;
00690 lad->_is_written = TRUE;
00691 _cyclic_bit_vector->Bottom_nth(v)->Set(lad->_id);
00692 }
00693 #endif
00694 } else {
00695 lad->_address_taken = TRUE;
00696 }
00697 }
00698 } else if (WN_operator(wn) == OPR_LDID) {
00699 LOCAL_ARRAY_DESC *lad = _la_hash_table->Find(WN_st(wn));
00700 if (lad) {
00701 lad->_is_read = TRUE;
00702 lad->_is_written = TRUE;
00703 _cyclic_bit_vector->Bottom_nth(v)->Set(lad->_id);
00704 }
00705 } else if (WN_operator(wn) == OPR_BLOCK) {
00706 WN *kid = WN_first(wn);
00707 while (kid) {
00708 Handle_Call(kid,v);
00709 kid = WN_next(kid);
00710 }
00711 } else {
00712 for (INT kidno=0; kidno < WN_kid_count(wn); kidno++) {
00713 Handle_Call(WN_kid(wn,kidno),v);
00714 }
00715 }
00716 }
00717
00718
00719
00720
00721
00722
00723
00724 INT AEQUIV::Build_CFG_Loop(WN *wn,VINDEX16 loopv,
00725 GOTO_VERTEX_STACK *goto_stack,LABEL_STACK *label_stack,
00726 LABEL_VERTEX_HASH *label_hash)
00727 {
00728 OPCODE opcode = WN_opcode(wn);
00729
00730 if (opcode == OPC_BLOCK) {
00731 WN *kid = WN_first(wn);
00732 while (kid) {
00733 if (Build_CFG_Loop(kid,loopv,goto_stack,label_stack,label_hash) == -1) {
00734 return -1;
00735 }
00736 kid = WN_next(kid);
00737 }
00738 return 1;
00739 }
00740
00741 if (opcode == OPC_GOTO || opcode == OPC_AGOTO ||
00742 opcode == OPC_TRUEBR || opcode == OPC_FALSEBR) {
00743 for (INT kidno=0; kidno < WN_kid_count(wn); kidno++) {
00744 Handle_Rhs(WN_kid(wn,kidno),loopv);
00745 }
00746 GOTO_VERTEX gv;
00747 gv._wn = wn;
00748 gv._vindex = loopv;
00749 goto_stack->Push(gv);
00750 } else if (opcode == OPC_IO) {
00751 Handle_Call(wn,loopv);
00752 for (INT32 i = 0; i < WN_kid_count(wn); i++) {
00753 WN *kid = WN_kid(wn, i);
00754 OPCODE kid_opcode = WN_opcode(kid);
00755 Is_True(OPCODE_has_inumber(kid_opcode),
00756 ("illegal OPC_IO_ITEM within iostmt"));
00757 if (kid_opcode == OPC_IO_ITEM) {
00758 if (WN_io_item(kid) == IOC_END || WN_io_item(kid) == IOC_ERR ||
00759 WN_io_item(kid) == IOC_EOR) {
00760 WN *kid0 = WN_kid0(kid);
00761 Is_True(WN_operator(kid0) == OPR_GOTO,
00762 ("IOC_END/ERR with non-GOTO kid"));
00763 GOTO_VERTEX gv;
00764 gv._wn = kid0;
00765 gv._vindex = loopv;
00766 goto_stack->Push(gv);
00767 }
00768 }
00769 }
00770 } else if (opcode == OPC_COMPGOTO) {
00771 Handle_Rhs(WN_kid0(wn),loopv);
00772 GOTO_VERTEX gv;
00773 WN *goto_wn= WN_first(WN_kid1(wn));
00774 while (goto_wn) {
00775 gv._wn = goto_wn;
00776 gv._vindex = loopv;
00777 goto_stack->Push(gv);
00778 goto_wn = WN_next(goto_wn);
00779 }
00780 } else if (opcode == OPC_ALTENTRY) {
00781 if (!Add_CFG_Edge(_head_vertex,loopv)) return -1;
00782 } else if (opcode == OPC_RETURN
00783 #ifdef KEY
00784 || opcode == OPC_GOTO_OUTER_BLOCK
00785 #endif
00786 ) {
00787 if (!Add_CFG_Edge(loopv,_tail_vertex)) return -1;
00788 } else if (opcode == OPC_LABEL) {
00789 label_hash->Enter(WN_label_number(wn),loopv);
00790 label_stack->Push(loopv);
00791 } else if (OPCODE_is_store(opcode)) {
00792 Handle_Store(wn,loopv);
00793 } else if (OPCODE_is_call(opcode)) {
00794 Handle_Call(wn,loopv);
00795 } else if (!OPCODE_is_expression(opcode)) {
00796 for (INT kidno=0; kidno < WN_kid_count(wn); kidno++) {
00797 if (Build_CFG_Loop(WN_kid(wn,kidno),
00798 loopv,goto_stack,label_stack,label_hash) == -1) {
00799 return -1;
00800 }
00801 }
00802 } else {
00803 Handle_Rhs(wn,loopv);
00804 }
00805
00806 return 1;
00807 }
00808
00809
00810
00811
00812 void AEQUIV::Print_Graph(FILE *fp,SCC_DIRECTED_GRAPH16 *graph)
00813 {
00814 VINDEX16 i;
00815 EINDEX16 e;
00816 fprintf(fp,"Printing a control-flow graph \n");
00817
00818 for (i=graph->Get_Vertex(); i; i = graph->Get_Next_Vertex(i)) {
00819 fprintf(fp,"Vertex %d has bitmask =",i);
00820 if (graph == _cfg) {
00821 _cyclic_bit_vector->Bottom_nth(i)->Print(fp);
00822 } else {
00823 _acyclic_bit_vector->Bottom_nth(i)->Print(fp);
00824 }
00825 fprintf(fp,"\n");
00826
00827 e = graph->Get_Out_Edge(i);
00828 while (e) {
00829 fprintf(fp,"Edge to vertex %d \n",graph->Get_Sink(e));
00830 e = graph->Get_Next_Out_Edge(e);
00831 }
00832 }
00833 }
00834
00835
00836 INT AEQUIV::Backpatch_CFG(GOTO_VERTEX_STACK *goto_stack,
00837 LABEL_STACK *label_stack, LABEL_VERTEX_HASH *label_hash)
00838 {
00839 for (INT i=0; i<goto_stack->Elements(); i++) {
00840 GOTO_VERTEX *gv = &goto_stack->Bottom_nth(i);
00841 WN *goto_wn = gv->_wn;
00842 VINDEX16 goto_v = gv->_vindex;
00843 OPCODE opcode = WN_opcode(goto_wn);
00844 if (opcode == OPC_AGOTO) {
00845 for (INT j=0; j<label_stack->Elements(); j++) {
00846 Add_CFG_Edge(goto_v,label_stack->Bottom_nth(j));
00847 }
00848 } else {
00849 VINDEX16 labelv = label_hash->Find(WN_label_number(goto_wn));
00850 Is_True(labelv,
00851 ("Goto to non-existant label in AEQUIV::Backpatch_CFG"));
00852 if (!Add_CFG_Edge(goto_v,labelv)) return -1;
00853 }
00854 }
00855 return 1;
00856 }
00857
00858
00859
00860 VINDEX16 AEQUIV::Add_CFG_Vertex(BIT_VECTOR *bit_vector) {
00861 VINDEX16 result = _cfg->Add_Vertex();
00862 if (result != 0) {
00863 while (_cyclic_bit_vector->Elements() <= result) {
00864 _cyclic_bit_vector->Push(NULL);
00865 }
00866 _cyclic_bit_vector->Bottom_nth(result) = bit_vector;
00867 }
00868 return result;
00869 }
00870
00871
00872 void AEQUIV::Set_Acyclic()
00873 {
00874 _acfg = _cfg->Acyclic_Condensation(_pool);
00875
00876
00877
00878
00879 _acyclic_bit_vector = CXX_NEW(BIT_VECTOR_STACK(_pool),_pool);
00880 for (VINDEX16 v=_cfg->Get_Vertex(); v; v = _cfg->Get_Next_Vertex(v)) {
00881 VINDEX16 scc = _cfg->Get_Scc_Id(v);
00882 while (_acyclic_bit_vector->Elements() <= scc) {
00883 _acyclic_bit_vector->Push(CXX_NEW(BIT_VECTOR(Num_Arrays(),_pool),_pool));
00884 }
00885 if (_acyclic_bit_vector->Bottom_nth(scc)) {
00886 *(_acyclic_bit_vector->Bottom_nth(scc)) |=
00887 *_cyclic_bit_vector->Bottom_nth(v);
00888 } else {
00889 *(_acyclic_bit_vector->Bottom_nth(scc)) =
00890 *_cyclic_bit_vector->Bottom_nth(v);
00891 }
00892 }
00893 }
00894
00895
00896
00897 void AEQUIV::Do_Dataflow()
00898 {
00899 MEM_POOL_Push(&LNO_local_pool);
00900
00901
00902 INT num_v = _acfg->Get_Vertex_Count();
00903 VINDEX16 *vsorted = CXX_NEW_ARRAY(VINDEX16,num_v,&LNO_local_pool);
00904 _acfg->Level_Sort(vsorted);
00905
00906
00907
00908 BIT_VECTOR_STACK *has_been_ref =
00909 CXX_NEW(BIT_VECTOR_STACK(&LNO_local_pool),&LNO_local_pool);
00910 INT i;
00911 for (i=0; i<num_v; i++) {
00912 VINDEX16 v = vsorted[i];
00913 while (has_been_ref->Elements() <= v) {
00914 has_been_ref->Push(CXX_NEW(BIT_VECTOR(Num_Arrays(),&LNO_local_pool),
00915 &LNO_local_pool));
00916 }
00917
00918
00919 BIT_VECTOR *this_vector = has_been_ref->Bottom_nth(v);
00920 *this_vector = *_acyclic_bit_vector->Bottom_nth(v);
00921
00922
00923 EINDEX16 e = _acfg->Get_In_Edge(v);
00924 while (e) {
00925 VINDEX16 pred = _acfg->Get_Source(e);
00926 *this_vector |= *has_been_ref->Bottom_nth(pred);
00927 e = _acfg->Get_Next_In_Edge(e);
00928 }
00929 }
00930
00931
00932
00933 BIT_VECTOR_STACK *still_ref =
00934 CXX_NEW(BIT_VECTOR_STACK(&LNO_local_pool),&LNO_local_pool);
00935 for (i=num_v-1; i>=0; i--) {
00936 VINDEX16 v = vsorted[i];
00937 while (still_ref->Elements() <= v) {
00938 still_ref->Push(CXX_NEW(BIT_VECTOR(Num_Arrays(),&LNO_local_pool),
00939 &LNO_local_pool));
00940 }
00941
00942
00943 BIT_VECTOR *this_vector = still_ref->Bottom_nth(v);
00944 *this_vector = *_acyclic_bit_vector->Bottom_nth(v);
00945
00946
00947 EINDEX16 e = _acfg->Get_Out_Edge(v);
00948 while (e) {
00949 VINDEX16 succ = _acfg->Get_Sink(e);
00950 *this_vector |= *still_ref->Bottom_nth(succ);
00951 e = _acfg->Get_Next_Out_Edge(e);
00952 }
00953 }
00954
00955
00956 for (i=0; i<num_v; i++) {
00957 VINDEX16 v = vsorted[i];
00958 *_acyclic_bit_vector->Bottom_nth(v) = *has_been_ref->Bottom_nth(v) &
00959 *still_ref->Bottom_nth(v);
00960 }
00961
00962 MEM_POOL_Pop(&LNO_local_pool);
00963 }
00964
00965
00966
00967
00968 void AEQUIV::Set_Array_Bit_Vector()
00969 {
00970 INT num_v = _acfg->Get_Vertex_Count();
00971 INT num_a = Num_Arrays();
00972
00973
00974 _array_bit_vector = CXX_NEW(BIT_VECTOR_STACK(_pool),_pool);
00975 INT i;
00976 for (i=0; i<num_a; i++) {
00977 _array_bit_vector->Push(CXX_NEW(BIT_VECTOR(num_v,_pool),_pool));
00978 }
00979
00980
00981 for (VINDEX16 v=_acfg->Get_Vertex(); v; v = _acfg->Get_Next_Vertex(v)) {
00982 BIT_VECTOR *ac_bit_vector = _acyclic_bit_vector->Bottom_nth(v);
00983 for (i=0; i<num_a; i++) {
00984 if (ac_bit_vector->Test(i)) {
00985 _array_bit_vector->Bottom_nth(i)->Set(v-1);
00986 }
00987 }
00988 }
00989 }
00990
00991
00992
00993
00994
00995
00996
00997
00998 BOOL AEQUIV::Do_Color(mBOOL *equivalenced_array)
00999 {
01000 BOOL result = FALSE;
01001 MEM_POOL_Push(&LNO_local_pool);
01002 INT num_array = Num_Arrays();
01003 mBOOL *did_color = CXX_NEW_ARRAY(mBOOL,num_array,&LNO_local_pool);
01004 BIT_VECTOR *bv = CXX_NEW(BIT_VECTOR(_acfg->Get_Vertex_Count(),
01005 &LNO_local_pool),&LNO_local_pool);
01006
01007
01008 INT i;
01009 for (i=0; i<num_array; i++) {
01010 LOCAL_ARRAY_DESC *lad = _la_hash_table->Find(_la_stack->Bottom_nth(i));
01011 if (lad->_address_taken) {
01012 did_color[i] = TRUE;
01013 equivalenced_array[i] = FALSE;
01014 } else if (!lad->_is_read) {
01015 result = TRUE;
01016 did_color[i] = TRUE;
01017 equivalenced_array[i] = TRUE;
01018 Set_ST_is_not_used(_la_stack->Bottom_nth(i));
01019 if (Get_Trace(TP_LNOPT,TT_LNO_AEQUIV)) {
01020 fprintf(TFile,"eliminating all references to array %d \n",i);
01021 }
01022 } else {
01023 did_color[i] = FALSE;
01024 equivalenced_array[i] = FALSE;
01025 }
01026 }
01027
01028 for (i=0; i<num_array; i++) {
01029 if (!did_color[i]) {
01030 *bv = *_array_bit_vector->Bottom_nth(i);
01031 did_color[i] = TRUE;
01032 for (INT j=0; j<num_array; j++) {
01033 if (!did_color[j]) {
01034 if (!bv->Intersects(_array_bit_vector->Bottom_nth(j))) {
01035
01036 result = TRUE;
01037 St_Block_Union(_la_stack->Bottom_nth(i),_la_stack->Bottom_nth(j));
01038 *bv |= *_array_bit_vector->Bottom_nth(j);
01039 did_color[j] = TRUE;
01040 equivalenced_array[i] = TRUE;
01041 equivalenced_array[j] = TRUE;
01042 if (Get_Trace(TP_LNOPT,TT_LNO_AEQUIV)) {
01043 fprintf(TFile,"equivalencing arrays %d and %d\n",i,j);
01044 }
01045 }
01046 }
01047 }
01048 }
01049 }
01050 MEM_POOL_Pop(&LNO_local_pool);
01051 return result;
01052 }
01053
01054
01055
01056
01057 void AEQUIV::Update_Code(WN *wn,mBOOL *equivalenced_array)
01058 {
01059 OPCODE opcode = WN_opcode(wn);
01060 OPERATOR oper = OPCODE_operator(opcode);
01061 if (opcode == OPC_BLOCK) {
01062 WN *kid = WN_first(wn);
01063 while (kid) {
01064 Update_Code(kid,equivalenced_array);
01065 kid = WN_next(kid);
01066 }
01067 } else if ((OPCODE_is_store(opcode) || OPCODE_is_prefetch(opcode)) &&
01068 (Contains_Unread_Array(wn,equivalenced_array))) {
01069 LWN_Delete_Tree(wn);
01070 } else if (oper == OPR_LDA) {
01071 LOCAL_ARRAY_DESC *lad = _la_hash_table->Find(WN_st(wn));
01072 if (lad && equivalenced_array[lad->_id]) {
01073
01074
01075 Note_Invalid_IP_Alias_Class(Alias_Mgr, wn);
01076
01077 WN *tmp = LWN_Get_Parent(wn);
01078 while (tmp) {
01079 OPCODE opc_tmp = WN_opcode(tmp);
01080 if (OPCODE_is_store(opc_tmp) || OPCODE_is_load(opc_tmp)) {
01081 Create_alias(Alias_Mgr,tmp);
01082
01083
01084
01085
01086
01087 break;
01088 }
01089 tmp = LWN_Get_Parent(tmp);
01090 }
01091 }
01092 } else if (oper == OPR_PRAGMA &&
01093 (WN_pragma(wn) == WN_PRAGMA_LASTLOCAL ||
01094 WN_pragma(wn) == WN_PRAGMA_LOCAL)) {
01095 ST *st = WN_st(wn);
01096 LOCAL_ARRAY_DESC *lad = _la_hash_table->Find(st);
01097 if (lad &&
01098 !lad->_address_taken &&
01099 equivalenced_array[lad->_id] &&
01100 !lad->_is_read) {
01101 LWN_Delete_Tree(wn);
01102 }
01103 } else {
01104 for (INT kidno=0; kidno < WN_kid_count(wn); kidno++) {
01105 Update_Code(WN_kid(wn,kidno),equivalenced_array);
01106 }
01107 }
01108 }
01109
01110
01111 BOOL AEQUIV::Contains_Unread_Array(WN *wn,mBOOL *equivalenced_array)
01112 {
01113 OPCODE opcode = WN_opcode(wn);
01114 OPERATOR oper = OPCODE_operator(opcode);
01115 if (oper == OPR_LDA) {
01116 LOCAL_ARRAY_DESC *lad = _la_hash_table->Find(WN_st(wn));
01117 if (lad && !lad->_address_taken) {
01118 if (equivalenced_array[lad->_id]) {
01119 if (!lad->_is_read) {
01120 return TRUE;
01121 }
01122 }
01123 }
01124 }
01125 for (INT kidno=0; kidno < WN_kid_count(wn); kidno++) {
01126 if (Contains_Unread_Array(WN_kid(wn,kidno),equivalenced_array)) {
01127 return TRUE;
01128 }
01129 }
01130 return FALSE;
01131 }
01132