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
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219 #ifdef USE_PCH
00220 #include "lno_pch.h"
00221 #endif // USE_PCH
00222 #pragma hdrstop
00223
00224 #include "prefetch.h"
00225 #include "config_lno.h"
00226 #include "pf_loop.h"
00227 #include "lwn_util.h"
00228 #include "wn_map.h"
00229 #include "mat.h"
00230 #include "pf_cache.h"
00231 #include "lnoutils.h"
00232 #include "pf_manual.h"
00233 #include "whirl2src.h"
00234
00235 CACHE_PARAMETERS Cache;
00236
00237 extern void Dump_WN(WN*, FILE*, INT, INT = 2, INT = 2, WN** = NULL, WN* = NULL,
00238 ARRAY_DIRECTED_GRAPH16* =NULL);
00239
00240 extern WN_MAP Parent_Map;
00241 WN_MAP version_map = 0;
00242
00243 static BOOL pf_mempools_initialized = FALSE;
00244 MEM_POOL PF_memory_pool, *PF_mpool;
00245 MEM_POOL PF_CG_mpool;
00246
00247 WN* pf_func_nd;
00248
00249 UINT ls_num_indent = 0;
00250 UINT vb_num_indent = 0;
00251 BOOL vb_print_split = TRUE;
00252
00253 static WN* PF_Get_First_Do_Loop (WN* wn);
00254 static WN* PF_Get_Next_Do_Loop (WN* wn);
00255
00256 ARRAY_DIRECTED_GRAPH16 *pf_array_dep_graph;
00257
00258 BOOL Debug_Prefetch = FALSE;
00259 BOOL Verbose_Prefetch = FALSE;
00260 BOOL PU_has_manual_prefetch = FALSE;
00261
00262 #ifdef KEY
00263 #include "glob.h"
00264
00265 INT Num_Prefetches;
00266 #endif
00267
00268 static void Prefetch_Manual (WN* func_nd);
00269 static void Disable_Prefetch_Manual (WN* func_nd);
00270 static void Prefetch_Auto (WN* func_nd,
00271 ARRAY_DIRECTED_GRAPH16 *array_dep_graph);
00272 static void Process_PU_Pragmas (WN* func_nd);
00273
00274
00275
00276 static inline BOOL
00277 Target_ISA_Has_Prefetch()
00278 {
00279 return (Is_Target_ISA_M4Plus() || Is_Target_ISA_I1Plus()
00280 #ifdef TARG_X8664
00281 || Is_Target_x86_64()
00282 #endif
00283 );
00284 }
00285
00286
00287 static inline UINT32
00288 Target_Proc_Run_Prefetch()
00289 {
00290 if (Is_Target_R10K()) return 1;
00291 #ifdef TARG_MIPS
00292 if (Is_Target_Sb1()) return 1;
00293 #endif
00294 #ifdef TARG_IA64
00295 if (Is_Target_Itanium()) return 2;
00296 #endif
00297 #ifdef TARG_X8664
00298 if (Is_Target_x86_64()) return CONSERVATIVE_PREFETCH;
00299 #endif
00300 return 0;
00301 }
00302
00303
00304
00305
00306
00307
00308 extern void Init_Prefetch_Options (WN* func_nd)
00309 {
00310 INT i;
00311
00312 if (!Target_ISA_Has_Prefetch()) {
00313 static BOOL warned_isa_noprefetch = FALSE;
00314 if ((!warned_isa_noprefetch) &&
00315 (LNO_Run_Prefetch_Set && LNO_Run_Prefetch) ||
00316 (LNO_Run_Prefetch_Manual_Set && LNO_Run_Prefetch_Manual))
00317 {
00318
00319 fprintf ( stderr,
00320 "Warning: Prefetching disabled since ISA %s "
00321 "does not support prefetch.\n",
00322 Isa_Name(Target_ISA));
00323 warned_isa_noprefetch = TRUE;
00324 }
00325 #ifdef KEY
00326 LNO_Run_Prefetch = NO_PREFETCH;
00327 #else
00328 LNO_Run_Prefetch = 0;
00329 #endif
00330 LNO_Run_Prefetch_Manual = FALSE;
00331 return;
00332 }
00333
00334 if (!LNO_Run_Prefetch_Set) {
00335 LNO_Run_Prefetch = Target_Proc_Run_Prefetch();
00336 }
00337
00338 if (!LNO_Run_Prefetch_Manual_Set) {
00339 if (Target_Proc_Run_Prefetch() > 0)
00340 LNO_Run_Prefetch_Manual = TRUE;
00341 else LNO_Run_Prefetch_Manual = FALSE;
00342 }
00343
00344
00345
00346
00347 #ifndef KEY
00348 if (LNO_Run_Prefetch == 0)
00349 #else
00350 if (LNO_Run_Prefetch == NO_PREFETCH)
00351 #endif
00352 if (Get_Trace(TP_LNOPT,TT_LNO_PREFETCH))
00353 LNO_Run_Prefetch = Target_Proc_Run_Prefetch();
00354 Debug_Prefetch = Get_Trace(TP_LNOPT,TT_LNO_PREFETCH_DEBUG);
00355 Verbose_Prefetch = Get_Trace(TP_LNOPT,TT_LNO_PREFETCH_VERBOSE);
00356
00357 #ifdef KEY
00358
00359 if (!LNO_Prefetch_Stores_Set)
00360 LNO_Prefetch_Stores = LNO_Run_Prefetch > SOME_PREFETCH;
00361 #endif
00362
00363
00364
00365
00366 if (!LNO_Ignore_Pragmas) {
00367 Process_PU_Pragmas (WN_func_pragmas(func_nd));
00368 Process_PU_Pragmas (WN_func_body(func_nd));
00369 }
00370
00371 if (Verbose_Prefetch) {
00372 #ifdef KEY
00373 printf ("LNO:Run_Prefetch = %s\n",
00374 ((LNO_Run_Prefetch == NO_PREFETCH) ? "false" :
00375 ((LNO_Run_Prefetch == SOME_PREFETCH) ? "very conservative" : ((LNO_Run_Prefetch == CONSERVATIVE_PREFETCH) ?
00376 "conservative" : "aggressive"))));
00377 #else
00378 printf ("LNO:Run_Prefetch = %s\n",
00379 ((LNO_Run_Prefetch == 0) ? "false"
00380 : ((LNO_Run_Prefetch == 1) ?
00381 "conservative" : "aggressive")));
00382 #endif
00383 printf ("LNO:Run_Prefetch_Manual = %s\n", (LNO_Run_Prefetch_Manual
00384 ? "true" : "false"));
00385 printf ("Debug_Prefetch = %s\n", (Debug_Prefetch
00386 ? "true" : "false"));
00387 printf ("Verbose_Prefetch = %s\n", (Verbose_Prefetch
00388 ? "true" : "false"));
00389 printf ("LNO:Prefetch_Ahead = %d\n", LNO_Prefetch_Ahead);
00390 printf ("LNO:Prefetch_Cache_Factor = %d\n", LNO_Prefetch_Cache_Factor);
00391 for (i=0; i<4; i++)
00392 printf ("Cache level %d = %s\n", i+1,
00393 (LNO_FLAGS_mhd(Current_LNO)->L[i].Prefetch_Level
00394 ? "true" : "false"));
00395 }
00396 }
00397
00398
00399
00400
00401
00402
00403
00404 static void Process_PU_Pragmas (WN* func_nd) {
00405 WN* pwn = func_nd;
00406 if (WN_operator(pwn) == OPR_PRAGMA) {
00407 switch (WN_pragma(pwn)) {
00408 case WN_PRAGMA_PREFETCH:
00409 if (!WN_pragma_arg1(pwn) && !WN_pragma_arg2(pwn)) {
00410
00411 VB_PRINT (printf ("Disable automatic prefetching\n"));
00412 #ifdef KEY
00413 LNO_Run_Prefetch = NO_PREFETCH;
00414 #else
00415 LNO_Run_Prefetch = 0;
00416 #endif
00417 }
00418 else {
00419
00420 #ifdef KEY
00421 LNO_Run_Prefetch = CONSERVATIVE_PREFETCH;
00422 #else
00423 LNO_Run_Prefetch = 1;
00424 #endif
00425 if (WN_pragma_arg1(pwn)) {
00426 VB_PRINT (printf ("Enable auto-prefetch, level-1 cache\n"));
00427 LNO_FLAGS_mhd(Current_LNO)->L[0].Prefetch_Level = TRUE;
00428 if (WN_pragma_arg1(pwn) > LNO_Run_Prefetch)
00429 LNO_Run_Prefetch = WN_pragma_arg1(pwn);
00430 }
00431 else {
00432 VB_PRINT (printf ("Disable auto-prefetch, level-1 cache\n"));
00433 LNO_FLAGS_mhd(Current_LNO)->L[0].Prefetch_Level = FALSE;
00434 }
00435 if (WN_pragma_arg2(pwn)) {
00436 VB_PRINT (printf ("Enable auto-prefetch, level-2 cache\n"));
00437 LNO_FLAGS_mhd(Current_LNO)->L[1].Prefetch_Level = TRUE;
00438 if (WN_pragma_arg2(pwn) > LNO_Run_Prefetch)
00439 LNO_Run_Prefetch = WN_pragma_arg2(pwn);
00440 }
00441 else {
00442 VB_PRINT (printf ("Disable auto-prefetch, level-2 cache\n"));
00443 LNO_FLAGS_mhd(Current_LNO)->L[1].Prefetch_Level = FALSE;
00444 }
00445 }
00446 break;
00447 case WN_PRAGMA_PREFETCH_MANUAL:
00448 if (WN_pragma_arg1(pwn) == 0) {
00449
00450 VB_PRINT (printf ("Disable manual-prefetching\n"));
00451 LNO_Run_Prefetch_Manual = FALSE;
00452 }
00453 else {
00454 VB_PRINT (printf ("Enable manual-prefetching\n"));
00455 LNO_Run_Prefetch_Manual = TRUE;
00456 }
00457 break;
00458 default:
00459 break;
00460 }
00461 return;
00462 }
00463
00464 if (WN_operator(pwn) == OPR_BLOCK) {
00465 WN* wn = WN_first(pwn);
00466 while (wn) {
00467 Process_PU_Pragmas(wn);
00468 wn = WN_next(wn);
00469 }
00470 }
00471 else {
00472 for (INT i=0; i<WN_kid_count(pwn); i++) {
00473 Process_PU_Pragmas (WN_kid(pwn, i));
00474 }
00475 }
00476 }
00477
00478
00479
00480
00481
00482
00483 static void Process_PU_Disable_Pragmas (WN* func_nd) {
00484 WN* plist = WN_func_pragmas(func_nd);
00485 Is_True (WN_opcode(plist) == OPC_BLOCK,
00486 ("Pragma list is not a block"));
00487 WN* pwn = WN_first(plist);
00488
00489 while (pwn) {
00490 Is_True (WN_operator(pwn) == OPR_PRAGMA,
00491 ("Pragma list contains non-pragma node"));
00492 switch (WN_pragma(pwn)) {
00493 case WN_PRAGMA_PREFETCH_REF_DISABLE:
00494
00495 {
00496 SYMBOL sym (WN_st(pwn), 0, 0);
00497 mpf_syms->Enter (&sym, WN_pragma_arg2(pwn));
00498 VB_PRINT(printf ("Prefetch ref disable: ");
00499 sym.Print (stdout);
00500 printf ("\n"));
00501 }
00502 break;
00503 default:
00504 break;
00505 }
00506 pwn = WN_next(pwn);
00507 }
00508 }
00509
00510
00511
00512
00513
00514
00515
00516 static void Prefetch_Manual (WN* func_nd) {
00517 VB_PRINT (printf ("What about scalars?\n"));
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529 SINGLE_LOOP loop (PF_mpool);
00530 loop.Process_Loop_Manual (WN_func_body(func_nd));
00531 VB_PRINT (printf ("After manual prefetching ");
00532 mpf_syms->Print (stdout));
00533 return;
00534
00535
00536 #if 0
00537 WN* doloop_wn = PF_Get_First_Do_Loop (func_nd);
00538 while (doloop_wn) {
00539 SINGLE_LOOP loop(PF_mpool);
00540 loop.Process_Loop_Manual (WN_do_body(doloop_wn));
00541 doloop_wn = PF_Get_Next_Do_Loop (doloop_wn);
00542 }
00543 VB_PRINT (printf ("After manual prefetching ");
00544 mpf_syms->Print (stdout));
00545 return;
00546 #endif
00547 }
00548
00549
00550
00551
00552
00553
00554 static void Disable_Prefetch_Manual (WN* wn) {
00555 if (!wn) return;
00556
00557 OPERATOR opr = WN_operator(wn);
00558 if (opr == OPR_PREFETCH) {
00559
00560 WN_pf_set_confidence(wn, 0);
00561 return;
00562 }
00563
00564 if (opr == OPR_BLOCK) {
00565 WN* kid = WN_first(wn);
00566 while (kid) {
00567 Disable_Prefetch_Manual(kid);
00568 kid = WN_next(kid);
00569 }
00570 }
00571 else {
00572 for (INT i=0; i<WN_kid_count(wn); i++)
00573 Disable_Prefetch_Manual (WN_kid(wn, i));
00574 }
00575 }
00576
00577 static void Prefetch_Auto (WN* func_nd,
00578 ARRAY_DIRECTED_GRAPH16 *array_dep_graph) {
00579 WN* doloop;
00580 INT loopno = 0;
00581
00582
00583
00584
00585 Cache.Initialize ();
00586 if (Cache.Levels() == 0) return;
00587
00588
00589 pf_array_dep_graph = array_dep_graph;
00590 MAT<FRAC>::Set_Default_Pool(&PF_memory_pool);
00591 version_map = WN_MAP_Create (PF_mpool);
00592 Initialize_Lvs ();
00593
00594 PF_LOOPNODE *rootnode = CXX_NEW (PF_LOOPNODE(0, func_nd, -1), PF_mpool);
00595
00596
00597 doloop = PF_Get_First_Do_Loop (func_nd);
00598 while (doloop) {
00599 PF_LOOPNODE *childnode =
00600 CXX_NEW (PF_LOOPNODE(rootnode, doloop, 0), PF_mpool);
00601 rootnode->Add_Child (childnode);
00602 doloop = PF_Get_Next_Do_Loop (doloop);
00603 }
00604
00605
00606 for (loopno=0; loopno<rootnode->Num_Children(); loopno++) {
00607 PF_LOOPNODE *childnode = rootnode->Get_Child(loopno);
00608
00609 childnode->Process_Loop ();
00610
00611
00612
00613
00614
00615 PF_PRINT(fprintf (TFile, "------ Loop nest number: %d --------\n", loopno);
00616 childnode->Print (TFile);
00617 fprintf(TFile, "------------- Now build base LGs ----------\n"));
00618 VB_PRINT (printf ("\n================ Loop nest number: %d =========\n",
00619 loopno);
00620 printf ("---------------- structure ----------------\n");
00621 childnode->Print_Structure ());
00622
00623 childnode->Build_Base_LGs ();
00624
00625 PF_PRINT (childnode->Print (TFile);
00626 fprintf (TFile, "----------- Now do volume computation -----\n");
00627 fprintf (TFile, " --- cache parameters: %d (%d), %d (%d) \n",
00628 Cache.EffSize(1), Cache.LineSize(1),
00629 Cache.EffSize(2), Cache.LineSize(2)));
00630
00631 childnode->Volume ();
00632
00633 PF_PRINT (fprintf (TFile, "------- done with volume computation -----\n");
00634 childnode->Print (TFile);
00635 fprintf(TFile,"\n----- find loc loops+what to prefetch ---\n"));
00636 VB_PRINT (printf ("\n---------------- volume ----------------\n");
00637 childnode->Print_Volume ());
00638
00639 {
00640 PF_LOCLOOP tmp;
00641 childnode->Find_Loc_Loops (tmp);
00642 }
00643
00644 PF_PRINT (fprintf (TFile, "\n----- now split and gen prefetch -----\n"));
00645 VB_PRINT (printf ("\n---------------- splits ----------------\n");
00646 childnode->Print_Splits ();
00647 printf ("\n---------------- prefetches ----------------\n");
00648 printf (" (cannot coordinate with splits) \n"));
00649
00650 #ifdef KEY
00651 Num_Prefetches = 0;
00652 #endif
00653 childnode->Gen_Prefetch (NULL);
00654 #ifdef KEY
00655 if (Num_Prefetches > 0 && LNO_Prefetch_Verbose) {
00656 printf("(%s:%d) ",
00657 Src_File_Name,
00658 Srcpos_To_Line(WN_Get_Linenum(childnode->Get_Code())));
00659 printf ("Generated %d prefetch instructions for this loop\n",
00660 Num_Prefetches);
00661 }
00662 #endif
00663
00664 PF_PRINT (fprintf (TFile, "---- Done with Loop nest number: %d ----\n",
00665 loopno));
00666
00667
00668 Is_True (LWN_Check_Parentize (childnode->Get_Code()),
00669 ("Check_Parentize failed\n"));
00670 }
00671
00672 #if 0
00673
00674 doloop = PF_Get_First_Do_Loop (func_nd);
00675 while (doloop) {
00676 PF_LOOPNODE *childnode =
00677 CXX_NEW (PF_LOOPNODE(rootnode, doloop, 0), PF_mpool);
00678 rootnode->Add_Child (childnode);
00679 loopno++;
00680 childnode->Process_Loop ();
00681
00682
00683
00684
00685
00686 PF_PRINT(fprintf (TFile, "------ Loop nest number: %d --------\n", loopno);
00687 childnode->Print (TFile);
00688 fprintf(TFile, "------------- Now build base LGs ----------\n"));
00689 VB_PRINT (printf ("\n================ Loop nest number: %d =========\n",
00690 loopno);
00691 printf ("---------------- structure ----------------\n");
00692 childnode->Print_Structure ());
00693
00694 childnode->Build_Base_LGs ();
00695
00696 PF_PRINT (childnode->Print (TFile);
00697 fprintf (TFile, "----------- Now do volume computation -----\n");
00698 fprintf (TFile, " --- cache parameters: %d (%d), %d (%d) \n",
00699 Cache.EffSize(1), Cache.LineSize(1),
00700 Cache.EffSize(2), Cache.LineSize(2)));
00701
00702 childnode->Volume ();
00703
00704 PF_PRINT (fprintf (TFile, "------- done with volume computation -----\n");
00705 childnode->Print (TFile);
00706 fprintf(TFile,"\n----- find loc loops+what to prefetch ---\n"));
00707 VB_PRINT (printf ("\n---------------- volume ----------------\n");
00708 childnode->Print_Volume ());
00709
00710 {
00711 PF_LOCLOOP tmp;
00712 childnode->Find_Loc_Loops (tmp);
00713 }
00714
00715 PF_PRINT (fprintf (TFile, "\n----- now split and gen prefetch -----\n"));
00716 VB_PRINT (printf ("\n---------------- splits ----------------\n");
00717 childnode->Print_Splits ();
00718 printf ("\n---------------- prefetches ----------------\n");
00719 printf (" (cannot coordinate with splits) \n"));
00720
00721 childnode->Gen_Prefetch (NULL);
00722
00723 PF_PRINT (fprintf (TFile, "---- Done with Loop nest number: %d ----\n",
00724 loopno));
00725
00726
00727 Is_True (LWN_Check_Parentize (doloop), ("Check_Parentize failed\n"));
00728
00729 doloop = PF_Get_Next_Do_Loop (doloop);
00730 }
00731 #endif // 0
00732
00733 Is_True (LWN_Check_Parentize (func_nd), ("Check_Parentize failed\n"));
00734 Cleanup_Lvs ();
00735 CXX_DELETE (rootnode, PF_mpool);
00736 WN_MAP_Delete (version_map);
00737 return;
00738 }
00739
00740
00741
00742
00743
00744
00745 void Prefetch_Driver ( WN* func_nd, ARRAY_DIRECTED_GRAPH16 * ) {
00746
00747 pf_func_nd = func_nd;
00748 if (LNO_Analysis || Verbose_Prefetch) Whirl2Src_Init (func_nd);
00749
00750
00751 INT Run_Prefetch_save = LNO_Run_Prefetch;
00752 BOOL Run_Prefetch_Manual_save = LNO_Run_Prefetch_Manual;
00753 BOOL pf_level_save[4];
00754 INT i;
00755 for (i=0; i<4; i++ ) {
00756 pf_level_save[i] = LNO_FLAGS_mhd(Current_LNO)->L[i].Prefetch_Level;
00757 }
00758
00759
00760
00761
00762 if (LNO_Run_Prefetch || LNO_Run_Prefetch_Manual) {
00763 PF_PRINT (fprintf (TFile, "Process PU %s\n", Cur_PU_Name));
00764 VB_PRINT (printf ("Process PU %s\n", Cur_PU_Name));
00765 if (!pf_mempools_initialized) {
00766 MEM_POOL_Initialize (&PF_memory_pool, "Prefetch_pool", FALSE);
00767 MEM_POOL_Initialize (&PF_CG_mpool, "Prefetch_to_cg_mpool", FALSE);
00768 MEM_POOL_Push_Freeze (&PF_CG_mpool);
00769 PF_mpool = &(PF_memory_pool);
00770 pf_mempools_initialized = TRUE;
00771 }
00772 else {
00773
00774
00775 MEM_POOL_Pop_Unfreeze (&PF_CG_mpool);
00776 MEM_POOL_Push_Freeze (&PF_CG_mpool);
00777 }
00778
00779 MEM_POOL_Push_Freeze (PF_mpool);
00780 mpf_syms = CXX_NEW(MANUAL_PREFETCH_SYMBOLS(PF_mpool), PF_mpool);
00781
00782
00783 if (!LNO_Ignore_Pragmas) {
00784 Process_PU_Disable_Pragmas (func_nd);
00785 }
00786
00787 if (LNO_Run_Prefetch_Manual && PU_has_manual_prefetch) {
00788 Prefetch_Manual (func_nd);
00789 }
00790 else if (!LNO_Run_Prefetch_Manual && PU_has_manual_prefetch) {
00791 Disable_Prefetch_Manual (func_nd);
00792 }
00793 VB_PRINT (printf ("No manual prefetches\n"));
00794 if (LNO_Run_Prefetch) {
00795 Prefetch_Auto (func_nd, Array_Dependence_Graph);
00796 }
00797
00798 Is_True (mpf_syms || !LNO_Run_Prefetch_Manual,
00799 ("mpf_syms incorrect relative to manual_prefetch flag"));
00800 CXX_DELETE (mpf_syms, PF_mpool);
00801 mpf_syms = NULL;
00802 MEM_POOL_Pop_Unfreeze (PF_mpool);
00803 }
00804
00805
00806 LNO_Run_Prefetch = Run_Prefetch_save;
00807 LNO_Run_Prefetch_Manual = Run_Prefetch_Manual_save;
00808 for ( i=0; i<4; i++ ) {
00809 LNO_FLAGS_mhd(Current_LNO)->L[i].Prefetch_Level = pf_level_save[i];
00810 }
00811 }
00812
00813
00814
00815
00816
00817
00818
00819
00820 static WN* PF_Get_First_Do_Loop (WN* wn) {
00821 WN* tmp;
00822 if (OPCODE_is_leaf(WN_opcode(wn))) return NULL;
00823 if (WN_opcode(wn) == OPC_DO_LOOP) return wn;
00824 if (WN_opcode(wn) == OPC_BLOCK) {
00825 WN *kid = WN_first (wn);
00826 while (kid) {
00827 if (WN_opcode(kid) == OPC_DO_LOOP) return kid;
00828 if ((OPCODE_is_scf(WN_opcode(kid))) &&
00829 (tmp = PF_Get_First_Do_Loop (kid))) return tmp;
00830 kid = WN_next (kid);
00831 }
00832 return NULL;
00833 }
00834
00835 for (INT kidno=0; kidno<WN_kid_count(wn); kidno++) {
00836 WN *kid = WN_kid(wn,kidno);
00837 if (WN_opcode(kid) == OPC_DO_LOOP) return kid;
00838 if ((OPCODE_is_scf(WN_opcode(kid))) &&
00839 (tmp = PF_Get_First_Do_Loop (kid))) return tmp;
00840 }
00841
00842 return NULL;
00843 }
00844
00845
00846
00847
00848
00849
00850
00851 static WN* PF_Get_Next_Do_Loop (WN* wn) {
00852 WN *pwn, *tmp;
00853 Is_True ((WN_opcode(wn) == OPC_DO_LOOP),
00854 ("PF_Get_Next_Do_Loop called on a non-DO loop\n"));
00855 pwn = LWN_Get_Parent (wn);
00856
00857 while (1) {
00858 if (pwn == NULL) {
00859
00860 return NULL;
00861 }
00862 if (WN_opcode(pwn) == OPC_BLOCK) {
00863 WN* kid = WN_next (wn);
00864 while (kid) {
00865 if (WN_opcode(kid) == OPC_DO_LOOP) return kid;
00866 if ((OPCODE_is_scf(WN_opcode(kid))) &&
00867 (tmp = PF_Get_First_Do_Loop (kid))) return tmp;
00868 kid = WN_next (kid);
00869 }
00870 }
00871 else {
00872
00873 INT kidno;
00874 WN* kid;
00875 for (kidno=0; kidno<WN_kid_count(pwn); kidno++)
00876 if (wn == WN_kid (pwn, kidno)) break;
00877 Is_True ((kidno < WN_kid_count (pwn)),
00878 ("kid 0x%lx not a child of its parent 0x%lx\n", wn, pwn));
00879
00880
00881 kidno++;
00882 for (; kidno<WN_kid_count (pwn); kidno++) {
00883 kid = WN_kid (pwn, kidno);
00884 if (WN_opcode(kid) == OPC_DO_LOOP) return kid;
00885 if ((OPCODE_is_scf(WN_opcode(kid))) &&
00886 (tmp = PF_Get_First_Do_Loop (kid))) return tmp;
00887 }
00888 }
00889
00890 wn = pwn;
00891 pwn = LWN_Get_Parent (wn);
00892 }
00893
00894 }