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 #ifdef USE_PCH
00039 #include "lno_pch.h"
00040 #endif // USE_PCH
00041 #pragma hdrstop
00042
00043 #include <sys/types.h>
00044 #include <ctype.h>
00045 #include <limits.h>
00046 #include <alloca.h>
00047
00048 #include "pu_info.h"
00049 #include "opt_du.h"
00050 #include "lego_util.h"
00051 #include "lego_opts.h"
00052 #include "lnoutils.h"
00053 #include "lego_pragma.h"
00054 #include "lwn_util.h"
00055 #include "lego_affinity.h"
00056 #include "lnopt_main.h"
00057 #include "snl_utils.h"
00058
00059
00060
00061
00062
00063
00064
00065 static void Do_Loop_Explicit_Affinity (WN* loop);
00066 static void Do_Loop_Implicit_Affinity (WN* loop);
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077 static void Whack_Do_Loops_Traverse(WN* wn_tree)
00078 {
00079 if (WN_opcode(wn_tree) == OPC_DO_LOOP) {
00080 DO_LOOP_INFO* dli = Get_Do_Loop_Info(wn_tree);
00081 Is_True(dli, ("No DO_LOOP_INFO for this loop"));
00082 LEGO_INFO* li = dli->Lego_Info;
00083 if (li)
00084 Do_Loop_Explicit_Affinity(wn_tree);
00085 else
00086 Do_Loop_Implicit_Affinity(wn_tree);
00087 if (Debug_Lego && dli->Lego_Info)
00088 (dli->Lego_Info)->Print(stdout);
00089 }
00090
00091 if (WN_opcode(wn_tree) == OPC_BLOCK) {
00092 for (WN* wn = WN_first(wn_tree); wn != NULL; wn = WN_next(wn))
00093 Whack_Do_Loops_Traverse(wn);
00094 } else {
00095 for (INT i = 0; i < WN_kid_count(wn_tree); i++)
00096 Whack_Do_Loops_Traverse(WN_kid(wn_tree, i));
00097 }
00098
00099
00100
00101
00102 if (WN_opcode(wn_tree) == OPC_DO_LOOP) {
00103 DO_LOOP_INFO* dli = Get_Do_Loop_Info(wn_tree);
00104 if (dli->Mp_Info && dli->Mp_Info->Nest_Index() == 0) {
00105 INT lego_count = 0;
00106 for (INT i = 0; i < dli->Mp_Info->Nest_Total(); i++) {
00107 WN* wn_inner = SNL_Get_Inner_Snl_Loop(wn_tree, i + 1);
00108 DO_LOOP_INFO* dli_inner = Get_Do_Loop_Info(wn_inner);
00109 FmtAssert(dli_inner->Mp_Info != NULL, ("Could not find Mp_Info"));
00110 FmtAssert(dli_inner->Mp_Info->Nest_Index() == i,
00111 ("Did not find the right do loop in the nest"));
00112 if (dli_inner->Lego_Info != NULL)
00113 lego_count++;
00114 }
00115 if (lego_count != 0 && lego_count != dli->Mp_Info->Nest_Total()) {
00116 for (INT i = 0; i < dli->Mp_Info->Nest_Total(); i++) {
00117 WN* wn_inner = SNL_Get_Inner_Snl_Loop(wn_tree, i + 1);
00118 DO_LOOP_INFO* dli_inner = Get_Do_Loop_Info(wn_inner);
00119 if (dli_inner->Lego_Info != NULL) {
00120 CXX_DELETE(dli_inner->Lego_Info, LEGO_pool);
00121 dli_inner->Lego_Info = NULL;
00122 }
00123 }
00124 }
00125 }
00126 }
00127 }
00128
00129 extern void Whack_Do_Loops(WN* func_nd)
00130 {
00131 Whack_Do_Loops_Traverse(func_nd);
00132 }
00133
00134
00135
00136
00137
00138
00139
00140 static void Do_Loop_Explicit_Affinity (WN* loop)
00141 {
00142
00143 DO_LOOP_INFO* dli = Get_Do_Loop_Info(loop);
00144 Is_True(dli, ("Do_Loop_Explicit_Affinity: No DO_LOOP_INFO for this loop"));
00145
00146 LEGO_INFO* li = dli->Lego_Info;
00147 if (!li || !li->Array() || li->Dynamic_Affinity()) return;
00148
00149 SYMBOL* affinity_array = li->Array();
00150 ST* st = affinity_array->St();
00151 DISTR_ARRAY * dact = Lookup_DACT(st);
00152 Is_True(dact, ("Do_Loop_Explicit_Affinity: Array is not distributed"));
00153
00154 DISTRIBUTE_TYPE distr_type = dact->Get_Dim(li->Dim_Num())->Distr_Type();
00155 if (distr_type == DISTRIBUTE_STAR) {
00156 DevWarn("Affinity on not distributed dimension has no effect \n");
00157 return;
00158 }
00159
00160 INT loop_depth = dli->Depth;
00161 INT affinity_stride = li->Stride();
00162 INT affinity_offset = li->Offset();
00163 INT front_peel = 0;
00164 INT back_peel = 0;
00165
00166 LWN_ITER* wniter = LWN_WALK_TreeIter(loop);
00167 while (wniter) {
00168 WN* wn = wniter->wn;
00169 wniter = LWN_WALK_TreeNext(wniter);
00170 OPERATOR opr = WN_operator(wn);
00171
00172 if (((opr == OPR_ILOAD) &&
00173 (WN_operator(WN_kid0(wn)) == OPR_ARRAY)) ||
00174 ((opr == OPR_PARM) &&
00175 (WN_operator(WN_kid0(wn)) == OPR_ARRAY)) ||
00176 ((opr == OPR_ISTORE) &&
00177 (WN_operator(WN_kid1(wn)) == OPR_ARRAY))) {
00178
00179 wn = (opr==OPR_ILOAD || opr==OPR_PARM) ? WN_kid0(wn) : WN_kid1(wn);
00180
00181
00182
00183
00184 ST* cur_st = (WN_has_sym(WN_array_base(wn)) ?
00185 WN_st(WN_array_base(wn)) :
00186 NULL);
00187 DISTR_ARRAY * cur_dact = Lookup_DACT(st);
00188 if ((dact == NULL) || (!dact->Dinfo()->IsReshaped())) continue;
00189
00190 ACCESS_ARRAY* aa = (ACCESS_ARRAY *) WN_MAP_Get(LNO_Info_Map, wn);
00191 if (aa == NULL || aa->Too_Messy) continue;
00192
00193
00194 for (UINT i = 0; i< aa->Num_Vec(); ++i) {
00195
00196 DISTRIBUTE_TYPE distr_type = cur_dact->Get_Dim(i)->Distr_Type();
00197 if (distr_type == DISTRIBUTE_STAR) continue;
00198
00199
00200 if (!dact->DACT_Equiv(cur_dact, li->Dim_Num(), i)) continue;
00201
00202
00203 ACCESS_VECTOR* av = aa->Dim(i);
00204 if (av->Too_Messy ||
00205 av->Contains_Lin_Symb() ||
00206 av->Contains_Non_Lin_Symb() ||
00207 !av->Has_Loop_Coeff() ||
00208 av->Loop_Coeff(loop_depth) != affinity_stride) {
00209 continue;
00210 }
00211
00212
00213
00214
00215 BOOL is_good = TRUE;
00216 for (INT j = 0; j<av->Nest_Depth(); ++j) {
00217 if (j!=loop_depth && av->Loop_Coeff(j)!=0) {
00218 is_good = FALSE;
00219 break;
00220 }
00221 }
00222
00223 if (!is_good) continue;
00224
00225
00226 INT new_offset = av->Const_Offset - affinity_offset;
00227 if (new_offset < front_peel) front_peel = new_offset;
00228 if (new_offset > back_peel) back_peel = new_offset;
00229
00230 }
00231 }
00232 }
00233
00234 if (distr_type == DISTRIBUTE_BLOCK) {
00235 if (li->Stride() >= 0) {
00236 li->Set_Front_Peel(-front_peel);
00237 li->Set_Back_Peel(back_peel);
00238 }
00239 else {
00240
00241 li->Set_Front_Peel(back_peel);
00242 li->Set_Back_Peel(-front_peel);
00243 }
00244 } else {
00245 li->Set_Min_Offset(front_peel);
00246 li->Set_Max_Offset(back_peel);
00247 }
00248
00249 return;
00250
00251 }
00252
00253
00254
00255
00256
00257
00258 static void Do_Loop_Implicit_Affinity (WN* loop)
00259 {
00260
00261
00262
00263 if (!Loop_Bounds_Simple(loop)) {
00264 return;
00265 }
00266
00267 DO_LOOP_INFO* dli = Get_Do_Loop_Info(loop);
00268 Is_True(dli, ("Do_Loop_Implicit_Affinity: No DO_LOOP_INFO for this loop"));
00269
00270 Is_True(dli->Lego_Info==NULL, ("Do_Loop_Implicit_Affinity: DO_LOOP_INFO already has Lego_Info"));
00271 LEGO_INFO* li = CXX_NEW(LEGO_INFO(NULL),LEGO_pool);
00272
00273 LEGO_AFFINITY affinity;
00274 INT loop_depth = dli->Depth;
00275 LWN_ITER* wniter = LWN_WALK_TreeIter(loop);
00276 while (wniter) {
00277 WN* wn = wniter->wn;
00278 wniter = LWN_WALK_TreeNext(wniter);
00279 OPERATOR opr = WN_operator(wn);
00280
00281 if (((opr == OPR_ILOAD) &&
00282 (WN_operator(WN_kid0(wn)) == OPR_ARRAY)) ||
00283 ((opr == OPR_PARM) &&
00284 (WN_operator(WN_kid0(wn)) == OPR_ARRAY)) ||
00285 ((opr == OPR_ISTORE) &&
00286 (WN_operator(WN_kid1(wn)) == OPR_ARRAY))) {
00287
00288 wn = (opr==OPR_ILOAD || opr==OPR_PARM) ? WN_kid0(wn) : WN_kid1(wn);
00289
00290 WN *array_base = WN_array_base(wn);
00291
00292 ST* st = (WN_has_sym(array_base) ? WN_st(array_base) : NULL);
00293 DISTR_ARRAY * dact = Lookup_DACT(st);
00294 if ((dact == NULL) || (!dact->Dinfo()->IsReshaped())) continue;
00295
00296 ACCESS_ARRAY *aa = (ACCESS_ARRAY *) WN_MAP_Get(LNO_Info_Map, wn);
00297 if (aa == NULL || aa->Too_Messy) continue;
00298
00299
00300 for (UINT i=0; i<aa->Num_Vec(); ++i) {
00301
00302 DISTRIBUTE_TYPE distr_type = dact->Get_Dim(i)->Distr_Type();
00303 if (distr_type == DISTRIBUTE_STAR) continue;
00304
00305 ACCESS_VECTOR* av = aa->Dim(i);
00306 if (av->Too_Messy ||
00307 !av->Has_Loop_Coeff() ||
00308 av->Loop_Coeff(loop_depth)==0 ||
00309 av->Contains_Lin_Symb() ||
00310 av->Contains_Non_Lin_Symb())
00311 continue;
00312
00313 BOOL is_good=TRUE;
00314 for (INT j = 0; j<av->Nest_Depth(); ++j) {
00315 if ((j!=loop_depth && av->Loop_Coeff(j)!=0)) {
00316 is_good = FALSE;
00317 break;
00318 }
00319 }
00320
00321
00322 if (av->Loop_Coeff(loop_depth)<0 && distr_type != DISTRIBUTE_BLOCK)
00323 continue;
00324
00325
00326 if (is_good)
00327 affinity.Add_Ref(wn, distr_type, av, i, loop_depth);
00328
00329 }
00330
00331 }
00332 }
00333
00334 affinity.Pick_Affinity(li);
00335
00336 if (li->Array()==NULL) {
00337 CXX_DELETE(li,LEGO_pool);
00338 }
00339 else {
00340 if (li->Stride() < 0) {
00341
00342 INT32 tmp = li->Front_Peel();
00343 li->Set_Front_Peel (li->Back_Peel());
00344 li->Set_Back_Peel (tmp);
00345 }
00346 dli->Lego_Info = li;
00347 if (Debug_Lego) li->Print(stdout);
00348 }
00349 }
00350
00351
00352
00353
00354
00355
00356
00357 LEGO_UGS::LEGO_UGS(WN* wn_array, DISTRIBUTE_TYPE dtype, ACCESS_VECTOR *av, INT32 dim, INT32 loop_pos):_ref_dims(LEGO_pool),_array_refs(LEGO_pool)
00358 {
00359
00360 #ifdef Is_True_On
00361
00362 {
00363 FmtAssert(av, ("LEGO_UGS: Empty ACCESS_VECTOR"));
00364 FmtAssert(wn_array, ("LEGO_UGS: Empty array reference"));
00365
00366 ACCESS_ARRAY * aa = (ACCESS_ARRAY *) WN_MAP_Get(LNO_Info_Map, wn_array);
00367 FmtAssert(aa, ("LEGO_UGS: Array ref has no access array"));
00368 ACCESS_VECTOR *av_x = aa->Dim(dim);
00369 FmtAssert(av_x==av, ("LEGO_UGS: Array ref dim access vector mismatch"));
00370
00371 if (av->Too_Messy ||
00372 av->Contains_Lin_Symb() ||
00373 av->Contains_Non_Lin_Symb() ||
00374 !av->Has_Loop_Coeff() || av->Loop_Coeff(loop_pos)==0)
00375 FmtAssert(FALSE, ("LEGO_UGS: Array ref dim has bad access vector"));
00376
00377 DISTR_INFO * dinfo = da_hash->Find(WN_has_sym(WN_array_base(wn_array)) ?
00378 WN_st(WN_array_base(wn_array)) :
00379 NULL);
00380 DISTRIBUTE_TYPE t = dinfo->Get_Dact(0)->Get_Dim(dim)->Distr_Type();
00381 FmtAssert(t==dtype, ("LEGO_UGS: Array distribution type mismatch"));
00382 }
00383 #endif
00384
00385 _av = av;
00386 _dtype = dtype;
00387 _loop_pos = loop_pos;
00388 _min_offset = _max_offset = av->Const_Offset;
00389 _array_refs.Push(wn_array);
00390 _ref_dims.Push(dim);
00391
00392 }
00393
00394
00395
00396
00397
00398
00399 INT32 LEGO_UGS::Compute_Offset()
00400 {
00401 if (_min_offset==_max_offset) return _min_offset;
00402
00403
00404
00405 INT32 size = _max_offset-_min_offset+1;
00406 INT32 *bucket = CXX_NEW_ARRAY(INT32,size,&LNO_local_pool);
00407 INT32 i;
00408
00409 for (i=0; i<size; ++i) {
00410 bucket[i] = 0;
00411 }
00412
00413 for (i=0; i<_array_refs.Elements(); ++i) {
00414 WN* wn = _array_refs.Bottom_nth(i);
00415 INT32 dim = _ref_dims.Bottom_nth(i);
00416
00417 ACCESS_ARRAY* aa = (ACCESS_ARRAY *) WN_MAP_Get(LNO_Info_Map, wn);
00418 ACCESS_VECTOR* av = aa->Dim(dim);
00419 bucket[av->Const_Offset - _min_offset] += 1;
00420 }
00421
00422 INT32 pos = 0;
00423 INT32 count_max = bucket[pos];
00424 for (i=1; i<size; ++i) {
00425 if (bucket[i]>count_max) {
00426 count_max = bucket[i];
00427 pos=i;
00428 }
00429 else if (bucket[i]==count_max &&
00430 (abs(i+_min_offset) < abs(pos+_min_offset))) {
00431
00432
00433
00434 pos=i;
00435 }
00436 }
00437
00438 return pos+_min_offset;
00439 }
00440
00441
00442
00443
00444
00445
00446 BOOL LEGO_UGS::Add_Ref(WN* wn_array,
00447 DISTRIBUTE_TYPE dtype,
00448 ACCESS_VECTOR *av,
00449 INT32 dim,
00450 INT32 loop_pos)
00451 {
00452 Is_True(dtype==_dtype,("LEGO_UGS::Add_Ref: Different distr_type"));
00453 Is_True(loop_pos==_loop_pos,("LEGO_UGS::Add_Ref: Different loop_pos"));
00454 if (av->Loop_Coeff(loop_pos)!=_av->Loop_Coeff(loop_pos)) return FALSE;
00455
00456 DISTR_ARRAY *dact = Lookup_DACT(WN_has_sym(WN_array_base(wn_array)) ?
00457 WN_st(WN_array_base(wn_array)) :
00458 NULL);
00459 Is_True(dact,("LEGO_UGS::Add_Ref: array is not reshaped"));
00460
00461 WN* wn_orig = _array_refs.Bottom_nth(0);
00462 DISTR_ARRAY *dact_orig = Lookup_DACT(WN_has_sym(WN_array_base(wn_orig)) ?
00463 WN_st(WN_array_base(wn_orig)) :
00464 NULL);
00465 INT dim_orig = _ref_dims.Bottom_nth(0);
00466 if (!dact_orig->DACT_Equiv(dact, dim_orig, dim)) return FALSE;
00467
00468
00469
00470 for (INT i = 0; i<_array_refs.Elements(); ++i) {
00471 WN* wn_orig = _array_refs.Bottom_nth(i);
00472 if (WN_st(WN_array_base(wn_array))==WN_st(WN_array_base(wn_orig))) {
00473
00474
00475
00476
00477 INT dim_orig = _ref_dims.Bottom_nth(i);
00478 ACCESS_ARRAY *aa = (ACCESS_ARRAY *) WN_MAP_Get(LNO_Info_Map, wn_orig);
00479 ACCESS_VECTOR *av_orig = aa->Dim(dim_orig);
00480 if (av_orig->Const_Offset==av->Const_Offset) return TRUE;
00481 }
00482 }
00483
00484
00485 INT offset = av->Const_Offset;
00486 if (offset<_min_offset) _min_offset = offset;
00487 if (offset>_max_offset) _max_offset = offset;
00488 _array_refs.Push(wn_array);
00489 _ref_dims.Push(dim);
00490
00491 return TRUE;
00492
00493 }
00494
00495
00496
00497
00498
00499
00500 static void
00501 Add_To_Lego_UGS_Stack(LEGO_UGS_STACK & ugs_stack,
00502 WN* wn_array,
00503 DISTRIBUTE_TYPE dtype,
00504 ACCESS_VECTOR* av,
00505 INT32 dim,
00506 INT32 loop_pos)
00507 {
00508 for (INT i = 0; i < ugs_stack.Elements(); ++i)
00509 if (ugs_stack.Bottom_nth(i)->Add_Ref(wn_array, dtype, av, dim, loop_pos))
00510 return;
00511
00512
00513 ugs_stack.Push(CXX_NEW(LEGO_UGS(wn_array, dtype, av, dim, loop_pos),LEGO_pool));
00514
00515 return;
00516
00517 }
00518
00519 LEGO_AFFINITY::LEGO_AFFINITY():_block(LEGO_pool),_cyclic(LEGO_pool),_block_cyclic(LEGO_pool)
00520 {
00521
00522 }
00523
00524 LEGO_AFFINITY::~LEGO_AFFINITY()
00525 {
00526 while (_block.Elements()) CXX_DELETE(_block.Pop(), LEGO_pool);
00527 while (_cyclic.Elements()) CXX_DELETE(_cyclic.Pop(), LEGO_pool);
00528 while (_block_cyclic.Elements()) CXX_DELETE(_block_cyclic.Pop(), LEGO_pool);
00529 }
00530
00531
00532
00533
00534
00535
00536 void
00537 LEGO_AFFINITY::Add_Ref(WN* wn_array,
00538 DISTRIBUTE_TYPE dtype,
00539 ACCESS_VECTOR* av,
00540 INT32 dim,
00541 INT32 loop_pos)
00542 {
00543 switch (dtype) {
00544 case DISTRIBUTE_BLOCK:
00545 Add_To_Lego_UGS_Stack(_block, wn_array, dtype, av, dim, loop_pos);
00546 break;
00547 case DISTRIBUTE_CYCLIC_CONST:
00548 Add_To_Lego_UGS_Stack(_cyclic, wn_array, dtype, av, dim, loop_pos);
00549 break;
00550 case DISTRIBUTE_CYCLIC_EXPR:
00551 Add_To_Lego_UGS_Stack(_block_cyclic, wn_array, dtype, av, dim, loop_pos);
00552 break;
00553 default:
00554 FmtAssert(FALSE, ("LEGO_AFFINITY::Add_Ref: dimension is not reshaped"));
00555 }
00556
00557 return;
00558 }
00559
00560
00561
00562
00563
00564
00565
00566 static INT
00567 Vote_Affinity(LEGO_UGS_STACK & ugs_stack)
00568 {
00569 if (ugs_stack.Elements()<=0) return -1;
00570 INT pos = 0;
00571 INT count = ugs_stack.Bottom_nth(0)->Get_Array_Refs().Elements();
00572 INT spread = ugs_stack.Bottom_nth(0)->Get_Max_Offset()-
00573 ugs_stack.Bottom_nth(0)->Get_Min_Offset();
00574 for (INT i = 1; i < ugs_stack.Elements(); ++i) {
00575 LEGO_UGS * ugs_cur = ugs_stack.Bottom_nth(i);
00576 INT new_count = ugs_cur->Get_Array_Refs().Elements();
00577 INT new_spread = ugs_cur->Get_Max_Offset()-ugs_cur->Get_Min_Offset();
00578 if (new_count>count || (new_count==count && new_spread<spread)) {
00579 pos = i;
00580 count = new_count;
00581 spread = new_spread;
00582 }
00583 }
00584
00585 return pos;
00586 }
00587
00588
00589
00590
00591
00592
00593
00594 void
00595 LEGO_AFFINITY::Pick_Affinity(LEGO_INFO *dli)
00596 {
00597
00598
00599
00600
00601 INT block_leader = Vote_Affinity(_block);
00602 INT cyclic_leader = Vote_Affinity(_cyclic);
00603 INT block_c_leader = Vote_Affinity(_block_cyclic);
00604
00605 INT count = 0;
00606 INT spread = 0;
00607 LEGO_UGS * lego_ugs = NULL;
00608 if (block_leader>=0) {
00609 lego_ugs = _block.Bottom_nth(block_leader);
00610 count = lego_ugs->Get_Array_Refs().Elements();
00611 spread = lego_ugs->Get_Max_Offset()-lego_ugs->Get_Min_Offset();
00612 }
00613 if (cyclic_leader>=0) {
00614 LEGO_UGS * ugs_cur = _cyclic.Bottom_nth(cyclic_leader);
00615 INT new_count = ugs_cur->Get_Array_Refs().Elements();
00616 INT new_spread = ugs_cur->Get_Max_Offset()-ugs_cur->Get_Min_Offset();
00617 if (lego_ugs==NULL || new_count>count
00618 || (new_count==count && new_spread<spread)) {
00619 lego_ugs = ugs_cur;
00620 count = new_count;
00621 spread = new_spread;
00622 }
00623 }
00624 if (block_c_leader>=0) {
00625 LEGO_UGS * ugs_cur = _block_cyclic.Bottom_nth(block_c_leader);
00626 INT new_count = ugs_cur->Get_Array_Refs().Elements();
00627 INT new_spread = ugs_cur->Get_Max_Offset()-ugs_cur->Get_Min_Offset();
00628 if (lego_ugs==NULL || new_count>count
00629 || (new_count==count && new_spread<spread)) {
00630 lego_ugs = ugs_cur;
00631 count = new_count;
00632 spread = new_spread;
00633 }
00634 }
00635
00636
00637 if (lego_ugs) {
00638 WN * array_wn = lego_ugs->Get_Array_Refs().Bottom_nth(0);
00639 Is_True(array_wn,("Cannot find WN for LEGO_UGS"));
00640
00641 SYMBOL *symb = CXX_NEW(SYMBOL(WN_st(WN_array_base(array_wn)),
00642 (WN_OFFSET) 0,
00643 0),
00644 LEGO_pool);
00645 INT32 offset = lego_ugs->Compute_Offset();
00646 INT32 front_peel = lego_ugs->Get_Min_Offset()-offset;
00647 INT32 back_peel = lego_ugs->Get_Max_Offset()-offset;
00648 INT32 stride = lego_ugs->Stride();
00649 INT32 dim = lego_ugs->Get_Ref_Dims().Bottom_nth(0);
00650
00651 if (lego_ugs->Dis_Type()==DISTRIBUTE_BLOCK)
00652 dli->Init(symb, dim, stride, offset, -front_peel, back_peel);
00653 else {
00654 dli->Init(symb, dim, stride, offset, 0, 0);
00655 dli->Set_Min_Offset(front_peel);
00656 dli->Set_Max_Offset(back_peel);
00657 }
00658 }
00659
00660 }
00661