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 #define __STDC_LIMIT_MACROS
00062 #include <stdint.h>
00063 #ifdef USE_PCH
00064 #include "lno_pch.h"
00065 #endif // USE_PCH
00066 #pragma hdrstop
00067
00068 #include <sys/types.h>
00069 #include <limits.h>
00070 #include "pu_info.h"
00071 #include "ara_loop.h"
00072 #include "stab.h"
00073 #include "stblock.h"
00074 #include "lwn_util.h"
00075 #include "opt_alias_interface.h"
00076 #include "opt_du.h"
00077 #include "config.h"
00078 #include "snl_xbounds.h"
00079 #include "debug.h"
00080 #include "parmodel.h"
00081 #include "parids.h"
00082 #include "ara_utils.h"
00083
00084 static void Add_Symbol_To_Use(WN* wn_sym,
00085 ARA_LOOP_INFO* ali)
00086 {
00087 ST* st_sym = WN_st(wn_sym);
00088 if (st_sym == NULL)
00089 return;
00090 TY_IDX ty_idx_sym = ST_type(st_sym);
00091 if (TY_kind(ty_idx_sym) == KIND_POINTER)
00092 ty_idx_sym = TY_pointed(ty_idx_sym);
00093 if (TY_kind(ty_idx_sym) == KIND_ARRAY) {
00094 SYMBOL sym_array(wn_sym);
00095 REGION* rg_array = CXX_NEW(REGION(0, 0), &ARA_memory_pool);
00096 rg_array->_type = ARA_TOP;
00097 ARA_REF* ref_new = CXX_NEW(ARA_REF(&sym_array, rg_array, ali, TRUE),
00098 &ARA_memory_pool);
00099 ali->Add_Use(ref_new);
00100 } else if (WN_operator(wn_sym) == OPR_LDID || WN_operator(wn_sym) ==
00101 OPR_STID) {
00102 ali->SCALAR_USE().Add_Scalar(wn_sym, 0);
00103 } else if (WN_operator(wn_sym) == OPR_LDA) {
00104 SYMBOL sym(WN_st(wn_sym), 0, TY_mtype(ST_type(WN_st(wn_sym))));
00105 ali->SCALAR_USE().Add_Scalar(wn_sym, &sym, 0);
00106 }
00107 }
00108
00109 static void Add_Symbols_To_Uses_Traverse(WN* wn_tree,
00110 ARA_LOOP_INFO* ali)
00111 {
00112 if (OPCODE_has_sym(WN_opcode(wn_tree)))
00113 Add_Symbol_To_Use(wn_tree, ali);
00114 for (INT i = 0; i < WN_kid_count(wn_tree); i++)
00115 Add_Symbols_To_Uses_Traverse(WN_kid(wn_tree, i), ali);
00116 }
00117
00118 static void Add_Symbols_To_Uses(WN* wn_node,
00119 ARA_LOOP_INFO* ali)
00120 {
00121 Add_Symbols_To_Uses_Traverse(wn_node, ali);
00122 }
00123
00124
00125
00126
00127
00128
00129
00130 void
00131 ARA_LOOP_INFO::Default_For_Bad_Loop()
00132 {
00133
00134
00135 for (INT i = 0; i < _children.Elements(); ++i)
00136 _children.Bottom_nth(i)->Walk_Loop();
00137
00138
00139 LWN_ITER * stmt_iter;
00140 if (WN_operator(_loop) == OPR_FUNC_ENTRY)
00141 stmt_iter = LWN_WALK_StmtIter(WN_func_body(_loop));
00142 else
00143 stmt_iter = LWN_WALK_StmtIter(_loop);
00144
00145
00146 if (WN_operator(_loop) == OPR_DO_LOOP)
00147 stmt_iter = LWN_WALK_StmtNext(stmt_iter);
00148
00149
00150 WN *skip_store_id = NULL;
00151
00152 while (stmt_iter) {
00153
00154 WN *stmt = stmt_iter->wn;
00155 stmt_iter = LWN_WALK_StmtNext(stmt_iter);
00156 OPERATOR opr = WN_operator(stmt);
00157
00158 if (opr == OPR_DO_LOOP) {
00159
00160 DO_LOOP_INFO* dli = Get_Do_Loop_Info(stmt);
00161
00162 Is_True(dli, ("ARA_LOOP_INFO::Walk_Loop: No DO_LOOP_INFO for this loop"));
00163 ARA_LOOP_INFO* ali = dli->ARA_Info;
00164 Is_True(ali, ("ARA_LOOP_INFO::Walk_Loop: No ARA_LOOP_INFO for this loop"));
00165
00166 for (INT i = 0; i < ali->_use.Elements(); ++i) {
00167 ARA_REF *cur_clone = CXX_NEW(ARA_REF(*(ali->_use.Bottom_nth(i))), &ARA_memory_pool);
00168 Add_Use(cur_clone);
00169 }
00170
00171
00172 Merge_Scalar_List(&ali->_scalar_use, &_scalar_use);
00173
00174
00175
00176 do
00177 stmt_iter = LWN_WALK_StmtNext(stmt_iter);
00178 while (stmt_iter && Wn_Is_Inside(stmt_iter->wn,stmt));
00179
00180 continue;
00181
00182 } else if (opr == OPR_IO) {
00183
00184 Add_Symbols_To_Uses(stmt, this);
00185
00186 } else if ((opr == OPR_ISTORE) &&
00187 (WN_operator(WN_kid1(stmt)) == OPR_ARRAY)) {
00188
00189
00190 WN* lfs = WN_kid1(stmt);
00191
00192 skip_store_id = WN_kid0(lfs);
00193
00194 } else if (opr == OPR_STID) {
00195
00196 _scalar_def.Add_Scalar(stmt, 0);
00197 _scalar_may_def.Add_Scalar(stmt, 0);
00198 for (WN* wn = stmt; wn != NULL; wn = LWN_Get_Parent(wn)) {
00199 if (WN_operator(wn) == OPR_DO_LOOP
00200 && SYMBOL(WN_index(wn)) == SYMBOL(stmt)) {
00201 _scalar_def.Add_Scalar(stmt, 0);
00202 _scalar_may_def.Add_Scalar(stmt, 0);
00203 }
00204 }
00205
00206 } else if (OPCODE_is_scf(WN_opcode(stmt)))
00207 continue;
00208
00209
00210 LWN_ITER* rhs =
00211 LWN_WALK_TreeIter(stmt);
00212
00213 while (rhs) {
00214
00215 WN* wn = rhs->wn;
00216 rhs = LWN_WALK_TreeNext(rhs);
00217 if (wn == skip_store_id) {
00218 wn = rhs->wn;
00219 rhs = LWN_WALK_TreeNext(rhs);
00220 skip_store_id = NULL;
00221 }
00222
00223 if ((WN_operator(wn) == OPR_ILOAD) &&
00224 (WN_operator(WN_kid0(wn)) == OPR_ARRAY)) {
00225 ARA_REF *new_use = CXX_NEW(ARA_REF(WN_kid0(wn),WN_offset(wn),this),
00226 &ARA_memory_pool);
00227 if (new_use->Has_Bad_Alias())
00228 CXX_DELETE(new_use, &ARA_memory_pool);
00229 else
00230 Add_Use(new_use);
00231
00232
00233 rhs = LWN_WALK_TreeNext(rhs);
00234 rhs = LWN_WALK_TreeNext(rhs);
00235
00236 } else if (WN_operator(wn) == OPR_LDID) {
00237
00238 if (Is_Covered(wn))
00239 _scalar_pri.Add_Scalar(wn,0);
00240 else
00241 _scalar_use.Add_Scalar(wn,0);
00242
00243 }
00244
00245 }
00246
00247 }
00248
00249 }
00250
00251
00252
00253
00254
00255
00256 void
00257 ARA_LOOP_INFO::Create_Live_Use()
00258 {
00259
00260 Is_True(_live_use==NULL,("ARA_LOOP_INFO::Create_Live_Use(): It already exists"));
00261
00262 if (_live_use) CXX_DELETE(_live_use,&ARA_memory_pool);
00263
00264
00265 INT i;
00266 for (i = 0; i < _children.Elements(); ++ i) {
00267 _children.Bottom_nth(i)->Create_Live_Use();
00268 }
00269
00270 #if 0
00271
00272 if (WN_opcode(_loop) != OPC_DO_LOOP) {
00273 Default_For_Bad_Loop();
00274 }
00275 #endif
00276
00277 _live_use = CXX_NEW(S_HTABLE(_use.Elements()+1,&ARA_memory_pool),&ARA_memory_pool);
00278 for (i = 0; i < _use.Elements(); ++ i) {
00279 ST* st = _use.Bottom_nth(i)->Array().St();
00280 _live_use->Enter(st,TRUE);
00281 }
00282
00283 }
00284
00285
00286
00287
00288
00289
00290
00291
00292 void
00293 ARA_LOOP_INFO::Determine_Last_Value()
00294 {
00295
00296 INT i;
00297 for (i = 0; i < _children.Elements(); ++i) {
00298 _children.Bottom_nth(i)->Determine_Last_Value();
00299 }
00300
00301 for (i = 0; i < _pri.Elements(); ++ i) {
00302 ARA_REF *ara = _pri.Bottom_nth(i);
00303 Is_True(ara->Need_Last_Value(),
00304 ("unexpected FALSE ara->Need_Last_Value()"));
00305
00306 if (!ara->Has_Bad_Alias() &&
00307 ara->Need_Last_Value() &&
00308 ara->Is_Loop_Invariant()) {
00309 ST* st = ara->Array().St();
00310 if (ST_class(st) == CLASS_VAR &&
00311 ST_sclass(st) == SCLASS_AUTO &&
00312 ST_base_idx(st) == ST_st_idx(st) &&
00313 ST_addr_not_saved(st) &&
00314 ST_addr_not_passed(st) &&
00315 TY_size(ST_type(st)) > 0 &&
00316 !ST_is_initialized(st) &&
00317 !ST_has_nested_ref(st) &&
00318 !ST_is_reshaped(st) &&
00319 TY_kind(ST_type(st)) == KIND_ARRAY) {
00320 for (ARA_LOOP_INFO *cur_p = _parent; cur_p; cur_p = cur_p->_parent) {
00321 if (cur_p->_live_use->Find(st)) {
00322 _has_last_value_array = TRUE;
00323 goto next_pri;
00324 }
00325 }
00326
00327
00328
00329 ara->Set_No_Last_Value();
00330
00331 next_pri:
00332 continue;
00333
00334 } else
00335 _has_last_value_array = TRUE;
00336 }
00337 }
00338
00339 for (i = 0; i < _def.Elements(); ++ i) {
00340 if (_def.Bottom_nth(i)->Is_Loop_Invariant() &&
00341 !_def.Bottom_nth(i)->Is_Whole_Array() &&
00342 !Overlap_Local_Array(_def.Bottom_nth(i)->Array()) &&
00343 !Overlap_Exposed_Array(_def.Bottom_nth(i)->Array())) {
00344 ST* st = _def.Bottom_nth(i)->Array().St();
00345 #ifdef _NEW_SYMTAB
00346 if (ST_class(st) == CLASS_VAR &&
00347 (ST_sclass(st) == SCLASS_AUTO) &&
00348 ST_addr_not_saved(st) &&
00349 ST_addr_not_passed(st) &&
00350 (TY_size(ST_type(st)) > 0) &&
00351 (!ST_is_initialized(st)) &&
00352 !ST_has_nested_ref(st) &&
00353 (!ST_is_reshaped(st)) &&
00354 #else
00355 if (ST_symclass(st) == CLASS_VAR &&
00356 (ST_sclass(st) == SCLASS_AUTO) &&
00357 !ST_addr_taken_saved(st) && !ST_addr_taken_passed(st) &&
00358 (ST_size(st)>0) &&
00359 (!ST_is_initialized(st)) &&
00360 !ST_has_nested_ref(st) &&
00361 (!ST_is_reshaped(st)) &&
00362 #endif
00363 (TY_kind(ST_type(st)) == KIND_ARRAY)) {
00364 ARA_LOOP_INFO *cur_p = _parent;
00365 while (cur_p) {
00366
00367 if (cur_p->_live_use->Find(st)) {
00368 _has_last_value_array = TRUE;
00369 goto next_def;
00370 }
00371
00372 cur_p = cur_p->_parent;
00373 }
00374
00375 next_def:
00376 continue;
00377
00378 } else
00379 _has_last_value_array = TRUE;
00380 }
00381 }
00382
00383 for (i = 0; i < _scalar_pri.Elements(); ++ i) {
00384 BOOL need_last_value = TRUE;
00385 SCALAR_NODE *s_pri = _scalar_pri.Bottom_nth(i);
00386 for (INT j = 0; j < _scalar_may_def.Elements(); ++j)
00387 if (s_pri->_scalar ==
00388 _scalar_may_def.Bottom_nth(j)->_scalar) {
00389
00390 need_last_value = FALSE;
00391 SCALAR_NODE *sn = _scalar_may_def.Bottom_nth(j);
00392
00393 for (INT k = 0; k < sn->Elements(); ++k) {
00394 WN* def = sn->Bottom_nth(k)->Wn;
00395 USE_LIST *use_list = Du_Mgr->Du_Get_Use(def);
00396
00397 if (use_list && use_list->Incomplete()) {
00398 need_last_value = TRUE;
00399 goto break_point;
00400 }
00401
00402 USE_LIST_ITER iter_use(use_list);
00403
00404 for (DU_NODE* use_node = iter_use.First(); !iter_use.Is_Empty();
00405 use_node = (DU_NODE *) iter_use.Next()) {
00406 WN *use = use_node->Wn();
00407 if (!Wn_Is_Inside(use,_loop)) {
00408 need_last_value = TRUE;
00409 goto break_point;
00410 }
00411 }
00412
00413 }
00414 }
00415
00416 break_point:
00417 _scalar_last_value.Push(need_last_value);
00418
00419 if (need_last_value) {
00420 INT i;
00421 for (i = 0; i < _scalar_def.Elements(); ++i) {
00422 if (s_pri->_scalar == _scalar_def.Bottom_nth(i)->_scalar)
00423 break;
00424 }
00425 if (i == _scalar_def.Elements()) {
00426 if (Run_prompf || LNO_Prompl) {
00427 INT j;
00428 for (j = 0; j < _scalar_no_final.Elements(); j++)
00429 if (_scalar_no_final.Bottom_nth(j) == s_pri->_scalar)
00430 break;
00431 if (j == _scalar_no_final.Elements())
00432 _scalar_no_final.Push(s_pri->_scalar);
00433 }
00434 Set_To_Sequential();
00435 }
00436 }
00437 }
00438
00439 for (INT j = 0; j < _scalar_may_def.Elements(); ++j) {
00440 SCALAR_NODE *sn = _scalar_may_def.Bottom_nth(j);
00441 if (!Overlap_Kill_Scalar(sn->_scalar)) {
00442 BOOL need_last_value = FALSE;
00443 for (INT k = 0; k < sn->Elements(); ++k) {
00444 WN* def = sn->Bottom_nth(k)->Wn;
00445
00446 if (red_manager && red_manager->Which_Reduction(def) != RED_NONE) {
00447 continue;
00448 }
00449
00450 USE_LIST *use_list = Du_Mgr->Du_Get_Use(def);
00451
00452 if (use_list && use_list->Incomplete()) {
00453 need_last_value = TRUE;
00454 goto break_point1;
00455 }
00456
00457 USE_LIST_ITER iter_use(use_list);
00458
00459 for (DU_NODE* use_node = iter_use.First(); !iter_use.Is_Empty();
00460 use_node = (DU_NODE *) iter_use.Next()) {
00461 WN *use = use_node->Wn();
00462 if (!Wn_Is_Inside(use,_loop)) {
00463 need_last_value = TRUE;
00464 goto break_point1;
00465 }
00466 }
00467 }
00468
00469 break_point1:
00470
00471 if (need_last_value) {
00472 if (Run_prompf || LNO_Prompl) {
00473 INT j;
00474 for (j = 0; j < _scalar_no_final.Elements(); j++)
00475 if (_scalar_no_final.Bottom_nth(j) == sn->_scalar)
00476 break;
00477 if (j == _scalar_no_final.Elements())
00478 _scalar_no_final.Push(sn->_scalar);
00479 }
00480 Set_To_Sequential();
00481 }
00482 }
00483 }
00484
00485 }
00486
00487
00488
00489
00490
00491
00492
00493 static STACK<WN*>* Scalar_Defs(SYMBOL* sym,
00494 WN* wn_loop)
00495 {
00496 STACK<WN*>* st_def = CXX_NEW(STACK<WN*>(&ARA_memory_pool), &ARA_memory_pool);
00497 LWN_ITER* itr = LWN_WALK_TreeIter(wn_loop);
00498 for (; itr != NULL; itr = LWN_WALK_TreeNext(itr)) {
00499 WN* wn = itr->wn;
00500 if (WN_operator(wn) == OPR_STID
00501 && SYMBOL(wn) == *sym)
00502 st_def->Push(wn);
00503 }
00504 return st_def;
00505 }
00506
00507
00508
00509
00510
00511
00512
00513 static STACK<WN*>* Array_Defs(SYMBOL* sym,
00514 WN* wn_loop)
00515 {
00516 STACK<WN*>* st_def = CXX_NEW(STACK<WN*>(&ARA_memory_pool), &ARA_memory_pool);
00517 LWN_ITER* itr = LWN_WALK_TreeIter(wn_loop);
00518 for (; itr != NULL; itr = LWN_WALK_TreeNext(itr)) {
00519 WN* wn = itr->wn;
00520 if (WN_operator(wn) == OPR_ISTORE
00521 && WN_operator(WN_kid1(wn)) == OPR_ARRAY
00522 && SYMBOL(WN_kid0(WN_kid1(wn))) == *sym)
00523 st_def->Push(wn);
00524 }
00525 return st_def;
00526 }
00527
00528
00529
00530
00531
00532
00533
00534 static BOOL Scalar_Def_Covered_In_Loop(WN* wn_def,
00535 WN* wn_loop)
00536 {
00537 WN* wn_first = LWN_Get_Parent(wn_def);
00538 for (WN* wnn = wn_first; wnn != wn_loop; wnn = LWN_Get_Parent(wnn)) {
00539 for (WN* wn = wnn; wn != NULL; wn = WN_prev(wn))
00540 if (WN_operator(wn) == OPR_STID
00541 && SYMBOL(wn) == SYMBOL(wn_def))
00542 return TRUE;
00543 }
00544 return FALSE;
00545 }
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555 static BOOL Always_Executes(SNL_BOUNDS_INFO* ebounds,
00556 WN* wn_loop,
00557 INT dimlb,
00558 INT dimub)
00559 {
00560 DO_LOOP_INFO* dli = Get_Do_Loop_Info(wn_loop);
00561 INT loop_depth = Do_Depth(wn_loop);
00562 ACCESS_VECTOR* avlb = dli->LB->Dim(dimlb);
00563 ACCESS_VECTOR* avub = dli->UB->Dim(dimub);
00564 if (avlb->Too_Messy || avub->Too_Messy)
00565 return FALSE;
00566 ACCESS_VECTOR* nox = Difference_Inequality(avlb, avub, loop_depth,
00567 DIFFERENCE_EXEC_NEVER, &ARA_memory_pool);
00568 ebounds->Add_Access(nox, FALSE);
00569 BOOL is_consistent = ebounds->Bounds().Is_Consistent();
00570 return !is_consistent;
00571 }
00572
00573
00574
00575
00576
00577
00578
00579
00580 static BOOL Peelable(WN* wn_outer,
00581 WN* wn_loop,
00582 INT peeled_iterations)
00583 {
00584 if (peeled_iterations == 0)
00585 return TRUE;
00586 INT outer_depth = Do_Depth(wn_outer);
00587 DO_LOOP_INFO* dli_outer = Get_Do_Loop_Info(wn_outer);
00588 DO_LOOP_INFO* dli_loop = Get_Do_Loop_Info(wn_loop);
00589 return dli_outer->UB->Num_Vec() == 1
00590 && dli_loop->LB->Num_Vec() == 1 && dli_loop->UB->Num_Vec() == 1
00591 && dli_outer->UB->Dim(0)->Loop_Coeff(outer_depth) == 1;
00592 }
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604 static INT Convex_Peeling_Depth(WN* wn_def,
00605 WN* wn_outer)
00606 {
00607 const INT Peel_Max = 2;
00608 WN* wn_inner = Enclosing_Do_Loop(wn_def);
00609 DOLOOP_STACK stack(&ARA_memory_pool);
00610 Build_Doloop_Stack(wn_inner, &stack);
00611 INT outer_depth = Do_Loop_Depth(wn_outer);
00612 INT inner_depth = Do_Loop_Depth(wn_inner);
00613 INT i;
00614 for (i = outer_depth + 1; i <= inner_depth; i++)
00615 if (!SNL_Is_Invariant(&stack, outer_depth, i))
00616 break;
00617 if (i == inner_depth + 1)
00618 return 0;
00619 DO_LOOP_INFO** dli = CXX_NEW_ARRAY(DO_LOOP_INFO*, inner_depth + 1,
00620 &ARA_memory_pool);
00621 for (i = 0; i <= inner_depth; i++)
00622 dli[i] = Get_Do_Loop_Info(stack.Bottom_nth(i));
00623 INT peel = 0;
00624 INT k;
00625 for (k = 0; k <= Peel_Max; k++) {
00626 SNL_BOUNDS_INFO ebounds_peel(&ARA_memory_pool);
00627 ebounds_peel.Outermost_Depth() = outer_depth;
00628 ebounds_peel.Collect_Outer_Info(wn_outer);
00629 INT i;
00630 for (i = 0; i < dli[outer_depth]->LB->Num_Vec(); i++) {
00631 ACCESS_VECTOR* lb = dli[outer_depth]->LB->Dim(i);
00632 ACCESS_VECTOR first_iter(lb, &ARA_memory_pool);
00633 ebounds_peel.Add_Access(&first_iter, FALSE);
00634 }
00635 for (i = 0; i < dli[outer_depth]->UB->Num_Vec(); i++) {
00636 ACCESS_VECTOR* ub = dli[outer_depth]->UB->Dim(i);
00637 ACCESS_VECTOR last_iter(ub, &ARA_memory_pool);
00638 last_iter.Const_Offset -= k;
00639 ebounds_peel.Add_Access(&last_iter, FALSE);
00640 last_iter.Negate_Me();
00641 ebounds_peel.Add_Access(&last_iter, FALSE);
00642 }
00643 BOOL pbreak = FALSE;
00644 for (i = outer_depth + 1; !pbreak && i <= inner_depth; i++) {
00645 WN* wn_loop = stack.Bottom_nth(i);
00646 for (INT dimlb = 0; !pbreak && dimlb < dli[i]->LB->Num_Vec(); dimlb++)
00647 for(INT dimub = 0; !pbreak && dimub < dli[i]->UB->Num_Vec(); dimub++)
00648 if (!Peelable(wn_outer, wn_loop, k)
00649 || !Always_Executes(&ebounds_peel, wn_loop, dimlb, dimub))
00650 pbreak = TRUE;
00651 }
00652 if (!pbreak)
00653 return k;
00654 }
00655 return -1;
00656 }
00657
00658
00659
00660
00661
00662
00663
00664 static BOOL Invariant_Loops(WN* wn_loop)
00665 {
00666 if (WN_opcode(wn_loop) != OPC_DO_LOOP)
00667 return TRUE;
00668 INT outer_depth = Do_Depth(wn_loop);
00669 LWN_ITER* itr = LWN_WALK_TreeIter(wn_loop);
00670 for (; itr != NULL; itr = LWN_WALK_TreeNext(itr)) {
00671 WN* wn = itr->wn;
00672 if (WN_opcode(wn) == OPC_DO_LOOP) {
00673 DO_LOOP_INFO* dli = Get_Do_Loop_Info(wn);
00674 if (dli->Is_Inner) {
00675 DOLOOP_STACK stack(&ARA_memory_pool);
00676 Build_Doloop_Stack(wn, &stack);
00677 INT inner_depth = Do_Loop_Depth(wn);
00678 INT i;
00679 for (i = 0; i <= inner_depth; i++)
00680 if (!Upper_Bound_Standardize(WN_end(stack.Bottom_nth(i)), TRUE))
00681 return FALSE;
00682 INT nloops = inner_depth - outer_depth + 1;
00683 for (i = 2; i <= nloops; i++) {
00684 INT d = inner_depth + 1 - i;
00685 for (INT dd = d + 1; dd <= inner_depth; dd++)
00686 if (!SNL_Is_Invariant(&stack, d, dd))
00687 return FALSE;
00688 }
00689 }
00690 }
00691 }
00692 return TRUE;
00693 }
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707 void ARA_LOOP_INFO::Determine_Peel()
00708 {
00709 INT peel = 0;
00710 INT i;
00711 INT save_peel_value = _peel_value;
00712 _peel_value = 0;
00713 if (!Is_OK_Parallel()) {
00714 _peel_value = save_peel_value;
00715 peel = _peel_value;
00716 goto check_kids;
00717 }
00718 if (Invariant_Loops(_loop)) {
00719 peel = 0;
00720 goto check_kids;
00721 }
00722 for (i = 0; i < _scalar_pri.Elements(); i++) {
00723 if (_scalar_last_value.Bottom_nth(i)) {
00724 SYMBOL sym = _scalar_pri.Bottom_nth(i)->_scalar;
00725 STACK<WN*>* stk_sdef = Scalar_Defs(&sym, _loop);
00726 for (INT j = 0; j < stk_sdef->Elements(); j++) {
00727 WN* wn = stk_sdef->Bottom_nth(j);
00728 if (Scalar_Def_Covered_In_Loop(wn, _loop))
00729 continue;
00730 INT local_peel = Convex_Peeling_Depth(wn, _loop);
00731 if (local_peel == -1) {
00732 peel = -1;
00733 if (Run_prompf || LNO_Prompl) {
00734 SYMBOL* sym = CXX_NEW(SYMBOL(wn), &ARA_memory_pool);
00735 Scalar_Bad_Peel().Push(*sym);
00736 Ln_Scalar_Bad_Peel().Push(WN_Whirl_Linenum(wn));
00737 } else
00738 goto check_kids;
00739 }
00740 if (local_peel == 0)
00741 continue;
00742 if (local_peel > peel)
00743 peel = local_peel;
00744 }
00745 }
00746 }
00747 for (i = 0; i < _pri.Elements(); i++) {
00748 ARA_REF* ara_ref = _pri.Bottom_nth(i);
00749 if (ara_ref->Is_Loop_Invariant() && !ara_ref->Is_Unknown_Size()
00750 && ara_ref->Need_Last_Value()) {
00751 SYMBOL sym = ara_ref->Array();
00752 STACK<WN*>* stk_adef = Array_Defs(&sym, _loop);
00753 for (INT j = 0; j < stk_adef->Elements(); j++) {
00754 WN* wn = stk_adef->Bottom_nth(j);
00755 INT local_peel = Convex_Peeling_Depth(wn, _loop);
00756 if (local_peel == -1) {
00757 peel = -1;
00758 if (Run_prompf || LNO_Prompl) {
00759 Dep_Bad_Peel().Push(SYMBOL(WN_Array_Symbol(wn)));
00760 Ln_Dep_Bad_Peel().Push(WN_Whirl_Linenum(wn));
00761 } else
00762 goto check_kids;
00763 }
00764 if (local_peel == 0)
00765 continue;
00766 if (local_peel > peel)
00767 peel = local_peel;
00768 }
00769 }
00770 }
00771
00772 check_kids:
00773
00774 _peel_value = peel;
00775
00776
00777 if (WN_opcode(_loop) == OPC_DO_LOOP) {
00778 DO_LOOP_INFO* dli = Get_Do_Loop_Info(_loop);
00779 if (_peel_value >= 0 && !dli->Suggested_Parallel) {
00780 WN* wn_first = LWN_Get_Parent(_loop);
00781 for (WN* wn = wn_first; wn != NULL; wn = LWN_Get_Parent(wn)) {
00782 if (WN_opcode(wn) == OPC_DO_LOOP) {
00783 DO_LOOP_INFO* dli_loop = Get_Do_Loop_Info(wn);
00784 if (dli_loop->Suggested_Parallel) {
00785 if (dli_loop->ARA_Info != NULL
00786 && dli_loop->ARA_Info->_peel_value == -1) {
00787 dli->Suggested_Parallel = TRUE;
00788 double work_estimate = 0;
00789 INT nloops = SNL_Loop_Count(_loop);
00790 double machine_cycles = SNL_Machine_Cost(_loop, nloops, 0, NULL,
00791 &work_estimate, TRUE);
00792 dli->Work_Estimate = work_estimate;
00793 if (Get_Trace(TP_LNOPT2, TT_LNO_PARALLEL_DEBUG))
00794 fprintf(stdout,
00795 "Convex Problem: Parallelizing %s instead of %s\n",
00796 WB_Whirl_Symbol(_loop), WB_Whirl_Symbol(wn));
00797 }
00798 }
00799 break;
00800 }
00801 }
00802 }
00803 }
00804
00805 for (i = 0; i < Children().Elements(); ++i)
00806 Children().Bottom_nth(i)->Determine_Peel();
00807 }