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 #define __STDC_LIMIT_MACROS
00045 #include <stdint.h>
00046 #ifdef USE_PCH
00047 #include "lno_pch.h"
00048 #endif // USE_PCH
00049 #pragma hdrstop
00050
00051 #include <sys/types.h>
00052 #include <ctype.h>
00053 #include <limits.h>
00054 #include "pu_info.h"
00055 #include "ara.h"
00056 #include "fiz_fuse.h"
00057 #include "lwn_util.h"
00058 #include "dep_graph.h"
00059 #include "snl.h"
00060 #include "snl_nest.h"
00061 #include "snl_xbounds.h"
00062 #include "scalar_expand.h"
00063 #include "wn_simp.h"
00064 #include "parmodel.h"
00065
00066 #include "targ_sim.h"
00067 #include "strtab.h"
00068 #include "dvector.h"
00069 #include "opt_wn.h"
00070 #include "access_vector.h"
00071 #include "dep_graph.h"
00072 #include "lego_opts.h"
00073
00074 #include "lnoutils.h"
00075 #include "lnopt_main.h"
00076 #include "stab.h"
00077 #include "targ_const.h"
00078 #include "reduc.h"
00079 #include "opt_alias_mgr.h"
00080 #include "snl_trans.h"
00081 #include "permute.h"
00082 #include "fusion.h"
00083 #include "reverse.h"
00084 #include "model.h"
00085 #include "cache_model.h"
00086 #include "debug.h"
00087 #include "whirl2src.h"
00088 #include "sxlist.h"
00089 #include "sxlimit.h"
00090 #include "parallel.h"
00091 #include "snl_dist.h"
00092 #include "mat.h"
00093 #include "lu_mat.h"
00094 #include "prompf.h"
00095 #include "wb_util.h"
00096 #include "wb_carray.h"
00097 #include "wb_buffer.h"
00098 #include "wb_browser.h"
00099 #include "wb.h"
00100 #include "DaVinci.h"
00101 #include "wutil.h"
00102 #include "intrn_info.h"
00103
00104 #define BUFFER_MAX 132
00105 #define MAX_FORMULA_VARS 100
00106 #define ASCII_CHAR_COUNT 256
00107
00108 enum SOURCE_LANGUAGE {SRC_NONE, SRC_FORTRAN, SRC_C};
00109 enum SKIP_CLASS {SKIP_NONE, SKIP_ALPHANUMERIC, SKIP_NUMERIC, SKIP_HEX};
00110
00111 WN* WB_global_fd = NULL;
00112 DU_MANAGER* WB_du_mgr;
00113 ALIAS_MANAGER* WB_alias_mgr;
00114 INT WB_sanity_check_level = 0;
00115 SOURCE_LANGUAGE WB_language = SRC_NONE;
00116 char WB_keymap[ASCII_CHAR_COUNT];
00117 char last_ch = '\0';
00118 BOOL init_mode = FALSE;
00119 BOOL WB_davinci_mode = FALSE;
00120
00121 extern ARRAY_DIRECTED_GRAPH16* Array_Dependence_Graph;
00122 extern REDUCTION_MANAGER* red_manager;
00123
00124 typedef void (*VOID_FUNC_PTR)();
00125 typedef BOOL (*BOOL_FUNC_PTR)();
00126 const INT MAX_STRING_LENGTH = 1000;
00127
00128 static WN* cnode = NULL;
00129 static INT fancy = 2;
00130 const INT fancy_min = 2;
00131 const INT fancy_max = 3;
00132 static VOID_FUNC_PTR last_fp;
00133
00134 static const char *operator_table[OPERATOR_LAST + 1] =
00135 {
00136 "UNKNOWN",
00137 "ABS",
00138 "ADD",
00139 "AGOTO",
00140 "ALTENTRY",
00141 "ARRAY",
00142 "ARRAYEXP",
00143 "ARRSECTION",
00144 "ASHR",
00145 "ASSERT",
00146 "BACKWARD_BARRIER",
00147 "BAND",
00148 "BIOR",
00149 "BLOCK",
00150 "BNOR",
00151 "BNOT",
00152 "BXOR",
00153 "CALL",
00154 "CAND",
00155 "CASEGOTO",
00156 "CEIL",
00157 "CIOR",
00158 "COMMA",
00159 "COMMENT",
00160 "COMPGOTO",
00161 "COMPLEX",
00162 "CONST",
00163 "CSELECT",
00164 "CVT",
00165 "CVTL",
00166 "DIV",
00167 "DIVREM",
00168 "DO_LOOP",
00169 "DO_WHILE",
00170 "EQ",
00171 "EVAL",
00172 "EXC_SCOPE_BEGIN",
00173 "EXC_SCOPE_END",
00174 "FALSEBR",
00175 "FLOOR",
00176 "FORWARD_BARRIER",
00177 "FUNC_ENTRY",
00178 "GE",
00179 "GOTO",
00180 "GT",
00181 "HIGHMPY",
00182 "HIGHPART",
00183 "ICALL",
00184 "IDNAME",
00185 "IF",
00186 "ILDA",
00187 "ILDBITS",
00188 "ILOAD",
00189 "ILOADX",
00190 "IMAGPART",
00191 "INTCONST",
00192 "INTRINSIC_CALL",
00193 "INTRINSIC_OP",
00194 "IO",
00195 "IO_ITEM",
00196 "ISTBITS",
00197 "ISTORE",
00198 "ISTOREX",
00199 "LABEL",
00200 "LAND",
00201 "LDA",
00202 "LDBITS",
00203 "LDID",
00204 "LE",
00205 "LIOR",
00206 "LNOT",
00207 "LOOP_INFO",
00208 "LOWPART",
00209 "LSHR",
00210 "LT",
00211 "MADD",
00212 "MAX",
00213 "MAXPART",
00214 "MIN",
00215 "MINMAX",
00216 "MINPART",
00217 "MLOAD",
00218 "MOD",
00219 "MPY",
00220 "MSTORE",
00221 "MSUB",
00222 "NE",
00223 "NEG",
00224 "NMADD",
00225 "NMSUB",
00226 "OPTPARM",
00227 "OPT_CHI",
00228 "OPT_RESERVE2",
00229 "PAREN",
00230 "PARM",
00231 "PICCALL",
00232 "PRAGMA",
00233 "PREFETCH",
00234 "PREFETCHX",
00235 "RCOMMA",
00236 "REALPART",
00237 "RECIP",
00238 "REGION",
00239 "REGION_EXIT",
00240 "REM",
00241 "RETURN",
00242 "RETURN_VAL",
00243 "RND",
00244 "RSQRT",
00245 "SELECT",
00246 "SHL",
00247 "SQRT",
00248 "STBITS",
00249 "STID",
00250 "SUB",
00251 "SWITCH",
00252 "TAS",
00253 "TRAP",
00254 "TRIPLET",
00255 "TRUEBR",
00256 "TRUNC",
00257 "VFCALL",
00258 "WHERE",
00259 "WHILE_DO",
00260 "XGOTO",
00261 "XMPY",
00262 "XPRAGMA",
00263 "AFFIRM",
00264 "ALLOCA",
00265 "DEALLOCA",
00266 "LDMA",
00267 #ifdef KEY
00268 "ASM_STMT",
00269 "ASM_EXPR",
00270 "ASM_INPUT",
00271 "RROTATE",
00272 "LDA_LABEL",
00273 "GOTO_OUTER_BLOCK",
00274 "EXTRACT_BITS",
00275 "COMPOSE_BITS",
00276 #endif
00277 #ifdef TARG_X8664
00278 "REPLICATE",
00279 "REDUCE_ADD",
00280 "REDUCE_MPY",
00281 "REDUCE_MAX",
00282 "REDUCE_MIN",
00283 "PURE_CALL_OP",
00284 "SHUFFLE",
00285 "ATOMIC_RSQRT",
00286 #elif defined(TARG_MIPS)
00287 "PURE_CALL_OP",
00288 #endif
00289 };
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305 extern void WB_LNO_Initialize(WN* global_fd,
00306 DU_MANAGER* du_mgr,
00307 ALIAS_MANAGER* alias_mgr,
00308 INT sanity_check_level)
00309 {
00310 WB_Set_Phase(WBP_LNO);
00311 WB_global_fd = global_fd;
00312 WB_du_mgr = du_mgr;
00313 WB_alias_mgr = alias_mgr;
00314 WB_sanity_check_level = sanity_check_level;
00315 for (INT i = 0; i < ASCII_CHAR_COUNT; i++)
00316 WB_keymap[i] = i;
00317 }
00318
00319
00320
00321
00322
00323
00324
00325 extern void WB_LNO_Terminate(void)
00326 {
00327 WB_Set_Phase(WBP_NONE);
00328 WB_global_fd = NULL;
00329 WB_sanity_check_level = 0;
00330 }
00331
00332
00333
00334
00335
00336
00337
00338 extern void WB_Set_Sanity_Check_Level(INT sanity_check_level)
00339 {
00340 FmtAssert(sanity_check_level >= WBC_MIN && sanity_check_level <= WBC_MAX,
00341 ("Set sanity check level to invalid value."));
00342 WB_sanity_check_level = sanity_check_level;
00343 }
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353 extern const char* WB_Whirl_Symbol(WN* wn)
00354 {
00355 if (wn == NULL)
00356 return NULL;
00357 WN* wn_symbol = NULL;
00358 const char* name = NULL;
00359 OPCODE opc = WN_opcode(wn);
00360 OPERATOR opr = OPCODE_operator(opc);
00361 if (opc == OPC_PRAGMA || opc == OPC_XPRAGMA)
00362 return WN_pragmas[WN_pragma(wn)].name;
00363 if (opr == OPR_INTRINSIC_CALL)
00364 return INTRINSIC_name((INTRINSIC) WN_intrinsic(wn));
00365 wn_symbol = (opc == OPC_DO_LOOP) ? WN_index(wn) : (OPCODE_has_sym(opc))
00366 ? wn : NULL;
00367 if (wn_symbol == NULL)
00368 return NULL;
00369 if (WN_st(wn_symbol) == NULL)
00370 return NULL;
00371 name = ST_class(WN_st(wn_symbol)) != CLASS_PREG
00372 ? ST_name(WN_st(wn_symbol)) :
00373 WN_offset(wn_symbol) > Last_Dedicated_Preg_Offset
00374 ? Preg_Name(WN_offset(wn_symbol)) : "DEDICATED PREG";
00375 return name;
00376 }
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387 extern const char* WB_Whirl_Symbol_Type(WN* wn)
00388 {
00389 WN* wn_symbol = NULL;
00390 const char* name = NULL;
00391 OPCODE opc = WN_opcode(wn);
00392 OPERATOR opr = OPCODE_operator(opc);
00393 if (opc == OPC_PRAGMA || opc == OPC_XPRAGMA)
00394 return WN_pragmas[WN_pragma(wn)].name;
00395 wn_symbol = (opc == OPC_DO_LOOP) ? WN_index(wn) : (OPCODE_has_sym(opc))
00396 ? wn : NULL;
00397 if (wn_symbol == NULL)
00398 return (char *) (OPCODE_name(WN_opcode(wn)) + 4);
00399 if (WN_st(wn_symbol) == NULL)
00400 return NULL;
00401 name = ST_class(WN_st(wn_symbol)) != CLASS_PREG
00402 ? ST_name(WN_st(wn_symbol)) :
00403 WN_offset(wn_symbol) > Last_Dedicated_Preg_Offset
00404 ? Preg_Name(WN_offset(wn_symbol)) : "DEDICATED PREG";
00405
00406 return name;
00407 }
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429 struct WB_CHAR_FUNCPTR {
00430 char ch;
00431 BOOL context_independent;
00432 const char* message;
00433 VOID_FUNC_PTR fp;
00434 };
00435
00436 static void WB_root();
00437 static void WB_parent();
00438 static void WB_kids();
00439 static void WB_next();
00440 static void WB_previous();
00441 static void WB_statements();
00442 static void WB_set_node();
00443 static void WB_address();
00444 static void WB_this_tree();
00445 static void WB_addresses();
00446 static void WB_uses();
00447 static void WB_defs();
00448 static void WB_access();
00449 static void WB_RR_Map();
00450 static void WB_node_deps();
00451 static void WB_stmt_deps();
00452 static void WB_fancyup();
00453 static void WB_fancydown();
00454 static void WB_loops();
00455 static void WB_check();
00456 static void WB_find();
00457 static void WB_find_symbols();
00458 static void WB_findopr();
00459 static void WB_symbol();
00460 static void WB_type();
00461 static void WB_type_table();
00462 static void WB_vertices();
00463 static void WB_reduction();
00464 static void WB_alias();
00465 static void WB_ancestors();
00466 static void WB_lisp_loops();
00467 static void WB_transform();
00468 static void WB_whirl2fc();
00469 static void WB_whirl2fset();
00470 static void WB_whirl2cset();
00471 static void WB_scratch();
00472 static void WB_last_command();
00473 static void WB_Set_Map_Id();
00474 static void WB_Map_Id();
00475 static void WB_private();
00476 static void WB_vset_node();
00477 static void WB_Prompf_Map();
00478 static void WB_Prompf_Info();
00479 static void WB_davinci();
00480 static void WB_help();
00481
00482 static WB_CHAR_FUNCPTR Command_List[] =
00483 {
00484 'R', TRUE, "Go to the root of the program unit", WB_root,
00485 'E', TRUE, "Go to the parent of the current node", WB_parent,
00486 'N', TRUE, "Go to the next node in the subtree chain", WB_next,
00487 'P', TRUE, "Go to the previous node in the subtree chain", WB_previous,
00488 '=', FALSE, "Set the current node to the following address", WB_set_node,
00489 '@', FALSE, "Set the current node to this numbered node", WB_address,
00490 '>', TRUE, "Increase the fanciness level for printing", WB_fancyup,
00491 '<', TRUE, "Decrease the fanciness level for printing", WB_fancydown,
00492 'W', TRUE, "Print tree in whirl2[fc] format at current node",WB_whirl2fc,
00493 'K', TRUE, "Print the kids of this node", WB_kids,
00494 'S', TRUE, "Print the list of statements under this node", WB_statements,
00495 'T', TRUE, "Print the tree at the current node", WB_this_tree,
00496 '%', TRUE, "Print the addresses of nodes in this subtree", WB_addresses,
00497 'U', TRUE, "Print the uses at the current node", WB_uses,
00498 'D', TRUE, "Print the definitions at the current node", WB_defs,
00499 'A', TRUE, "Print the access info at the current node", WB_access,
00500 'G', TRUE, "Print the node dep graph info at current node", WB_node_deps,
00501 'g', TRUE, "Print the stmt dep graph info at current node", WB_stmt_deps,
00502 'V', TRUE, "Print the vertices of the dep graph", WB_vertices,
00503 'r', TRUE, "Print the reduction manager", WB_reduction,
00504 'a', TRUE, "Print the alias info for this node", WB_alias,
00505 'e', TRUE, "Print the ancestors of this node", WB_ancestors,
00506 's', TRUE, "Print the symbol table entry for this node", WB_symbol,
00507 't', TRUE, "Print the type table entry for this node", WB_type,
00508 '#', FALSE, "Print node of this type at this address", WB_type_table,
00509 'L', TRUE, "Sketch the loop nests in the program unit", WB_loops,
00510 'l', TRUE, "Sketch the loop nests in Suresh Tool format", WB_lisp_loops,
00511 'y', FALSE, "Perform a transformation", WB_transform,
00512 'C', TRUE, "Check the program unit for consistency", WB_check,
00513 'F', FALSE, "Find nodes with this symbol in the subtree", WB_find,
00514 '$', FALSE, "Find symbols with this name", WB_find_symbols,
00515 'o', FALSE, "Find nodes with this operator type", WB_findopr,
00516 'f', TRUE, "Change WHIRL-TO-SOURCE language to FORTRAN", WB_whirl2fset,
00517 'c', TRUE, "Change WHIRL-TO-SOURCE language to C", WB_whirl2cset,
00518 'B', FALSE, "Print the scratch register with this number", WB_scratch,
00519 '.', TRUE, "Execute the previous command", WB_last_command,
00520 'Y', TRUE, "Print the reshaped-ref map for array nodes", WB_RR_Map,
00521 'i', TRUE, "Print the PROMPF ids for tree at this node", WB_Prompf_Map,
00522 'I', TRUE, "Print the PROMPF_INFO", WB_Prompf_Info,
00523 'M', TRUE, "Set the current node to node with this map id", WB_Set_Map_Id,
00524 'm', TRUE, "Print the map-id at this node", WB_Map_Id,
00525 'p', TRUE, "Print the privatization info at this node", WB_private,
00526 'v', FALSE, "Go to the node with this vertex number", WB_vset_node,
00527 'd', TRUE, "Toggle Da Vinci mode", WB_davinci,
00528 'H', TRUE, "Print this information", WB_help,
00529 'h', TRUE, "Print this information", WB_help,
00530 '\0',FALSE, "", NULL
00531 };
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544 struct WB_STRING_VOIDFUNCPTR {
00545 const char* type;
00546 VOID_FUNC_PTR fp;
00547 };
00548
00549 static void WBT_SNL_DEP_INFO();
00550 static void WBT_SNL_DEP_MATRIX();
00551 static void WBT_SNL_NEST_INFO();
00552 static void WBT_DOLOOP_STACK();
00553 static void WBT_ARRAY_REF_STAR();
00554 static void WBT_ARRAY_REF_LIST();
00555 static void WBT_COMPUTE_FOOTPRINT_RVAL();
00556 static void WBT_MHD_LEVEL();
00557 static void WBT_MHD();
00558 static void WBT_FORMULA();
00559 static void WBT_FORMULA_EVALUATE();
00560 static void WBT_PAR_STAT();
00561 static void WBT_MAT_INT();
00562 static void WBT_MAT_FRAC();
00563 static void WBT_LU_MAT_INT();
00564 static void WBT_LU_MAT_FRAC();
00565
00566 static WB_STRING_VOIDFUNCPTR Type_List[] =
00567 {
00568 "SNL_DEP_INFO", WBT_SNL_DEP_INFO,
00569 "SNL_DEP_MATRIX", WBT_SNL_DEP_MATRIX,
00570 "SNL_NEST_INFO", WBT_SNL_NEST_INFO,
00571 "DOLOOP_STACK", WBT_DOLOOP_STACK,
00572 "ARRAY_REF*", WBT_ARRAY_REF_STAR,
00573 "ARRAY_REF_LIST", WBT_ARRAY_REF_LIST,
00574 "COMPUTE_FOOTPRINT_RVAL", WBT_COMPUTE_FOOTPRINT_RVAL,
00575 "MHD_LEVEL", WBT_MHD_LEVEL,
00576 "MHD", WBT_MHD,
00577 "FORMULA", WBT_FORMULA,
00578 "FORMULA EVALUATE", WBT_FORMULA_EVALUATE,
00579 "PAR_STAT", WBT_PAR_STAT,
00580 "MAT<INT>", WBT_MAT_INT,
00581 "MAT<FRAC>", WBT_MAT_FRAC,
00582 "LU_MAT<INT>", WBT_LU_MAT_INT,
00583 "LU_MAT<FRAC>", WBT_LU_MAT_FRAC,
00584 "", NULL
00585 };
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599 struct WB_STRING_BOOLFUNCPTR {
00600 const char* type;
00601 BOOL_FUNC_PTR fp;
00602 };
00603
00604 static BOOL WBTR_Pre_Loop_Peeling();
00605 static BOOL WBTR_Post_Loop_Peeling();
00606 static BOOL WBTR_Loop_Reversal();
00607 static BOOL WBTR_Loop_Permutation();
00608 static BOOL WBTR_Scalar_Expansion();
00609 static BOOL WBTR_Distribution();
00610 static BOOL WBTR_SNL_INV_Limited_SE_And_Dist();
00611 static BOOL WBTR_Loop_Tiling();
00612
00613 static WB_STRING_BOOLFUNCPTR Transform_List[] =
00614 {
00615 "Pre Loop Peeling", WBTR_Pre_Loop_Peeling,
00616 "Post Loop Peeling", WBTR_Post_Loop_Peeling,
00617 "Loop Reversal", WBTR_Loop_Reversal,
00618 "Loop Permutation", WBTR_Loop_Permutation,
00619 "Scalar Expansion", WBTR_Scalar_Expansion,
00620 "Distribution", WBTR_Distribution,
00621 "Limited SE and Dist", WBTR_SNL_INV_Limited_SE_And_Dist,
00622 "Loop Tiling", WBTR_Loop_Tiling,
00623 "", NULL
00624 };
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635 static void this_node(WN* wn,
00636 BOOL print_vertex = TRUE,
00637 BOOL print_brackets = FALSE)
00638 {
00639 ARRAY_DIRECTED_GRAPH16* dg = Array_Dependence_Graph;
00640 if (wn == NULL) {
00641 fprintf(stdout, "<NULL>");
00642 return;
00643 }
00644 const char* ch = OPCODE_name(WN_opcode(wn));
00645 if (print_brackets)
00646 fprintf(stdout, "[0x%p] ", wn);
00647 else
00648 fprintf(stdout, "0x%p ", wn);
00649 if (print_vertex && dg != NULL && dg->Get_Vertex(wn) != 0)
00650 fprintf(stdout, "V#%d ", dg->Get_Vertex(wn));
00651 fprintf(stdout, "%s ", ch);
00652 if (fancy >= 3)
00653 if (OPCODE_has_next_prev(WN_opcode(wn)))
00654 fprintf(stdout, "(%d) ", (INT) WN_linenum(wn));
00655 if (fancy >= 3 && Prompf_Info != NULL)
00656 fprintf(stdout, "<%d> ", WN_MAP32_Get(Prompf_Id_Map, wn));
00657 if (WN_operator(wn) == OPR_INTCONST) {
00658 fprintf(stdout, "%lld ", WN_const_val(wn));
00659 } else {
00660 const char* wn_symbol = WB_Whirl_Symbol(wn);
00661 if (wn_symbol != NULL)
00662 fprintf(stdout, "%s ", wn_symbol);
00663 }
00664 }
00665
00666
00667
00668
00669
00670
00671 static void print_this_node(WN* wn,
00672 BOOL print_vertex = TRUE,
00673 BOOL print_brackets = FALSE)
00674 {
00675 this_node(wn, print_vertex, print_brackets);
00676 fprintf(stdout, "\n");
00677 }
00678
00679
00680
00681
00682
00683
00684 static void print_this_node()
00685 {
00686 print_this_node(cnode);
00687 }
00688
00689
00690
00691
00692
00693
00694 static void bell()
00695 {
00696 fprintf(stdout, "%c", '\007');
00697 fflush(stdout);
00698 }
00699
00700
00701
00702
00703
00704
00705 static void dump_spaces(FILE* fp, INT spaces)
00706 {
00707 for (INT i = 0; i < spaces; i++)
00708 fprintf(fp, " ");
00709 }
00710
00711
00712
00713
00714
00715
00716 static void prompt()
00717 {
00718 fprintf(stdout, "WB> ");
00719 }
00720
00721
00722
00723
00724
00725
00726
00727
00728 static VOID_FUNC_PTR this_fp(char ch)
00729 {
00730 for (INT i = 0; Command_List[i].ch != '\0'; i++)
00731 if (Command_List[i].ch == ch)
00732 return Command_List[i].fp;
00733 return NULL;
00734 }
00735
00736
00737
00738
00739
00740 const INT MAX_SAVED_NODES = 500;
00741 static WN* carray[MAX_SAVED_NODES];
00742 static INT carray_max = 0;
00743
00744
00745
00746
00747
00748
00749
00750
00751
00752 static void enter_this_node(INT& index, WN* wn, BOOL print_vertex = TRUE)
00753 {
00754 fprintf(stdout, "[%d] ", index);
00755 this_node(wn, print_vertex);
00756 if (index < MAX_SAVED_NODES)
00757 carray[index] = wn;
00758 index++;
00759 }
00760
00761
00762
00763
00764
00765
00766
00767 static void enter_this_node_unique(INT& index,
00768 WN* wn,
00769 BOOL print_vertex = TRUE)
00770 {
00771 INT i;
00772 for (i = 0; i < index; i++)
00773 if (wn == carray[i])
00774 break;
00775 fprintf(stdout, "[%d] ", i);
00776 this_node(wn, print_vertex);
00777 if (i < index)
00778 return;
00779 if (index < MAX_SAVED_NODES)
00780 carray[index] = wn;
00781 index++;
00782 }
00783
00784
00785
00786
00787
00788 char buffer[BUFFER_MAX];
00789 INT buffer_start = 0;
00790
00791
00792
00793
00794
00795
00796
00797 static void load_buffer()
00798 {
00799 for (INT i = 0; ; i++) {
00800 buffer[i] = fgetc(stdin);
00801 if (buffer[i] == '\n')
00802 break;
00803 }
00804 buffer_start = 0;
00805 }
00806
00807
00808
00809
00810
00811
00812
00813 static void scan_blanks_and_tabs()
00814 {
00815 char ch;
00816 do {
00817 ch = buffer[buffer_start++];
00818 } while (ch == ' ' || ch == '\t');
00819 buffer_start--;
00820 }
00821
00822
00823
00824
00825
00826
00827
00828 static void scan_blanks_and_tabs(char buffer[],
00829 INT* buffer_start)
00830 {
00831 char ch;
00832 do {
00833 ch = buffer[(*buffer_start)++];
00834 } while (ch == ' ' || ch == '\t');
00835 (*buffer_start)--;
00836 }
00837
00838
00839
00840
00841
00842
00843
00844 static void skip_to_separator(SKIP_CLASS skip_type)
00845 {
00846 switch (skip_type) {
00847 case SKIP_ALPHANUMERIC:
00848 while (buffer[buffer_start] != ' ' && buffer[buffer_start] != '\t'
00849 && buffer[buffer_start] != ';' && buffer[buffer_start] != '\n')
00850 buffer_start++;
00851 break;
00852 case SKIP_NUMERIC:
00853 while (isdigit(buffer[buffer_start]))
00854 buffer_start++;
00855 break;
00856 case SKIP_HEX:
00857 while (isxdigit(buffer[buffer_start]))
00858 buffer_start++;
00859 break;
00860 default:
00861 while (buffer[buffer_start] != ' ' && buffer[buffer_start] != '\t'
00862 && buffer[buffer_start] != ';' && buffer[buffer_start] != '\n')
00863 buffer_start++;
00864 }
00865 if (buffer[buffer_start] == '\n')
00866 return;
00867 while (buffer[buffer_start] == ' ' || buffer[buffer_start] == '\t'
00868 || buffer[buffer_start] == ';')
00869 buffer_start++;
00870 }
00871
00872
00873
00874
00875
00876
00877
00878 static void Error_Cleanup()
00879 {
00880 bell();
00881 prompt();
00882 load_buffer();
00883 scan_blanks_and_tabs();
00884 }
00885
00886
00887
00888
00889
00890
00891 static BOOL Load_Loop(WN** wn_loop)
00892 {
00893 load_buffer();
00894 scan_blanks_and_tabs();
00895 sscanf(buffer + buffer_start, "0x%p", wn_loop);
00896 buffer_start += 2;
00897 skip_to_separator(SKIP_HEX);
00898 if (WN_opcode(*wn_loop) != OPC_DO_LOOP) {
00899 fprintf(stdout, "Address is not address of a do loop.\n");
00900 Error_Cleanup();
00901 return FALSE;
00902 }
00903 return TRUE;
00904 }
00905
00906
00907
00908
00909
00910
00911 static void Load_UINT32(UINT32* int_value)
00912 {
00913 load_buffer();
00914 scan_blanks_and_tabs();
00915 sscanf(buffer + buffer_start, "%d", int_value);
00916 skip_to_separator(SKIP_NUMERIC);
00917 }
00918
00919
00920
00921
00922
00923
00924 static void Load_Integer(INT* int_value)
00925 {
00926 load_buffer();
00927 scan_blanks_and_tabs();
00928 sscanf(buffer + buffer_start, "%d", int_value);
00929 skip_to_separator(SKIP_NUMERIC);
00930 }
00931
00932
00933
00934
00935
00936
00937 static void Load_mINT32(mINT32* value)
00938 {
00939 load_buffer();
00940 scan_blanks_and_tabs();
00941 sscanf(buffer + buffer_start, "%d", value);
00942 skip_to_separator(SKIP_NUMERIC);
00943 }
00944
00945
00946
00947
00948
00949
00950 static void Load_mINT64(mINT64* value)
00951 {
00952 load_buffer();
00953 scan_blanks_and_tabs();
00954 sscanf(buffer + buffer_start, "%lld", value);
00955 skip_to_separator(SKIP_NUMERIC);
00956 }
00957
00958
00959
00960
00961
00962
00963 static void Load_Double(double* value)
00964 {
00965 load_buffer();
00966 scan_blanks_and_tabs();
00967 sscanf(buffer + buffer_start, "%lg", value);
00968 skip_to_separator(SKIP_NUMERIC);
00969 }
00970
00971
00972
00973
00974
00975
00976
00977
00978
00979
00980
00981 static void Load_Boolean(BOOL* bool_value, BOOL default_present = FALSE,
00982 BOOL default_value = FALSE)
00983 {
00984 load_buffer();
00985 scan_blanks_and_tabs();
00986 if (!default_present) {
00987 if (buffer[buffer_start] == 'Y' || buffer[buffer_start] == 'y')
00988 *bool_value = TRUE;
00989 if (buffer[buffer_start] == 'N' || buffer[buffer_start] == 'n')
00990 *bool_value = FALSE;
00991 return;
00992 }
00993 if (default_value == TRUE) {
00994 *bool_value = TRUE;
00995 if (buffer[buffer_start] == 'N' || buffer[buffer_start] == 'n')
00996 *bool_value = FALSE;
00997 } else {
00998 *bool_value = FALSE;
00999 if (buffer[buffer_start] == 'Y' || buffer[buffer_start] == 'y')
01000 *bool_value = TRUE;
01001 }
01002 }
01003
01004
01005
01006
01007
01008
01009
01010
01011
01012
01013
01014
01015 static INT dump_whirl_node(WN* wn,
01016 char* buffer,
01017 INT cc)
01018 {
01019 BOOL printed = FALSE;
01020
01021 if (wn == NULL) {
01022 cc += sprintf(buffer + cc, "<null>");
01023 return cc;
01024 }
01025
01026 OPCODE opc = WN_opcode(wn);
01027 OPERATOR opr = OPCODE_operator(opc);
01028
01029 printed = TRUE;
01030 switch(opr) {
01031 case OPR_CONST:
01032 switch (OPCODE_rtype(opc)) {
01033 case MTYPE_F4:
01034 cc += sprintf(buffer + cc, "%g", STC_val(WN_st(wn)).vals.fval);
01035 break;
01036 case MTYPE_F8:
01037 cc += sprintf(buffer + cc, "%g", STC_val(WN_st(wn)).vals.dval);
01038 break;
01039 default:
01040 printed = FALSE;
01041 break;
01042 }
01043 break;
01044 case OPR_INTCONST:
01045 cc += sprintf(buffer + cc, "%lld", WN_const_val(wn));
01046 break;
01047 case OPR_LDID:
01048 cc += sprintf(buffer + cc, "%s", WB_Whirl_Symbol(wn));
01049 break;
01050 case OPR_ADD:
01051 cc += sprintf(buffer + cc, "+");
01052 break;
01053 case OPR_SUB:
01054 cc += sprintf(buffer + cc, "-");
01055 break;
01056 case OPR_MPY:
01057 cc += sprintf(buffer + cc, "*");
01058 break;
01059 case OPR_DIV:
01060 cc += sprintf(buffer + cc, "/");
01061 break;
01062 default:
01063 printed = FALSE;
01064 break;
01065 }
01066
01067 if (!printed) {
01068 FmtAssert(strncmp(OPCODE_name(opc), "OPC_", 4) == 0,
01069 ("opname=%s", OPCODE_name(opc)));
01070
01071 cc += sprintf(buffer + cc, "%s", OPCODE_name(opc) + 4);
01072 if (OPCODE_has_sym(opc))
01073 cc += sprintf(buffer + cc, " %s", SYMBOL(wn).Name());
01074 if (OPCODE_has_label(opc))
01075 cc += sprintf(buffer + cc, " LAB%d", WN_offset(wn));
01076 if (opr == OPR_INTRINSIC_OP || opr == OPR_INTRINSIC_CALL) {
01077 INTRINSIC i = (INTRINSIC) WN_intrinsic(wn);
01078 if (i >= INTRINSIC_FIRST && i <= INTRINSIC_LAST)
01079 cc += sprintf(buffer + cc, "<%s>", INTRINSIC_name(i));
01080 else
01081 cc += sprintf(buffer + cc, "<bad intr #=%d>", i);
01082 }
01083 else if (opr == OPR_IO)
01084 cc += sprintf(buffer + cc, "<io=%d>", WN_io_statement(wn));
01085 else if (opr == OPR_IO_ITEM)
01086 cc += sprintf(buffer + cc, "<io item=%d>", WN_io_item(wn));
01087 }
01088 return cc;
01089 }
01090
01091
01092
01093
01094
01095
01096 static BOOL Is_Leaf(WN* wn)
01097 {
01098 switch (WN_operator(wn)) {
01099 case OPR_INTCONST:
01100 case OPR_LDID:
01101 return TRUE;
01102 default:
01103 return FALSE;
01104 }
01105 }
01106
01107
01108
01109
01110
01111
01112
01113
01114
01115 static INT dump_whirl_expr(WN* wn_root,
01116 WN* wn,
01117 char* buffer,
01118 INT cc)
01119 {
01120 if (wn != wn_root && !Is_Leaf(wn))
01121 cc += sprintf(buffer + cc, "(");
01122 switch (WN_operator(wn)) {
01123 case OPR_ADD:
01124 case OPR_SUB:
01125 case OPR_MPY:
01126 case OPR_DIV:
01127 {
01128 for (INT i = 0; i < WN_kid_count(wn); i++) {
01129 cc = dump_whirl_expr(wn_root, WN_kid(wn, i), buffer, cc);
01130 if (i < WN_kid_count(wn) - 1)
01131 cc = dump_whirl_node(wn, buffer, cc);
01132 }
01133 }
01134 break;
01135 case OPR_ARRAY:
01136 {
01137 cc = dump_whirl_node(WN_array_base(wn), buffer, cc);
01138 cc += sprintf(buffer + cc, "[");
01139 for (INT i = 0; i < WN_num_dim(wn); i++) {
01140 cc = dump_whirl_expr(WN_array_index(wn, i), WN_array_index(wn, i),
01141 buffer, cc);
01142 if (i < WN_num_dim(wn) - 1)
01143 cc += sprintf(buffer + cc, ",");
01144 }
01145 cc += sprintf(buffer + cc, "]");
01146 }
01147 break;
01148 case OPR_LDID:
01149 case OPR_INTCONST:
01150 case OPR_CONST:
01151 cc = dump_whirl_node(wn, buffer, cc);
01152 break;
01153 case OPR_CALL:
01154 case OPR_INTRINSIC_CALL:
01155 case OPR_ICALL:
01156 case OPR_PICCALL:
01157 cc += sprintf(buffer + cc, "<CALL NODE>");
01158 break;
01159 default:
01160 {
01161 cc = dump_whirl_node(wn, buffer, cc);
01162 cc += sprintf(buffer + cc, "(");
01163 for (INT i = 0; i < WN_kid_count(wn); i++) {
01164 cc = dump_whirl_expr(wn_root, WN_kid(wn, i), buffer, cc);
01165 if (i < WN_kid_count(wn) - 1)
01166 cc += sprintf(buffer + cc, ",");
01167 }
01168 cc += sprintf(buffer + cc, ")");
01169 }
01170 break;
01171 }
01172 if (wn != wn_root && !Is_Leaf(wn))
01173 cc += sprintf(buffer + cc, ")");
01174 return cc;
01175 }
01176
01177
01178
01179
01180
01181
01182
01183 static void compact_buffer(char* buffer)
01184 {
01185 INT i, j;
01186 for (i = 0, j = 0; buffer[i] != '\0'; i++) {
01187 if (buffer[i] == '+' && buffer[i+1] == '-') {
01188 buffer[j++] = '-';
01189 i++;
01190 } else if (buffer[i] == '-' && buffer[i+1] == '-') {
01191 buffer[j++] = '+';
01192 i++;
01193 } else {
01194 buffer[j++] = buffer[i];
01195 }
01196 }
01197 buffer[j] = '\0';
01198 }
01199
01200
01201
01202
01203
01204
01205 extern BOOL WB_Dep_Symbol(WN* wn,
01206 char buffer[],
01207 INT max_string)
01208 {
01209 FmtAssert(max_string >= strlen("Expression too long!") + 1,
01210 ("WB_Dep_Symbol: Too short for error message"));
01211 WN* symbol_node = NULL;
01212 switch (WN_operator(wn)) {
01213 case OPR_ISTORE:
01214 symbol_node = WN_kid1(wn);
01215 break;
01216 case OPR_ILOAD:
01217 symbol_node = WN_kid0(wn);
01218 break;
01219 case OPR_CALL:
01220 case OPR_INTRINSIC_CALL:
01221 case OPR_ICALL:
01222 case OPR_PICCALL:
01223 symbol_node = wn;
01224 break;
01225 }
01226 if (symbol_node == NULL) {
01227 sprintf(buffer, " ");
01228 return TRUE;
01229 }
01230 INT cc = dump_whirl_expr(symbol_node, symbol_node, buffer, 0);
01231 if (cc > max_string) {
01232 sprintf(buffer, "Expression too long!");
01233 return FALSE;
01234 }
01235 compact_buffer(buffer);
01236 return TRUE;
01237 }
01238
01239 static void WB_Dep_Symbol(WN* wn)
01240 {
01241 char buffer[MAX_STRING_LENGTH];
01242 BOOL fits = WB_Dep_Symbol(wn, buffer, MAX_STRING_LENGTH - 1);
01243 if (!fits)
01244 bell();
01245 fprintf(stdout, "%s", buffer);
01246 }
01247
01248
01249
01250
01251
01252
01253
01254
01255
01256
01257
01258 static void WB_root()
01259 {
01260 cnode = WB_global_fd;
01261 print_this_node();
01262 }
01263
01264
01265
01266
01267
01268
01269
01270
01271
01272 static BOOL WB_Parent_Search(WN* wn_root,
01273 STACK<WN*>* stk_parent,
01274 WN* wn_node)
01275 {
01276 stk_parent->Push(wn_root);
01277 if (wn_root == wn_node)
01278 return TRUE;
01279 if (WN_opcode(wn_root) == OPC_BLOCK) {
01280 for (WN* wn = WN_first(wn_root); wn != NULL; wn = WN_next(wn)) {
01281 BOOL found_path = WB_Parent_Search(wn, stk_parent, wn_node);
01282 if (found_path)
01283 return TRUE;
01284 }
01285 } else {
01286 for (INT i = 0; i < WN_kid_count(wn_root); i++) {
01287 BOOL found_path = WB_Parent_Search(WN_kid(wn_root, i), stk_parent,
01288 wn_node);
01289 if (found_path)
01290 return TRUE;
01291 }
01292 }
01293 stk_parent->Pop();
01294 return FALSE;
01295 }
01296
01297
01298
01299
01300
01301
01302
01303 static void WB_parent()
01304 {
01305 if (cnode == WB_global_fd) {
01306 Error_Cleanup();
01307 return;
01308 }
01309 extern WN_MAP Parent_Map;
01310 if (Parent_Map <= 0) {
01311 MEM_POOL_Push(&MEM_local_pool);
01312 STACK<WN*> stk_parent(&MEM_local_pool);
01313 BOOL found_path = WB_Parent_Search(WB_global_fd, &stk_parent, cnode);
01314 if (!found_path) {
01315 Error_Cleanup();
01316 MEM_POOL_Pop(&MEM_local_pool);
01317 return;
01318 }
01319 cnode = stk_parent.Bottom_nth(stk_parent.Elements() - 2);
01320 print_this_node();
01321 MEM_POOL_Pop(&MEM_local_pool);
01322 } else {
01323 WN* pnode = LWN_Get_Parent(cnode);
01324 if (pnode == NULL) {
01325 Error_Cleanup();
01326 return;
01327 }
01328 cnode = pnode;
01329 print_this_node();
01330 }
01331 }
01332
01333
01334
01335
01336
01337
01338
01339 static void WB_next()
01340 {
01341 WN* pnode = WN_next(cnode);
01342 if (pnode == NULL) {
01343 Error_Cleanup();
01344 return;
01345 }
01346 cnode = pnode;
01347 print_this_node();
01348 }
01349
01350
01351
01352
01353
01354
01355
01356 static void WB_previous()
01357 {
01358 WN* pnode = WN_prev(cnode);
01359 if (pnode == NULL) {
01360 Error_Cleanup();
01361 return;
01362 }
01363 cnode = pnode;
01364 print_this_node();
01365 }
01366
01367
01368
01369
01370
01371
01372
01373 static void WB_set_node()
01374 {
01375 WN* node;
01376 scan_blanks_and_tabs();
01377 (void) sscanf(buffer + buffer_start, "0x%p", &node);
01378 buffer_start += 2;
01379 skip_to_separator(SKIP_HEX);
01380 cnode = node;
01381 print_this_node();
01382 }
01383
01384
01385
01386
01387
01388
01389
01390 static void WB_vset_node()
01391 {
01392 WN* node;
01393 ARRAY_DIRECTED_GRAPH16* dg = Array_Dependence_Graph;
01394 INT vertex_number = 0;
01395 scan_blanks_and_tabs();
01396 (void) sscanf(buffer + buffer_start, "%d", &vertex_number);
01397 buffer_start += 2;
01398 skip_to_separator(SKIP_NUMERIC);
01399 VINDEX16 v;
01400 for (v = dg->Get_Vertex(); v != 0; v = dg->Get_Next_Vertex(v))
01401 if (v == (VINDEX16) vertex_number)
01402 break;
01403 if (v == 0) {
01404 Error_Cleanup();
01405 return;
01406 }
01407 cnode = dg->Get_Wn((VINDEX16) vertex_number);
01408 print_this_node();
01409 }
01410
01411
01412
01413
01414
01415
01416
01417 static void WB_davinci()
01418 {
01419 if (WB_davinci_mode) {
01420 WB_davinci_mode = FALSE;
01421 fprintf(stdout, "DAVINCI is OFF.\n");
01422 } else {
01423 WB_davinci_mode = TRUE;
01424 fprintf(stdout, "DAVINCI is ON.\n");
01425 }
01426 }
01427
01428
01429
01430
01431
01432
01433
01434 static void WB_Set_Map_Id()
01435 {
01436 INT map_id;
01437 scan_blanks_and_tabs();
01438 (void) sscanf(buffer + buffer_start, "%d", &map_id);
01439 skip_to_separator(SKIP_NUMERIC);
01440 LWN_ITER* itr = LWN_WALK_TreeIter(WB_global_fd);
01441 for (; itr != NULL; itr = LWN_WALK_TreeNext(itr))
01442 if (WN_map_id(itr->wn) == map_id)
01443 break;
01444 if (itr == NULL) {
01445 Error_Cleanup();
01446 return;
01447 }
01448 cnode = itr->wn;
01449 print_this_node();
01450 }
01451
01452
01453
01454
01455
01456
01457
01458 static void WB_Map_Id()
01459 {
01460 fprintf(stdout, "%d\n", WN_map_id(cnode));
01461 }
01462
01463
01464
01465
01466
01467
01468
01469 static void WB_private()
01470 {
01471 if (cnode == NULL) {
01472 Error_Cleanup();
01473 return;
01474 }
01475 switch (WN_opcode(cnode)) {
01476 case OPC_DO_LOOP:
01477 {
01478 DO_LOOP_INFO* dli = Get_Do_Loop_Info(cnode, TRUE);
01479 if (dli != NULL && dli->ARA_Info != NULL)
01480 dli->ARA_Info->WB_Print(stdout);
01481 else
01482 Error_Cleanup();
01483 }
01484 return;
01485 default:
01486 return;
01487 }
01488 }
01489
01490
01491
01492
01493
01494
01495
01496 static void WB_address()
01497 {
01498 INT integer;
01499 scan_blanks_and_tabs();
01500 sscanf(buffer + buffer_start, "%d", &integer);
01501 skip_to_separator(SKIP_NUMERIC);
01502 if (integer < 0 || integer >= carray_max) {
01503 Error_Cleanup();
01504 return;
01505 }
01506 cnode = carray[integer];
01507 print_this_node();
01508 }
01509
01510
01511
01512
01513
01514
01515
01516
01517 static void Address_Walk(WN* wn_tree,
01518 INT spaces,
01519 INT increment)
01520 {
01521 for (INT i = 0; i < spaces; i++)
01522 fprintf(stdout, " ");
01523 print_this_node(wn_tree, FALSE, TRUE);
01524
01525 if (WN_opcode(wn_tree) == OPC_BLOCK) {
01526 for (WN* wn = WN_first(wn_tree); wn != NULL; wn = WN_next(wn))
01527 Address_Walk(wn, spaces + increment, increment);
01528 } else {
01529 for (INT i = 0; i < WN_kid_count(wn_tree); i++)
01530 Address_Walk(WN_kid(wn_tree, i), spaces + increment, increment);
01531 }
01532 }
01533
01534
01535
01536
01537
01538
01539
01540 static void WB_addresses()
01541 {
01542 Address_Walk(cnode, 0, 2);
01543 }
01544
01545
01546
01547
01548
01549
01550
01551 static void WB_fancyup()
01552 {
01553 if (fancy == fancy_max) {
01554 Error_Cleanup();
01555 return;
01556 }
01557 fancy++;
01558 }
01559
01560
01561
01562
01563
01564
01565
01566 static void WB_fancydown()
01567 {
01568 if (fancy == fancy_min) {
01569 Error_Cleanup();
01570 return;
01571 }
01572 fancy--;
01573 }
01574
01575
01576
01577
01578
01579
01580
01581 static void WB_whirl2fc()
01582 {
01583 if (WB_language == SRC_NONE) {
01584 Whirl2Src_Init(WB_global_fd);
01585 Whirl2Src_Emit(stdout, cnode);
01586 fprintf(stdout, "\n");
01587 } else if (WB_language == SRC_FORTRAN) {
01588 Whirl2F_Init(WB_global_fd);
01589 Whirl2F_Emit(stdout, cnode);
01590 fprintf(stdout, "\n");
01591 } else if (WB_language == SRC_C) {
01592 Whirl2C_Init(WB_global_fd);
01593 Whirl2C_Emit(stdout, cnode);
01594 fprintf(stdout, "\n");
01595 }
01596 }
01597
01598
01599
01600
01601
01602
01603
01604 static void WB_kids()
01605 {
01606 if (WN_kid_count(cnode) == 0) {
01607 Error_Cleanup();
01608 return;
01609 }
01610 for (INT i = 0; i < WN_kid_count(cnode); i++) {
01611 WN* kid = WN_kid(cnode, i);
01612 fprintf(stdout, "[%d] ", i);
01613 print_this_node(kid);
01614 if (i < MAX_SAVED_NODES)
01615 carray[i] = kid;
01616 }
01617 carray_max = WN_kid_count(cnode);
01618 }
01619
01620
01621
01622
01623
01624
01625
01626 static void WB_statements()
01627 {
01628 INT i = 0;
01629 if (WN_opcode(cnode) != OPC_BLOCK) {
01630 Error_Cleanup();
01631 return;
01632 }
01633 if (WN_first(cnode) == NULL) {
01634 Error_Cleanup();
01635 return;
01636 }
01637 for (WN* node = WN_first(cnode); node != NULL; i++, node = WN_next(node)) {
01638 fprintf(stdout, "[%d] ", i);
01639 print_this_node(node);
01640 if (i < MAX_SAVED_NODES)
01641 carray[i] = node;
01642 }
01643 carray_max = i;
01644 }
01645
01646
01647
01648
01649
01650
01651
01652 static void WB_this_tree()
01653 {
01654 if (cnode == NULL) {
01655 Error_Cleanup();
01656 return;
01657 }
01658 fdump_tree(stdout, cnode);
01659 }
01660
01661
01662
01663
01664
01665
01666
01667 static void WB_uses_loop()
01668 {
01669 if (WB_du_mgr == NULL) {
01670 Error_Cleanup();
01671 return;
01672 }
01673 ARRAY_DIRECTED_GRAPH16 *dg;
01674 dg = Array_Dependence_Graph;
01675 if (dg == NULL) {
01676 Error_Cleanup();
01677 return;
01678 }
01679 INT index = 0;
01680 WN* start_node = NULL;
01681 switch (WN_opcode(cnode)) {
01682 case OPC_DO_LOOP:
01683 start_node = WN_do_body(cnode);
01684 break;
01685 case OPC_DO_WHILE:
01686 case OPC_WHILE_DO:
01687 start_node = WN_while_body(cnode);
01688 break;
01689 }
01690 LWN_ITER* itr = LWN_WALK_TreeIter(start_node);
01691 for (; itr != NULL; itr = LWN_WALK_TreeNext(itr)) {
01692 WN* wn = itr->wn;
01693 USE_LIST *use_list = WB_du_mgr->Du_Get_Use(wn);
01694 if (use_list == NULL)
01695 continue;
01696 enter_this_node_unique(index, wn);
01697 WB_Dep_Symbol(wn);
01698 fprintf(stdout, "\n");
01699 if (use_list->Incomplete())
01700 fprintf(stdout, " WARNING: USE LIST INCOMPLETE\n");
01701 USE_LIST_ITER iter(use_list);
01702 const DU_NODE* node = NULL;
01703 INT i = carray_max;
01704 for (node = iter.First(); !iter.Is_Empty(); i++, node = iter.Next()) {
01705 WN* use = node->Wn();
01706 fprintf(stdout, " ");
01707 enter_this_node_unique(index, use);
01708 fprintf(stdout, "\n");
01709 }
01710 carray_max = i;
01711 }
01712 }
01713
01714 static void WB_uses_ref()
01715 {
01716 if (WB_du_mgr == NULL) {
01717 Error_Cleanup();
01718 return;
01719 }
01720 USE_LIST *use_list = WB_du_mgr->Du_Get_Use(cnode);
01721 if (use_list == NULL) {
01722 Error_Cleanup();
01723 return;
01724 }
01725 if (use_list->Incomplete())
01726 fprintf(stdout, "WARNING: USE LIST INCOMPLETE\n");
01727 USE_LIST_ITER iter(use_list);
01728 const DU_NODE* node = NULL;
01729 INT i = 0;
01730 for (node = iter.First(); !iter.Is_Empty(); i++, node = iter.Next()) {
01731 WN* use = node->Wn();
01732 fprintf(stdout, "[%d] ", i);
01733 print_this_node(use);
01734 if (i < MAX_SAVED_NODES)
01735 carray[i] = use;
01736 }
01737 carray_max = i;
01738 }
01739
01740 static void WB_uses()
01741 {
01742 switch (WN_opcode(cnode)) {
01743 case OPC_DO_LOOP:
01744 case OPC_DO_WHILE:
01745 case OPC_WHILE_DO:
01746 WB_uses_loop();
01747 break;
01748 default:
01749 WB_uses_ref();
01750 break;
01751 }
01752 }
01753
01754
01755
01756
01757
01758
01759
01760 static void WB_defs_loop()
01761 {
01762 if (WB_du_mgr == NULL) {
01763 Error_Cleanup();
01764 return;
01765 }
01766 ARRAY_DIRECTED_GRAPH16 *dg;
01767 dg = Array_Dependence_Graph;
01768 if (dg == NULL) {
01769 Error_Cleanup();
01770 return;
01771 }
01772 INT index = 0;
01773 WN* start_node = NULL;
01774 switch (WN_opcode(cnode)) {
01775 case OPC_DO_LOOP:
01776 start_node = WN_do_body(cnode);
01777 break;
01778 case OPC_DO_WHILE:
01779 case OPC_WHILE_DO:
01780 start_node = WN_while_body(cnode);
01781 break;
01782 }
01783 LWN_ITER* itr = LWN_WALK_TreeIter(start_node);
01784 for (; itr != NULL; itr = LWN_WALK_TreeNext(itr)) {
01785 WN* wn = itr->wn;
01786 DEF_LIST *def_list = WB_du_mgr->Ud_Get_Def(wn);
01787 if (def_list == NULL)
01788 continue;
01789 enter_this_node_unique(index, wn);
01790 WB_Dep_Symbol(wn);
01791 fprintf(stdout, "\n");
01792 if (def_list->Incomplete())
01793 fprintf(stdout, " WARNING: DEF LIST INCOMPLETE\n");
01794 fprintf(stdout, " Loop Statement: 0x%p\n", def_list->Loop_stmt());
01795 DEF_LIST_ITER iter(def_list);
01796 const DU_NODE* node = NULL;
01797 INT i = carray_max;
01798 for (node = iter.First(); !iter.Is_Empty(); i++, node = iter.Next()) {
01799 WN* def = node->Wn();
01800 fprintf(stdout, " ");
01801 enter_this_node_unique(index, def);
01802 fprintf(stdout, "\n");
01803 }
01804 carray_max = i;
01805 }
01806 }
01807
01808 static void WB_defs_ref()
01809 {
01810 if (WB_du_mgr == NULL) {
01811 Error_Cleanup();
01812 return;
01813 }
01814 DEF_LIST* def_list = WB_du_mgr->Ud_Get_Def(cnode);
01815 if (def_list == NULL) {
01816 Error_Cleanup();
01817 return;
01818 }
01819 if (def_list->Incomplete())
01820 fprintf(stdout, "WARNING: DEF LIST INCOMPLETE\n");
01821 fprintf(stdout, "Loop Statement: 0x%p\n", def_list->Loop_stmt());
01822 DEF_LIST_ITER iter(def_list);
01823 const DU_NODE* node = NULL;
01824 INT i = 0;
01825 for (node = iter.First(); !iter.Is_Empty(); i++, node = iter.Next()) {
01826 WN* def = node->Wn();
01827 fprintf(stdout, "[%d] ", i);
01828 print_this_node(def);
01829 if (i < MAX_SAVED_NODES)
01830 carray[i] = def;
01831 }
01832 carray_max = i;
01833 }
01834
01835 static void WB_defs()
01836 {
01837 switch (WN_opcode(cnode)) {
01838 case OPC_DO_LOOP:
01839 case OPC_DO_WHILE:
01840 case OPC_WHILE_DO:
01841 WB_defs_loop();
01842 break;
01843 default:
01844 WB_defs_ref();
01845 break;
01846 }
01847 }
01848
01849
01850
01851
01852
01853
01854
01855 static void WB_access()
01856 {
01857 OPCODE opc = WN_opcode(cnode);
01858 OPERATOR opr = OPCODE_operator(opc);
01859 if (opc == OPC_DO_LOOP || opc == OPC_IF || opr == OPR_REGION
01860 || opr == OPR_CALL || opr == OPR_ARRAY) {
01861 LNO_Print_One_Access(stdout, cnode);
01862 if (opr == OPR_DO_LOOP && Get_Do_Loop_Info(cnode, TRUE) != NULL) {
01863 WN* wn_outer_tile = Outer_Tile(cnode, WB_du_mgr);
01864 fprintf(stdout, "Outer Tile is 0x%p\n", wn_outer_tile);
01865 }
01866 } else {
01867 Error_Cleanup();
01868 }
01869 }
01870
01871
01872
01873
01874
01875
01876
01877 static void WB_RR_Map()
01878 {
01879 OPCODE opc = WN_opcode(cnode);
01880 OPERATOR opr = OPCODE_operator(opc);
01881 if (opr != OPR_ARRAY) {
01882 Error_Cleanup();
01883 } else {
01884 RR_INFO* rri = Get_RR_Map ((WN*) cnode);
01885 if (rri) rri->Print(stdout);
01886 else fprintf (stdout, "RR_Map is NULL\n");
01887 }
01888 }
01889
01890
01891
01892
01893
01894
01895
01896 static void WB_Prompf_Map()
01897 {
01898 if (Prompf_Id_Map == WN_MAP_UNDEFINED) {
01899 Error_Cleanup();
01900 return;
01901 }
01902 INT node_count = 0;
01903 LWN_ITER* itr = LWN_WALK_TreeIter(cnode);
01904 for (; itr != NULL; itr = LWN_WALK_TreeNext(itr)) {
01905 WN* wn = itr->wn;
01906 INT32 map_id = WN_MAP32_Get(Prompf_Id_Map, wn);
01907 if (map_id != 0) {
01908 fprintf(stdout, "[%d] %3d ", node_count, map_id);
01909 print_this_node(wn);
01910 if (node_count < MAX_SAVED_NODES)
01911 carray[node_count++] = wn;
01912 }
01913 }
01914 carray_max = node_count;
01915 }
01916
01917
01918
01919
01920
01921
01922
01923 static void WB_Prompf_Info()
01924 {
01925 if (!(Prompf_Info != NULL)) {
01926 Error_Cleanup();
01927 return;
01928 }
01929 Prompf_Info->Print(stdout);
01930 }
01931
01932
01933
01934
01935
01936
01937
01938
01939
01940
01941
01942
01943
01944 static void WB_DIRECTION_Print(DIRECTION dir, FILE *fp)
01945 {
01946 switch (dir) {
01947 case DIR_POS: fprintf(fp, "+"); break;
01948 case DIR_NEG: fprintf(fp, "-"); break;
01949 case DIR_EQ: fprintf(fp, "="); break;
01950 case DIR_POSNEG: fprintf(fp, "+-"); break;
01951 case DIR_POSEQ: fprintf(fp, "+="); break;
01952 case DIR_NEGEQ: fprintf(fp, "-="); break;
01953 case DIR_STAR: fprintf(fp, "*"); break;
01954 default: Is_True(0,("Illegal direction in WB_DIRECTION_Print"));
01955 };
01956 }
01957
01958 static void WB_DEP_Print(const DEP dep,FILE *fp)
01959 {
01960 if (DEP_IsDistance(dep))
01961 fprintf(fp,"%d", DEP_Distance(dep));
01962 else
01963 WB_DIRECTION_Print(DEP_Direction(dep), fp);
01964 }
01965
01966 static void WB_DEPV_Print(const DEPV *depv, FILE *fp, UINT8 num_dim)
01967 {
01968 INT i;
01969
01970 fprintf(fp, "(");
01971 for (i = 0; i < num_dim; i++) {
01972 WB_DEP_Print(DEPV_Dep(depv, i), fp);
01973 if (i < num_dim - 1)
01974 fprintf(fp, ",");
01975 }
01976 fprintf(fp, ")");
01977 }
01978
01979 void DEPV_ARRAY_Print(const DEPV_ARRAY* depv_array, FILE *fp)
01980 {
01981 for (INT i = 0; i < depv_array->Num_Vec(); i++) {
01982 WB_DEPV_Print(depv_array->Depv(i), fp, depv_array->Num_Dim());
01983 if (i < depv_array->Num_Vec() - 1)
01984 fprintf(fp, " ");
01985 }
01986 fprintf(fp, "\n");
01987 }
01988
01989 static BOOL WB_TXT_deps_loop(ARRAY_DIRECTED_GRAPH16* dg,
01990 BOOL print_arrays)
01991 {
01992 if (dg == NULL) {
01993 Error_Cleanup();
01994 return FALSE;
01995 }
01996 INT index = 0;
01997 WN* start_node = NULL;
01998 switch (WN_opcode(cnode)) {
01999 case OPC_DO_LOOP:
02000 start_node = WN_do_body(cnode);
02001 break;
02002 case OPC_DO_WHILE:
02003 case OPC_WHILE_DO:
02004 start_node = WN_while_body(cnode);
02005 break;
02006 }
02007 LWN_ITER* itr = LWN_WALK_TreeIter(start_node);
02008 for (; itr != NULL; itr = LWN_WALK_TreeNext(itr)) {
02009 WN* wn = itr->wn;
02010 VINDEX16 v = dg->Get_Vertex(wn);
02011 if (v == 0)
02012 continue;
02013 enter_this_node_unique(index, wn, FALSE);
02014 fprintf(stdout, "V#%d ", v);
02015 WB_Dep_Symbol(wn);
02016 fprintf(stdout, "\n");
02017 EINDEX16 e;
02018 if (dg->Get_In_Edge(v)) {
02019 fprintf(stdout, " ");
02020 fprintf(stdout, "IN EDGES:\n");
02021 for (e = dg->Get_In_Edge(v); e != 0; e = dg->Get_Next_In_Edge(e)) {
02022 fprintf(stdout, " ");
02023 enter_this_node_unique(index, dg->Get_Wn(dg->Get_Source(e)), FALSE);
02024 fprintf(stdout, "V#%d ", dg->Get_Source(e));
02025 fprintf(stdout, "E#%d ", e);
02026 WB_Dep_Symbol(dg->Get_Wn(dg->Get_Source(e)));
02027 fprintf(stdout, " ");
02028 if (print_arrays)
02029 DEPV_ARRAY_Print(dg->Depv_Array(e), stdout);
02030 else
02031 fprintf(stdout, "\n");
02032 }
02033 }
02034 if (dg->Get_Out_Edge(v)) {
02035 fprintf(stdout, " ");
02036 fprintf(stdout, "OUT EDGES:\n");
02037 for (e = dg->Get_Out_Edge(v); e != 0; e = dg->Get_Next_Out_Edge(e)) {
02038 fprintf(stdout, " ");
02039 enter_this_node_unique(index, dg->Get_Wn(dg->Get_Sink(e)), FALSE);
02040 fprintf(stdout, "V#%d ", dg->Get_Sink(e));
02041 fprintf(stdout, "E#%d ", e);
02042 WB_Dep_Symbol(dg->Get_Wn(dg->Get_Sink(e)));
02043 fprintf(stdout, " ");
02044 if (print_arrays)
02045 DEPV_ARRAY_Print(dg->Depv_Array(e), stdout);
02046 else
02047 fprintf(stdout, "\n");
02048 }
02049 }
02050 }
02051 carray_max = index;
02052 return TRUE;
02053 }
02054
02055
02056
02057 static DaVinci *DV_deps = NULL;
02058 static BOOL DV_deps_mempool_init = FALSE;
02059 static MEM_POOL DV_deps_mempool;
02060
02061 class DV_DEPS_CALLBACK : public DaVinci_Callback {
02062 public:
02063 virtual void Node_Select(const INT n_ids, const NODE_ID id_array[]);
02064 virtual void Edge_Select(const EDGE_ID& edge_id);
02065 virtual void Menu_Select(const char *menu_id);
02066 };
02067
02068 void DV_DEPS_CALLBACK::Node_Select(const INT n_ids,
02069 const NODE_ID id_array[])
02070 {
02071 ARRAY_DIRECTED_GRAPH16 *dg = Array_Dependence_Graph;
02072 for (INT i = 0; i < n_ids; ++i) {
02073 VINDEX16 v = VINDEX16(INTPTR(id_array[i]));
02074 WN *wn = dg->Get_Wn(v);
02075 fprintf(stdout, "V ");
02076 this_node(wn);
02077 fprintf(stdout, "V#%d ", v);
02078 WB_Dep_Symbol(wn);
02079 fprintf(stdout, "\n");
02080 }
02081 }
02082
02083 static ARRAY_DIRECTED_GRAPH16* Current_Dependence_Graph = NULL;
02084
02085 void DV_DEPS_CALLBACK::Edge_Select(const EDGE_ID& edge_id)
02086 {
02087 ARRAY_DIRECTED_GRAPH16 *dg = Current_Dependence_Graph;
02088 VINDEX16 v_src = VINDEX16(INTPTR(edge_id.src));
02089 VINDEX16 v_dst = VINDEX16(INTPTR(edge_id.dst));
02090 EINDEX16 e;
02091
02092 for (e = dg->Get_Out_Edge(v_src); e; e = dg->Get_Next_Out_Edge(e))
02093 if (dg->Get_Sink(e) == v_dst)
02094 break;
02095 if (!e) {
02096 fprintf(stdout, "ERROR: Array_Dependence_Graph edge %d -> %d not found.\n",
02097 v_src, v_dst);
02098 return;
02099 }
02100 fprintf(stdout, "E ");
02101 this_node(dg->Get_Wn(v_src));
02102 fprintf(stdout, "V#%d ", dg->Get_Source(e));
02103 fprintf(stdout, "E#%d ", e);
02104 WB_Dep_Symbol(dg->Get_Wn(dg->Get_Source(e)));
02105 fprintf(stdout, "\n");
02106 fprintf(stdout, " ");
02107 this_node(dg->Get_Wn(v_dst));
02108 fprintf(stdout, "V#%d ", dg->Get_Source(e));
02109 fprintf(stdout, "E#%d ", e);
02110 WB_Dep_Symbol(dg->Get_Wn(dg->Get_Source(e)));
02111 fprintf(stdout, "\n");
02112 fprintf(stdout, " ");
02113 if (Current_Dependence_Graph == Array_Dependence_Graph)
02114 DEPV_ARRAY_Print(dg->Depv_Array(e), stdout);
02115 else
02116 fprintf(stdout, "\n");
02117 }
02118
02119 void DV_DEPS_CALLBACK::Menu_Select(const char *menu_id)
02120 {
02121 fprintf(stdout, "DV_DEPS_CALLBACK::Menu_Select(%s)\n", menu_id);
02122 }
02123
02124 static void WB_DAV_draw_deps_loop(ARRAY_DIRECTED_GRAPH16* dg,
02125 BOOL print_arrays)
02126 {
02127 NODE_TYPE nt_box_pink;
02128 nt_box_pink.Shape(NS_BOX);
02129 nt_box_pink.Color("pink");
02130 NODE_TYPE nt_box_green;
02131 nt_box_green.Shape(NS_BOX);
02132 nt_box_green.Color("green");
02133 NODE_TYPE nt_box_blue;
02134 nt_box_blue.Shape(NS_BOX);
02135 nt_box_blue.Color("LightBlue");
02136 NODE_TYPE nt_circle_pink;
02137 nt_circle_pink.Shape(NS_CIRCLE);
02138 nt_circle_pink.Color("pink");
02139 NODE_TYPE nt_circle_green;
02140 nt_circle_green.Shape(NS_CIRCLE);
02141 nt_circle_green.Color("green");
02142 NODE_TYPE nt_circle_blue;
02143 nt_circle_blue.Shape(NS_CIRCLE);
02144 nt_circle_blue.Color("LightBlue");
02145 EDGE_TYPE et;
02146 BOOL did_loops = WB_TXT_deps_loop(dg, print_arrays);
02147 if (!did_loops)
02148 return;
02149 DV_deps->Graph_Begin();
02150 for (INT i = 0; i < carray_max; i++) {
02151 char vnum_buffer[BUFFER_MAX];
02152 WN* wn = carray[i];
02153 VINDEX16 v = dg->Get_Vertex(wn);
02154 sprintf(vnum_buffer, "%d", v);
02155 NODE_TYPE nt_local;
02156 if (Wn_Is_Inside(wn, cnode)) {
02157 if (OPCODE_is_load(WN_opcode(wn))) {
02158 nt_local = nt_circle_green;
02159 } else if (OPCODE_is_store(WN_opcode(wn))) {
02160 nt_local = nt_circle_pink;
02161 } else {
02162 nt_local = nt_circle_blue;
02163 }
02164 } else {
02165 if (OPCODE_is_load(WN_opcode(wn))) {
02166 nt_local = nt_box_green;
02167 } else if (OPCODE_is_store(WN_opcode(wn))) {
02168 nt_local = nt_box_pink;
02169 } else {
02170 nt_local = nt_box_blue;
02171 }
02172 }
02173 DV_deps->Node_Begin(NODE_ID(INTPTR(v)), vnum_buffer, nt_local);
02174 for (EINDEX16 e = dg->Get_Out_Edge(v); e; e = dg->Get_Next_Out_Edge(e)) {
02175 VINDEX16 v2 = dg->Get_Sink(e);
02176 DV_deps->Out_Edge(EDGE_ID(NODE_ID(INTPTR(v)), NODE_ID(INTPTR(v2))),
02177 et, NODE_ID(INTPTR(v2)));
02178 }
02179 DV_deps->Node_End();
02180 }
02181 DV_deps->Graph_End();
02182 }
02183
02184 static void WB_DAV_deps_loop(ARRAY_DIRECTED_GRAPH16* dg,
02185 BOOL print_arrays)
02186 {
02187 if (!DaVinci::enabled(true))
02188 return;
02189
02190 if (!DV_deps_mempool_init) {
02191 MEM_POOL_Initialize(&DV_deps_mempool, "DV_deps_mempool", FALSE);
02192 DV_deps_mempool_init = TRUE;
02193 }
02194 FILE* fp_dv = NULL;
02195 DV_deps = CXX_NEW(DaVinci(&DV_deps_mempool, fp_dv), &DV_deps_mempool);
02196 if (DV_deps->is_ok()) {
02197 char buffer[BUFFER_MAX];
02198 char* program_name = ST_name(WN_st(WB_global_fd));
02199 sprintf(buffer, "Dependence Graph for %s: Loop 0x%p",
02200 program_name, cnode);
02201 DV_deps->Title(buffer);
02202 WB_DAV_draw_deps_loop(dg, print_arrays);
02203 DV_DEPS_CALLBACK DV_deps_callback;
02204 DV_deps->Event_Loop(&DV_deps_callback);
02205 } else {
02206 fprintf(stdout, "Unable to start daVinci: Check path and DAVINCIHOME\n");
02207 Error_Cleanup();
02208 }
02209 CXX_DELETE(DV_deps, &DV_deps_mempool);
02210 DV_deps = NULL;
02211 }
02212
02213 static INT WB_TXT_deps_ref(ARRAY_DIRECTED_GRAPH16* dg,
02214 BOOL print_arrays)
02215 {
02216 if (dg == NULL) {
02217 Error_Cleanup();
02218 return -1;
02219 }
02220 VINDEX16 v = dg->Get_Vertex(cnode);
02221 if (v == 0) {
02222 Error_Cleanup();
02223 return -1;
02224 }
02225 EINDEX16 e;
02226 INT index = 0;
02227 if (!dg->Get_In_Edge(v) && !dg->Get_Out_Edge(v))
02228 fprintf(stdout, "V#%d\n", v);
02229 if (dg->Get_In_Edge(v)) {
02230 fprintf(stdout, "V#%d ", v);
02231 fprintf(stdout, "IN EDGES:\n");
02232 for (e = dg->Get_In_Edge(v); e != 0; e = dg->Get_Next_In_Edge(e)) {
02233 enter_this_node(index, dg->Get_Wn(dg->Get_Source(e)), FALSE);
02234 fprintf(stdout, "V#%d ", dg->Get_Source(e));
02235 fprintf(stdout, "E#%d ", e);
02236 WB_Dep_Symbol(dg->Get_Wn(dg->Get_Source(e)));
02237 fprintf(stdout, " ");
02238 if (print_arrays)
02239 DEPV_ARRAY_Print(dg->Depv_Array(e), stdout);
02240 else
02241 fprintf(stdout, "\n");
02242 }
02243 }
02244 INT in_index_count = index;
02245 if (dg->Get_Out_Edge(v)) {
02246 fprintf(stdout, "V#%d ", v);
02247 fprintf(stdout, "OUT EDGES:\n");
02248 for (e = dg->Get_Out_Edge(v); e != 0; e = dg->Get_Next_Out_Edge(e)) {
02249 enter_this_node(index, dg->Get_Wn(dg->Get_Sink(e)), FALSE);
02250 fprintf(stdout, "V#%d ", dg->Get_Sink(e));
02251 fprintf(stdout, "E#%d ", e);
02252 WB_Dep_Symbol(dg->Get_Wn(dg->Get_Source(e)));
02253 fprintf(stdout, " ");
02254 if (print_arrays)
02255 DEPV_ARRAY_Print(dg->Depv_Array(e), stdout);
02256 else
02257 fprintf(stdout, "\n");
02258 }
02259 }
02260 carray_max = index;
02261 return in_index_count;
02262 }
02263
02264 static void WB_DAV_draw_deps_ref(ARRAY_DIRECTED_GRAPH16* dg,
02265 BOOL print_arrays)
02266 {
02267 const INT HT_SIZE = 131;
02268 MEM_POOL_Push(&LNO_local_pool);
02269 typedef HASH_TABLE<VINDEX16, INT> HT_VINDEX;
02270 HT_VINDEX* ht = CXX_NEW(HT_VINDEX(HT_SIZE, &LNO_local_pool),
02271 &LNO_local_pool);
02272 VINDEX16 v = dg->Get_Vertex(cnode);
02273 INT in_index_count = WB_TXT_deps_ref(dg, print_arrays);
02274 if (in_index_count < 0)
02275 return;
02276 NODE_TYPE nt_box_pink;
02277 nt_box_pink.Shape(NS_BOX);
02278 nt_box_pink.Color("pink");
02279 NODE_TYPE nt_box_green;
02280 nt_box_green.Shape(NS_BOX);
02281 nt_box_green.Color("green");
02282 NODE_TYPE nt_box_blue;
02283 nt_box_blue.Shape(NS_BOX);
02284 nt_box_blue.Color("LightBlue");
02285 NODE_TYPE nt_circle_pink;
02286 nt_circle_pink.Shape(NS_CIRCLE);
02287 nt_circle_pink.Color("pink");
02288 NODE_TYPE nt_circle_green;
02289 nt_circle_green.Shape(NS_CIRCLE);
02290 nt_circle_green.Color("green");
02291 NODE_TYPE nt_circle_blue;
02292 nt_circle_blue.Shape(NS_CIRCLE);
02293 nt_circle_blue.Color("LightBlue");
02294 EDGE_TYPE et;
02295 DV_deps->Graph_Begin();
02296 for (INT i = 0; i < in_index_count; i++) {
02297 char vnum_buffer[BUFFER_MAX];
02298 WN* wn = carray[i];
02299 VINDEX16 vl = dg->Get_Vertex(wn);
02300 sprintf(vnum_buffer, "%d", vl);
02301 NODE_TYPE nt_local;
02302 if (OPCODE_is_load(WN_opcode(wn))) {
02303 nt_local = nt_box_green;
02304 } else if (OPCODE_is_store(WN_opcode(wn))) {
02305 nt_local = nt_box_pink;
02306 } else {
02307 nt_local = nt_box_blue;
02308 }
02309 if (vl != v) {
02310 ht->Enter(vl, 1);
02311 DV_deps->Node_Begin(NODE_ID(INTPTR(vl)), vnum_buffer, nt_local);
02312 DV_deps->Out_Edge(EDGE_ID(NODE_ID(INTPTR(vl)), NODE_ID(INTPTR(v))),
02313 et, NODE_ID(INTPTR(v)));
02314 DV_deps->Node_End();
02315 }
02316 }
02317 char vnum_buffer[BUFFER_MAX];
02318 sprintf(vnum_buffer, "%d", v);
02319 NODE_TYPE nt_local;
02320 if (OPCODE_is_load(WN_opcode(cnode))) {
02321 nt_local = nt_circle_green;
02322 } else if (OPCODE_is_store(WN_opcode(cnode))) {
02323 nt_local = nt_circle_pink;
02324 } else {
02325 nt_local = nt_circle_blue;
02326 }
02327 DV_deps->Node_Begin(NODE_ID(INTPTR(v)), vnum_buffer, nt_local);
02328 EINDEX16 e;
02329 for (e = dg->Get_Out_Edge(v); e; e = dg->Get_Next_Out_Edge(e)) {
02330 VINDEX16 v2 = dg->Get_Sink(e);
02331 DV_deps->Out_Edge(EDGE_ID(NODE_ID(INTPTR(v)), NODE_ID(
02332 INTPTR(v2))),
02333 et, NODE_ID(INTPTR(v2)));
02334 }
02335 DV_deps->Node_End();
02336 ht->Enter(v, 1);
02337 for (e = dg->Get_Out_Edge(v); e; e = dg->Get_Next_Out_Edge(e)) {
02338 VINDEX16 v2 = dg->Get_Sink(e);
02339 if (!ht->Find(v2)) {
02340 ht->Enter(v2, 1);
02341 WN* wn = dg->Get_Wn(v2);
02342 if (OPCODE_is_load(WN_opcode(wn))) {
02343 nt_local = nt_box_green;
02344 } else if (OPCODE_is_store(WN_opcode(wn))) {
02345 nt_local = nt_box_pink;
02346 } else {
02347 nt_local = nt_box_blue;
02348 }
02349 char vnum_buffer[BUFFER_MAX];
02350 sprintf(vnum_buffer, "%d", v2);
02351 DV_deps->Node_Begin(NODE_ID(INTPTR(v2)), vnum_buffer, nt_local);
02352 DV_deps->Node_End();
02353 }
02354 }
02355 const char* error_string = DV_deps->Graph_End();
02356 if (error_string != NULL)
02357 fprintf(stdout, "%s", error_string);
02358 MEM_POOL_Pop(&LNO_local_pool);
02359 }
02360
02361 static void WB_DAV_deps_ref(ARRAY_DIRECTED_GRAPH16* dg,
02362 BOOL print_arrays)
02363 {
02364 if (!DV_deps_mempool_init) {
02365 MEM_POOL_Initialize(&DV_deps_mempool, "DV_deps_mempool", FALSE);
02366 DV_deps_mempool_init = TRUE;
02367 }
02368 FILE* fp_dv = NULL;
02369 DV_deps = CXX_NEW(DaVinci(&DV_deps_mempool, fp_dv), &DV_deps_mempool);
02370 if (DV_deps->is_ok()) {
02371 char buffer[BUFFER_MAX];
02372 char* program_name = ST_name(WN_st(WB_global_fd));
02373 sprintf(buffer, "Dependence Graph for %s: Node 0x%p Vertex %d",
02374 program_name, cnode, dg->Get_Vertex(cnode));
02375 DV_deps->Title(buffer);
02376 WB_DAV_draw_deps_ref(dg, print_arrays);
02377 DV_DEPS_CALLBACK DV_deps_callback;
02378 DV_deps->Event_Loop(&DV_deps_callback);
02379 } else {
02380 fprintf(stdout, "Unable to start daVinci: Check path and DAVINCIHOME\n");
02381 Error_Cleanup();
02382 }
02383 CXX_DELETE(DV_deps, &DV_deps_mempool);
02384 DV_deps = NULL;
02385 }
02386
02387 static void WB_deps_loop(ARRAY_DIRECTED_GRAPH16* dg,
02388 BOOL print_arrays)
02389 {
02390 if (WB_davinci_mode)
02391 WB_DAV_deps_loop(dg, print_arrays);
02392 else
02393 WB_TXT_deps_loop(dg, print_arrays);
02394 }
02395
02396 static void WB_deps_ref(ARRAY_DIRECTED_GRAPH16* dg,
02397 BOOL print_arrays)
02398 {
02399 if (WB_davinci_mode)
02400 WB_DAV_deps_ref(dg, print_arrays);
02401 else
02402 WB_TXT_deps_ref(dg, print_arrays);
02403 }
02404
02405 static void WB_deps(ARRAY_DIRECTED_GRAPH16* dg,
02406 BOOL print_arrays)
02407 {
02408 switch (WN_opcode(cnode)) {
02409 case OPC_DO_LOOP:
02410 case OPC_DO_WHILE:
02411 case OPC_WHILE_DO:
02412 WB_deps_loop(dg, print_arrays);
02413 break;
02414 default:
02415 WB_deps_ref(dg, print_arrays);
02416 break;
02417 }
02418 }
02419
02420 static void WB_node_deps()
02421 {
02422 Current_Dependence_Graph = Array_Dependence_Graph;
02423 WB_deps(Array_Dependence_Graph, TRUE);
02424 Current_Dependence_Graph = NULL;
02425 }
02426
02427 static void WB_stmt_deps()
02428 {
02429 Current_Dependence_Graph = Statement_Dependence_Graph;
02430 WB_deps(Statement_Dependence_Graph, FALSE);
02431 Current_Dependence_Graph = NULL;
02432 }
02433
02434
02435
02436
02437
02438
02439
02440 static void WB_vertices()
02441 {
02442 ARRAY_DIRECTED_GRAPH16 *dg;
02443 dg = Array_Dependence_Graph;
02444 if (dg == NULL) {
02445 Error_Cleanup();
02446 return;
02447 }
02448 VINDEX16 v;
02449 for (v = dg->Get_Vertex(); v; v = dg->Get_Next_Vertex(v)) {
02450 WN* wn = dg->Get_Wn(v);
02451 fprintf(stdout, "V#%d ", (INT) v);
02452 this_node(wn, FALSE);
02453 WB_Dep_Symbol(wn);
02454 fprintf(stdout, "\n");
02455 }
02456 for (v = dg->Get_Vertex(); v; v = dg->Get_Next_Vertex(v))
02457 for (VINDEX16 w = dg->Get_Next_Vertex(v); w; w = dg->Get_Next_Vertex(w))
02458 if (dg->Get_Wn(v) == dg->Get_Wn(w))
02459 fprintf(stdout, "Vertices %d and %d are for the same node!\n", v, w);
02460 }
02461
02462
02463
02464
02465
02466
02467
02468 static INT reduction_count = 0;
02469
02470 static void dump_reductions(WN* wn, REDUCTION_MANAGER* rm)
02471 {
02472 if (WN_opcode(wn) == OPC_BLOCK) {
02473 for (WN* wn_temp = WN_first(wn); wn_temp; wn_temp = WN_next(wn_temp))
02474 dump_reductions(wn_temp, rm);
02475 } else {
02476 if (OPCODE_is_load(WN_opcode(wn)) || OPCODE_is_store(WN_opcode(wn))) {
02477 REDUCTION_TYPE red_type = rm->Which_Reduction(wn);
02478 switch (red_type) {
02479 case RED_ADD:
02480 fprintf(stdout, "[%d] 0x%p RED_ADD ", reduction_count, wn);
02481 break;
02482 case RED_MPY:
02483 fprintf(stdout, "[%d] 0x%p RED_MPY ", reduction_count, wn);
02484 break;
02485 case RED_MIN:
02486 fprintf(stdout, "[%d] 0x%p RED_MIN ", reduction_count, wn);
02487 break;
02488 case RED_MAX:
02489 fprintf(stdout, "[%d] 0x%p RED_MAX ", reduction_count, wn);
02490 break;
02491 }
02492 switch (red_type) {
02493 case RED_ADD:
02494 case RED_MPY:
02495 case RED_MIN:
02496 case RED_MAX:
02497 OPERATOR oper = WN_operator(wn);
02498 if (oper == OPR_ILOAD || oper == OPR_ISTORE) {
02499 WB_Dep_Symbol(wn);
02500 fprintf(stdout, "\n");
02501 } else {
02502 const char *name = WB_Whirl_Symbol(wn);
02503 fprintf(stdout, "%s\n", name);
02504 }
02505 if (reduction_count < MAX_SAVED_NODES)
02506 carray[reduction_count++] = wn;
02507 break;
02508 }
02509 }
02510 for (INT i = 0; i < WN_kid_count(wn); i++)
02511 dump_reductions(WN_kid(wn, i), rm);
02512 }
02513 }
02514
02515 static void WB_reduction()
02516 {
02517 REDUCTION_MANAGER *rm;
02518 rm = red_manager;
02519 if (rm == NULL) {
02520 Error_Cleanup();
02521 return;
02522 }
02523 reduction_count = 0;
02524 dump_reductions(cnode, rm);
02525 carray_max = reduction_count;
02526 }
02527
02528
02529
02530
02531
02532
02533
02534 static INT alias_count = 0;
02535
02536 static BOOL aliased_node(WN* wn)
02537 {
02538 OPCODE opc = WN_opcode(wn);
02539 OPERATOR opr = OPCODE_operator(opc);
02540 return (OPCODE_is_load(opc) || OPCODE_is_store(opc) || opr == OPR_PARM)
02541 && WB_alias_mgr->Id(wn) != 0;
02542 }
02543
02544 static void alias_walk(WN* wn_test,
02545 WN* wn_start,
02546 ALIAS_RESULT ar)
02547 {
02548 if (aliased_node(wn_start)) {
02549 ALIAS_RESULT result = Aliased(WB_alias_mgr, wn_test, wn_start);
02550 switch (result) {
02551 case NOT_ALIASED:
02552 break;
02553 case POSSIBLY_ALIASED:
02554 case SAME_LOCATION:
02555 if (ar == result) {
02556 fprintf(stdout, " [%d] ", alias_count);
02557 print_this_node(wn_start);
02558 if (alias_count < MAX_SAVED_NODES)
02559 carray[alias_count++] = wn_start;
02560 }
02561 break;
02562 }
02563 }
02564
02565 if (WN_opcode(wn_start) == OPC_BLOCK) {
02566 for (WN* wn = WN_first(wn_start); wn != NULL; wn = WN_next(wn))
02567 alias_walk(wn_test, wn, ar);
02568 } else {
02569 for (INT i = 0; i < WN_kid_count(wn_start); i++)
02570 alias_walk(wn_test, WN_kid(wn_start, i), ar);
02571 }
02572 }
02573
02574 static void WB_alias()
02575 {
02576 if (!aliased_node(cnode)) {
02577 Error_Cleanup();
02578 return;
02579 }
02580 alias_count = 0;
02581 fprintf(stdout, "POSSIBLY ALIASED: \n");
02582 alias_walk(cnode, WB_global_fd, POSSIBLY_ALIASED);
02583 if (alias_count == 0)
02584 fprintf(stdout, " NO LOCATIONS\n");
02585 INT possible_aliases = alias_count;
02586 fprintf(stdout, "SAME LOCATION: \n");
02587 alias_walk(cnode, WB_global_fd, SAME_LOCATION);
02588 if (alias_count == possible_aliases)
02589 fprintf(stdout, " NO LOCATIONS\n");
02590 carray_max = alias_count;
02591 }
02592
02593
02594
02595
02596
02597
02598
02599 static void WB_ancestors()
02600 {
02601 INT index = 0;
02602 if (cnode == WB_global_fd) {
02603 Error_Cleanup();
02604 return;
02605 }
02606 extern WN_MAP Parent_Map;
02607 if (Parent_Map <= 0) {
02608 MEM_POOL_Push(&MEM_local_pool);
02609 STACK<WN*> stk_parent(&MEM_local_pool);
02610 BOOL found_path = WB_Parent_Search(WB_global_fd, &stk_parent, cnode);
02611 if (!found_path) {
02612 Error_Cleanup();
02613 MEM_POOL_Pop(&MEM_local_pool);
02614 return;
02615 }
02616 for (INT i = stk_parent.Elements() - 1; i >= 0; i--) {
02617 enter_this_node(index, stk_parent.Bottom_nth(i));
02618 fprintf(stdout, "\n");
02619 }
02620 carray_max = index;
02621 MEM_POOL_Pop(&MEM_local_pool);
02622 } else {
02623 for (WN* wn = cnode; wn != NULL; wn = LWN_Get_Parent(wn)) {
02624 enter_this_node(index, wn);
02625 fprintf(stdout, "\n");
02626 }
02627 carray_max = index;
02628 }
02629 }
02630
02631
02632
02633
02634
02635
02636
02637 extern ST_IDX Compute_ST_IDX(UINT32 st_level,
02638 UINT32 st_index)
02639 {
02640 UINT32 st_idx = st_level + (st_index << 8);
02641 return (ST_IDX) (st_idx);
02642 }
02643
02644
02645
02646
02647
02648
02649
02650 static void WB_symbol()
02651 {
02652 if (buffer[buffer_start] == '<') {
02653 UINT32 st_level;
02654 UINT32 st_index;
02655 char comma;
02656 char right_angle_bracket;
02657 buffer_start++;
02658 scan_blanks_and_tabs();
02659 (void) sscanf(buffer + buffer_start, "%d", &st_level);
02660 skip_to_separator(SKIP_NUMERIC);
02661 scan_blanks_and_tabs();
02662 (void) sscanf(buffer + buffer_start, "%c", &comma);
02663 if (comma != ',') {
02664 Error_Cleanup();
02665 return;
02666 }
02667 buffer_start++;
02668 scan_blanks_and_tabs();
02669 (void) sscanf(buffer + buffer_start, "%d", &st_index);
02670 skip_to_separator(SKIP_NUMERIC);
02671 scan_blanks_and_tabs();
02672 (void) sscanf(buffer + buffer_start, "%c", &right_angle_bracket);
02673 if (right_angle_bracket != '>') {
02674 Error_Cleanup();
02675 return;
02676 }
02677 buffer_start++;
02678 ST_IDX st_idx = Compute_ST_IDX(st_level, st_index);
02679 ST* st = &St_Table[st_idx];
02680 fprintf(stdout, "ST_IDX: %d\n", st_idx);
02681 Print_ST(stdout, st, TRUE);
02682 } else if (isdigit(buffer[buffer_start])) {
02683 ST_IDX st_idx;
02684 (void) sscanf(buffer + buffer_start, "%d", &st_idx);
02685 skip_to_separator(SKIP_NUMERIC);
02686 ST* st = &St_Table[st_idx];
02687 fprintf(stdout, "ST_IDX: %d\n", st_idx);
02688 Print_ST(stdout, st, TRUE);
02689 } else {
02690 if (!OPCODE_has_sym(WN_opcode(cnode))) {
02691 Error_Cleanup();
02692 return;
02693 }
02694 fprintf(stdout, "ST_IDX: %d\n", WN_st_idx (cnode));
02695 Print_ST(stdout, WN_st(cnode), TRUE);
02696 }
02697 }
02698
02699
02700
02701
02702
02703
02704
02705 static void WB_type()
02706 {
02707 if (buffer[buffer_start] == '<') {
02708 char right_angle_bracket;
02709 UINT32 ty_index = 0;
02710 buffer_start++;
02711 scan_blanks_and_tabs();
02712 (void) sscanf(buffer + buffer_start, "%d", &ty_index);
02713 skip_to_separator(SKIP_NUMERIC);
02714 scan_blanks_and_tabs();
02715 (void) sscanf(buffer + buffer_start, "%c", &right_angle_bracket);
02716 if (right_angle_bracket != '>') {
02717 Error_Cleanup();
02718 return;
02719 }
02720 buffer_start++;
02721 Ty_tab[ty_index].Print(stdout);
02722 } else if (isdigit(buffer[buffer_start])) {
02723 TY_IDX ty_idx = 0;
02724 (void) sscanf(buffer + buffer_start, "%d", &ty_idx);
02725 skip_to_separator(SKIP_NUMERIC);
02726 Print_TY(stdout, ty_idx);
02727 } else {
02728 if (!OPCODE_has_sym(WN_opcode(cnode))) {
02729 Error_Cleanup();
02730 return;
02731 }
02732 Print_TY(stdout, ST_type(WN_st(cnode)));
02733 }
02734 }
02735
02736
02737
02738
02739
02740
02741
02742 static void WB_type_table()
02743 {
02744 WN* node;
02745 INT type_number;
02746 fprintf(stdout, "Available types:\n");
02747 INT i;
02748 for (i = 0; Type_List[i].type[0] != '\0'; i++)
02749 fprintf(stdout, " (%d) %s\n", i, Type_List[i].type);
02750 INT last_type_number = i - 1;
02751 fprintf(stdout, "Select a type by number: ");
02752 load_buffer();
02753 scan_blanks_and_tabs();
02754 sscanf(buffer + buffer_start, "%d", &type_number);
02755 skip_to_separator(SKIP_NUMERIC);
02756 if (type_number < 0 || type_number > last_type_number) {
02757 fprintf(stdout, "Incorrect number selected.\n");
02758 Error_Cleanup();
02759 return;
02760 }
02761 fprintf(stdout, "Enter address: ");
02762 load_buffer();
02763 scan_blanks_and_tabs();
02764 sscanf(buffer + buffer_start, "\n0x%p", &node);
02765 buffer_start += 3;
02766 skip_to_separator(SKIP_HEX);
02767 cnode = node;
02768 if (cnode == 0) {
02769 fprintf(stdout, "Bad address.\n");
02770 Error_Cleanup();
02771 return;
02772 }
02773 (*(Type_List[type_number].fp))();
02774 prompt();
02775 load_buffer();
02776 scan_blanks_and_tabs();
02777 }
02778
02779
02780
02781
02782
02783
02784
02785 static INT loop_count = 0;
02786
02787 #define WN_MAP_check_kind(maptab, wn_map, kind) \
02788 ((maptab)->_kind[(wn_map)] == (kind))
02789
02790 static BOOL WN_Map_Valid(WN_MAP wn_map)
02791 {
02792 WN_MAP_TAB* maptab = Current_Map_Tab;
02793 if (!maptab->_is_used[wn_map])
02794 return FALSE;
02795 if (!WN_MAP_check_kind(maptab, wn_map, WN_MAP_KIND_VOIDP))
02796 return FALSE;
02797 return TRUE;
02798 }
02799
02800 extern void dump_loops(WN* wn, FILE* fp, INT spaces, INT increment)
02801 {
02802 switch (WN_opcode(wn)) {
02803 case OPC_BLOCK: {
02804 for (WN* w = WN_first(wn); w; w = WN_next(w))
02805 dump_loops(w, fp, spaces, increment);
02806 }
02807 break;
02808 case OPC_DO_LOOP: {
02809 dump_spaces(fp, spaces);
02810 DO_LOOP_INFO* dli = WN_Map_Valid(LNO_Info_Map)
02811 ? Get_Do_Loop_Info(wn, TRUE) : NULL;
02812 if (dli == NULL) {
02813 const char *name = WB_Whirl_Symbol(wn);
02814 if (Prompf_Id_Map != WN_MAP_UNDEFINED) {
02815 fprintf(fp, "[%d] 0x%p DOLOOP (%d) <%d> %s\n", loop_count, wn,
02816 (INT) WN_linenum(wn), WN_MAP32_Get(Prompf_Id_Map, wn), name);
02817 } else {
02818 fprintf(fp, "[%d] 0x%p DOLOOP (%d) %s\n", loop_count, wn,
02819 (INT) WN_linenum(wn), name);
02820 }
02821 } else {
02822 const char *name = WB_Whirl_Symbol(wn);
02823 if (Prompf_Info != NULL) {
02824 fprintf(fp, "[%d] 0x%p DOLOOP %d (%d) <%d> %s\n", loop_count, wn,
02825 dli->Depth, (INT) WN_linenum(wn), WN_MAP32_Get(Prompf_Id_Map, wn),
02826 name);
02827 } else {
02828 fprintf(fp, "[%d] 0x%p DOLOOP %d (%d) %s\n", loop_count,
02829 wn, dli->Depth, (INT) WN_linenum(wn), name);
02830 }
02831 }
02832 if (loop_count < MAX_SAVED_NODES)
02833 carray[loop_count++] = wn;
02834 dump_loops(WN_do_body(wn), fp, spaces + increment, increment);
02835 }
02836 break;
02837 case OPC_FUNC_ENTRY:
02838 dump_spaces(fp, spaces);
02839 if (Prompf_Info != NULL) {
02840 fprintf(fp, "[%d] 0x%p FUNC_ENTRY <%d> %s\n", loop_count, wn,
02841 WN_MAP32_Get(Prompf_Id_Map, wn), WB_Whirl_Symbol(wn));
02842 } else {
02843 fprintf(fp, "[%d] 0x%p FUNC_ENTRY %s\n", loop_count, wn,
02844 WB_Whirl_Symbol(wn));
02845 }
02846 if (loop_count < MAX_SAVED_NODES)
02847 carray[loop_count++] = wn;
02848 dump_loops(WN_func_body(wn), fp, spaces + increment, increment);
02849 break;
02850 case OPC_IF:
02851 if (fancy < 3) {
02852 dump_loops(WN_then(wn), fp, spaces, increment);
02853 dump_loops(WN_else(wn), fp, spaces, increment);
02854 } else {
02855 dump_spaces(fp, spaces);
02856 fprintf(fp, "[%d] 0x%p IF ([%d] 0x%p) THEN [%d] 0x%p\n",
02857 loop_count, wn, loop_count + 1, WN_if_test(wn),
02858 loop_count + 2, WN_then(wn));
02859 INT if_loop_count = loop_count;
02860 if (loop_count < MAX_SAVED_NODES)
02861 carray[loop_count++] = wn;
02862 if (loop_count < MAX_SAVED_NODES)
02863 carray[loop_count++] = WN_if_test(wn);
02864 if (loop_count < MAX_SAVED_NODES)
02865 carray[loop_count++] = WN_then(wn);
02866 dump_loops(WN_then(wn), fp, spaces + increment, increment);
02867 if (!WN_else_is_empty(wn)) {
02868 dump_spaces(fp, spaces);
02869 fprintf(fp, "[%d] 0x%p ELSE\n", loop_count, WN_else(wn));
02870 if (loop_count < MAX_SAVED_NODES)
02871 carray[loop_count++] = WN_else(wn);
02872 dump_loops(WN_else(wn), fp, spaces + increment, increment);
02873 }
02874 dump_spaces(fp, spaces);
02875 fprintf(fp, "[%d] 0x%p ENDIF\n", if_loop_count, wn);
02876 }
02877 break;
02878 case OPC_DO_WHILE:
02879 dump_spaces(fp, spaces);
02880 fprintf(fp, "[%d] 0x%p DO_WHILE_LOOP (%d) \n", loop_count, wn,
02881 (INT) WN_linenum(wn));
02882 if (loop_count < MAX_SAVED_NODES)
02883 carray[loop_count++] = wn;
02884 dump_loops(WN_while_body(wn), fp, spaces + increment, increment);
02885 break;
02886 case OPC_WHILE_DO:
02887 dump_spaces(fp, spaces);
02888 fprintf(fp, "[%d] 0x%p WHILE_DO_LOOP (%d) \n", loop_count, wn,
02889 (INT) WN_linenum(wn));
02890 if (loop_count < MAX_SAVED_NODES)
02891 carray[loop_count++] = wn;
02892 dump_loops(WN_while_body(wn), fp, spaces + increment, increment);
02893 break;
02894 case OPC_REGION:
02895 if (fancy >= 3) {
02896 dump_spaces(fp, spaces);
02897 if (Prompf_Info != NULL) {
02898 fprintf(fp, "[%d] 0x%p REGION <%d>\n", loop_count, wn,
02899 WN_MAP32_Get(Prompf_Id_Map, wn));
02900 } else {
02901 fprintf(fp, "[%d] 0x%p REGION \n", loop_count, wn);
02902 }
02903 if (loop_count < MAX_SAVED_NODES)
02904 carray[loop_count++] = wn;
02905 for (INT i = 0; i < WN_kid_count(wn); i++)
02906 dump_loops(WN_kid(wn, i), fp, spaces + increment, increment);
02907 } else {
02908 for (INT i = 0; i < WN_kid_count(wn); i++)
02909 dump_loops(WN_kid(wn, i), fp, spaces, increment);
02910 }
02911 }
02912 }
02913
02914 static void WB_loops()
02915 {
02916 loop_count = 0;
02917 dump_loops(cnode, stdout, 0, 2);
02918 carray_max = loop_count;
02919 }
02920
02921
02922
02923
02924
02925
02926
02927 static void Lisp_Loops_Traverse(WN* wn_tree,
02928 INT spaces,
02929 INT increment,
02930 FILE* fp)
02931 {
02932 switch (WN_opcode(wn_tree)) {
02933 case OPC_DO_LOOP:
02934 {
02935 fprintf(fp, "\n");
02936 fflush(fp);
02937 dump_spaces(fp, spaces);
02938 fprintf(fp, "(DO ");
02939 const char *name = WB_Whirl_Symbol(wn_tree);
02940 fprintf(fp, "\"%s\"", name);
02941 if (WB_sanity_check_level != WBC_DISABLE) {
02942 DO_LOOP_INFO* dli = Get_Do_Loop_Info(wn_tree);
02943 fprintf(fp, "\n");
02944 fflush(fp);
02945 dump_spaces(fp, spaces + increment);
02946 fprintf(fp, " (LOOP_INFO");
02947 if (dli->Is_Cache_Winddown()) {
02948 fprintf(fp, "\n");
02949 fflush(fp);
02950 dump_spaces(fp, spaces + 2 * increment);
02951 fprintf(fp, "(CACHE_WINDDOWN)");
02952 }
02953 if (dli->Is_Register_Winddown()) {
02954 fprintf(fp, "\n");
02955 fflush(fp);
02956 dump_spaces(fp, spaces + 2 * increment);
02957 fprintf(fp, "(REGISTER_WINDDOWN)");
02958 }
02959 if (dli->Is_Generally_Unimportant()) {
02960 fprintf(fp, "\n");
02961 fflush(fp);
02962 dump_spaces(fp, spaces + 2 * increment);
02963 fprintf(fp, "(GENERALLY_UNIMPORTANT)");
02964 }
02965 fprintf(fp, "\n");
02966 fflush(fp);
02967 dump_spaces(fp, spaces + 2 * increment);
02968 fprintf(fp, " (TOTAL_ITERATIONS");
02969 INT64 iteration_count = Iterations(wn_tree, &LNO_local_pool);
02970 if (iteration_count != -1LL)
02971 fprintf(fp, " (EXACT %lld)", iteration_count);
02972 INT64 upper_bound = -1LL;
02973 if (dli->Is_Inner_Tile && dli->Tile_Size > 0
02974 && (upper_bound == -1LL || upper_bound > dli->Tile_Size))
02975 upper_bound = dli->Tile_Size;
02976 if (dli->Est_Max_Iterations_Index != -1LL
02977 && (upper_bound == -1LL
02978 || upper_bound > dli->Est_Max_Iterations_Index))
02979 upper_bound = dli->Est_Max_Iterations_Index;
02980 if (upper_bound != -1LL)
02981 fprintf(fp, " (UPPER_BOUND %lld)", upper_bound);
02982 if (dli->Num_Iterations_Profile)
02983 fprintf(fp, " (FEEDBACK %lld)", dli->Est_Num_Iterations);
02984 else if (iteration_count == -1LL && dli->Est_Num_Iterations != -1LL)
02985 fprintf(fp, " (ESTIMATE %lld)", dli->Est_Num_Iterations);
02986 fprintf(fp, ")");
02987 fprintf(fp, ")");
02988 }
02989 for (INT i = 0; i < WN_kid_count(wn_tree); i++)
02990 Lisp_Loops_Traverse(WN_kid(wn_tree, i), spaces + increment,
02991 increment, fp);
02992 fprintf(fp, ")");
02993 }
02994 break;
02995 case OPC_DO_WHILE:
02996 {
02997 fprintf(fp, "\n");
02998 fflush(fp);
02999 dump_spaces(fp, spaces);
03000 fprintf(fp, "(DO-WHILE ");
03001 for (INT i = 0; i < WN_kid_count(wn_tree); i++)
03002 Lisp_Loops_Traverse(WN_kid(wn_tree, i), spaces + increment,
03003 increment, fp);
03004 fprintf(fp, ")");
03005 }
03006 break;
03007 case OPC_WHILE_DO:
03008 {
03009 fprintf(fp, "\n");
03010 fflush(fp);
03011 dump_spaces(fp, spaces);
03012 fprintf(fp, "(WHILE-DO ");
03013 for (INT i = 0; i < WN_kid_count(wn_tree); i++)
03014 Lisp_Loops_Traverse(WN_kid(wn_tree, i), spaces + increment,
03015 increment, fp);
03016 fprintf(fp, ")");
03017 }
03018 break;
03019 case OPC_BLOCK:
03020 {
03021 for (WN* wn = WN_first(wn_tree); wn != NULL; wn = WN_next(wn))
03022 Lisp_Loops_Traverse(wn, spaces, increment, fp);
03023 }
03024 break;
03025 default:
03026 {
03027 for (INT i = 0; i < WN_kid_count(wn_tree); i++)
03028 Lisp_Loops_Traverse(WN_kid(wn_tree, i), spaces, increment, fp);
03029 }
03030 break;
03031 }
03032 }
03033
03034 extern void Lisp_Loops(WN* wn_root,
03035 FILE *fp)
03036 {
03037 fprintf(fp, "(POST_LNO_LOOPS");
03038 Lisp_Loops_Traverse(wn_root, 2, 2, fp);
03039 fprintf(fp, ")\n");
03040 fflush(fp);
03041 }
03042
03043 static void WB_lisp_loops()
03044 {
03045 Lisp_Loops(WB_global_fd, stdout);
03046 }
03047
03048
03049
03050
03051
03052
03053
03054 static void WB_transform()
03055 {
03056 INT transform_number;
03057 fprintf(stdout, "Current loop nest structure:\n");
03058 WB_loops();
03059 fprintf(stdout, "\n");
03060 fprintf(stdout, "Available transformations:\n");
03061 INT i;
03062 for (i = 0; Transform_List[i].type[0] != '\0'; i++)
03063 fprintf(stdout, " (%d) %s\n", i, Transform_List[i].type);
03064 INT last_transform_number = i - 1;
03065 fprintf(stdout, "Select a transformation by number: ");
03066 Load_Integer(&transform_number);
03067 if (transform_number < 0 || transform_number > last_transform_number) {
03068 fprintf(stdout, "Incorrect number selected.\n");
03069 Error_Cleanup();
03070 return;
03071 }
03072 BOOL trans_result = (*(Transform_List[transform_number].fp))();
03073 if (!trans_result)
03074 return;
03075 fprintf(stdout, "\n");
03076 fprintf(stdout, "Transformed loop nest structure:\n");
03077 WB_loops();
03078 prompt();
03079 load_buffer();
03080 scan_blanks_and_tabs();
03081 }
03082
03083
03084
03085
03086
03087
03088
03089 static void WB_check()
03090 {
03091 switch (WB_sanity_check_level) {
03092 case WBC_DISABLE:
03093 fprintf(stdout, "SANITY CHECKING IS DISABLED\n");
03094 Error_Cleanup();
03095 break;
03096 case WBC_DU_ONLY:
03097 #ifdef Is_True_On
03098 Du_Sanity_Check(WB_global_fd);
03099 #endif
03100 break;
03101 case WBC_DU_AND_ARRAY:
03102 #ifdef Is_True_On
03103 Du_Sanity_Check(WB_global_fd);
03104 Array_Dependence_Graph->Check_Graph();
03105 LNO_Check_Graph(Array_Dependence_Graph);
03106 #endif
03107 break;
03108 case WBC_FULL_SNL:
03109 #ifdef Is_True_On
03110 Du_Sanity_Check(WB_global_fd);
03111 Array_Dependence_Graph->Check_Graph();
03112 LNO_Check_Graph(Array_Dependence_Graph);
03113 SNL_Sanity_Check_Func(WB_global_fd);
03114 #endif
03115 break;
03116 default:
03117 FmtAssert(0, ("Bad value for sanity check level in whirl browser."));
03118 break;
03119 }
03120 }
03121
03122
03123
03124
03125
03126
03127
03128 static BOOL Is_Substring(const char s1[],
03129 const char s2[])
03130 {
03131 INT substring_length = strlen(s1);
03132 INT string_length = strlen(s2);
03133 INT difference = string_length - substring_length;
03134 if (substring_length > string_length)
03135 return FALSE;
03136 for (INT i = 0; i <= difference; i++) {
03137 INT j;
03138 for (j = 0; j < substring_length; j++)
03139 if (s1[j] != s2[i + j])
03140 break;
03141 if (j == substring_length)
03142 return TRUE;
03143 }
03144 return FALSE;
03145 }
03146
03147
03148
03149
03150
03151
03152
03153
03154
03155 static INT find_count = 0;
03156
03157 static void find_walk(char *s, WN* wn)
03158 {
03159 if (wn == NULL)
03160 return;
03161 BOOL test_substring = s[0] == '\'';
03162 const char* wn_symbol = WB_Whirl_Symbol(wn);
03163 if (wn_symbol != NULL && (!test_substring && strcmp(wn_symbol, s) == 0
03164 || test_substring && Is_Substring(&s[1], wn_symbol))) {
03165 fprintf(stdout, "[%d] ", find_count);
03166 print_this_node(wn);
03167 if (find_count < MAX_SAVED_NODES)
03168 carray[find_count] = wn;
03169 find_count++;
03170 }
03171 for (INT i = 0; i < WN_kid_count(wn); i++)
03172 find_walk(s, WN_kid(wn, i));
03173 if (WN_opcode(wn) == OPC_BLOCK)
03174 for (WN* wn_sub = WN_first(wn); wn_sub != NULL; wn_sub = WN_next(wn_sub))
03175 find_walk(s, wn_sub);
03176 }
03177
03178 static void WB_find_string(char* s)
03179 {
03180 find_count = 0;
03181 find_walk(s, cnode);
03182 carray_max = find_count;
03183 }
03184
03185 static void WB_find()
03186 {
03187 char s[MAX_STRING_LENGTH];
03188 scan_blanks_and_tabs();
03189 sscanf(buffer + buffer_start, "%s", s);
03190 INT i;
03191 for (i = 0; s[i] != '\0'; i++)
03192 if (s[i] == '\n' || s[i] == ';')
03193 break;
03194 s[i] = '\0';
03195 skip_to_separator(SKIP_ALPHANUMERIC);
03196 WB_find_string(s);
03197 }
03198
03199
03200
03201
03202
03203
03204
03205 static void WB_find_symbols()
03206 {
03207 ST* st = NULL;
03208 char s[MAX_STRING_LENGTH];
03209 scan_blanks_and_tabs();
03210 sscanf(buffer + buffer_start, "%s", s);
03211 INT i;
03212 for (i = 0; s[i] != '\0'; i++)
03213 if (s[i] == '\n' || s[i] == ';')
03214 break;
03215 s[i] = '\0';
03216 skip_to_separator(SKIP_ALPHANUMERIC);
03217 BOOL test_substring = s[0] == '\'';
03218 #ifdef _NEW_SYMTAB
03219 FOREACH_SYMBOL(CURRENT_SYMTAB, st, i) {
03220 #else
03221 SYMTAB* symtab = Current_Symtab;
03222 for (st = SYMTAB_symbols(symtab); st != NULL; st = ST_next(st)) {
03223 #endif
03224 if ((!test_substring && strcmp(ST_name(st), s) == 0
03225 || test_substring && Is_Substring(&s[1], ST_name(st)))) {
03226 Print_ST(stdout, st, TRUE);
03227 }
03228 }
03229 #ifdef _NEW_SYMTAB
03230 FOREACH_SYMBOL(GLOBAL_SYMTAB, st, i) {
03231 if ((!test_substring && strcmp(ST_name(st), s) == 0
03232 || test_substring && Is_Substring(&s[1], ST_name(st)))) {
03233 Print_ST(stdout, st, TRUE);
03234 }
03235 }
03236 #endif
03237 }
03238
03239
03240
03241
03242
03243
03244
03245 static INT findopr_count = 0;
03246
03247 static void findopr_walk(OPERATOR opr_test, WN* wn)
03248 {
03249 if (wn == NULL)
03250 return;
03251 if (WN_operator(wn) == opr_test) {
03252 fprintf(stdout, "[%d] ", findopr_count);
03253 print_this_node(wn);
03254 if (findopr_count < MAX_SAVED_NODES)
03255 carray[findopr_count] = wn;
03256 findopr_count++;
03257 }
03258 if (WN_opcode(wn) == OPC_BLOCK) {
03259 for (WN* wn_sub = WN_first(wn); wn_sub != NULL; wn_sub = WN_next(wn_sub))
03260 findopr_walk(opr_test, wn_sub);
03261 } else {
03262 for (INT i = 0; i < WN_kid_count(wn); i++)
03263 findopr_walk(opr_test, WN_kid(wn, i));
03264 }
03265 }
03266
03267 static void WB_findopr_string(OPERATOR opr_test)
03268 {
03269 findopr_count = 0;
03270 findopr_walk(opr_test, cnode);
03271 carray_max = findopr_count;
03272 }
03273
03274 static void WB_findopr()
03275 {
03276 OPERATOR opr_test;
03277 char s[MAX_STRING_LENGTH];
03278 scan_blanks_and_tabs();
03279 sscanf(buffer + buffer_start, "%s", s);
03280 INT i;
03281 for (i = 0; s[i] != '\0'; i++)
03282 if (s[i] == '\n' || s[i] == ';')
03283 break;
03284 s[i] = '\0';
03285 skip_to_separator(SKIP_ALPHANUMERIC);
03286 for (i = 1; i <= OPERATOR_LAST; i++)
03287 if (!strcmp(s, operator_table[i]))
03288 break;
03289 if (i > OPERATOR_LAST) {
03290 Error_Cleanup();
03291 return;
03292 }
03293 WB_findopr_string((OPERATOR) i);
03294 }
03295
03296
03297
03298
03299
03300
03301
03302 static void WB_whirl2fset()
03303 {
03304 if (WB_language != SRC_FORTRAN) {
03305 Whirl2F_Init(WB_global_fd);
03306 WB_language = SRC_FORTRAN;
03307 }
03308 fprintf(stdout, "WHIRL-TO-SOURCE language is FORTRAN. ");
03309 fprintf(stdout, "\n");
03310 }
03311
03312
03313
03314
03315
03316
03317
03318 static void WB_whirl2cset()
03319 {
03320 if (WB_language != SRC_C) {
03321 Whirl2C_Init(WB_global_fd);
03322 WB_language = SRC_C;
03323 }
03324 fprintf(stdout, "WHIRL-TO-SOURCE language is C.\n");
03325 }
03326
03327
03328
03329
03330
03331
03332
03333 static void WB_scratch()
03334 {
03335 if (FORMULA::Fpool == NULL) {
03336 Error_Cleanup();
03337 return;
03338 }
03339 INT scratch_register = -1;
03340 scan_blanks_and_tabs();
03341 (void) sscanf(buffer + buffer_start, "%d", &scratch_register);
03342 skip_to_separator(SKIP_NUMERIC);
03343 if (!(scratch_register >= 0 && scratch_register
03344 < FORMULA::SCRATCH_REGISTERS)) {
03345 Error_Cleanup();
03346 return;
03347 }
03348 double dvalue = FORMULA::Use(scratch_register)->Eval(0, (double *) NULL);
03349 fprintf(stdout, "Value is %.4g\n", dvalue);
03350 }
03351
03352
03353
03354
03355
03356
03357
03358 static void WB_last_command()
03359 {
03360 INT i;
03361 for (i = 0; Command_List[i].ch != '\0'; i++)
03362 if (Command_List[i].context_independent && Command_List[i].ch == last_ch)
03363 break;
03364 if (Command_List[i].ch == '\0') {
03365 Error_Cleanup();
03366 return;
03367 }
03368 (*(Command_List[i].fp))();
03369 }
03370
03371
03372
03373
03374
03375
03376
03377 static void WB_help()
03378 {
03379 fprintf(stdout, "The following commands are available:\n");
03380 for (INT i = 0; Command_List[i].ch != '\0'; i++)
03381 for (INT j = 0; j < ASCII_CHAR_COUNT; j++)
03382 if (WB_keymap[j] == Command_List[i].ch)
03383 fprintf(stdout, " %c: %s\n", j, Command_List[i].message);
03384 fprintf(stdout, " Q: Exit the debugger\n");
03385 fprintf(stdout, " q: Exit the debugger\n");
03386 }
03387
03388
03389
03390
03391
03392
03393
03394
03395
03396
03397 static void WBT_SNL_DEP_INFO()
03398 {
03399 SNL_DEP_INFO* this_address = (SNL_DEP_INFO*) cnode;
03400 this_address->Print(stdout);
03401 }
03402
03403
03404
03405
03406
03407
03408 static void WBT_SNL_DEP_MATRIX()
03409 {
03410 SNL_DEP_MATRIX* this_address = (SNL_DEP_MATRIX*) cnode;
03411 this_address->Print(stdout);
03412 }
03413
03414
03415
03416
03417
03418
03419 static void WBT_SNL_NEST_INFO()
03420 {
03421 SNL_NEST_INFO* this_address = (SNL_NEST_INFO*) cnode;
03422 this_address->Print(stdout);
03423 }
03424
03425
03426
03427
03428
03429
03430 static void WBT_DOLOOP_STACK()
03431 {
03432 DOLOOP_STACK* this_address = (DOLOOP_STACK*) cnode;
03433 if (WB_sanity_check_level == WBC_DISABLE) {
03434 Error_Cleanup();
03435 return;
03436 }
03437 fprintf(stdout, "Stack has %d elements\n", this_address->Elements());
03438 INT i;
03439 for (i = 0; i < this_address->Elements(); i++)
03440 if (WN_MAP_Get(LNO_Info_Map, this_address->Bottom_nth(i)) == NULL)
03441 break;
03442 if (i < this_address->Elements()) {
03443 fprintf(stdout, "Stack has unmarked do loop.\n");
03444 Error_Cleanup();
03445 return;
03446 }
03447 for (i = 0; i < this_address->Elements(); i++) {
03448 DO_LOOP_INFO* dli = Get_Do_Loop_Info(this_address->Bottom_nth(i));
03449 fprintf(stdout, "[%d] 0x%p %d\n", i, this_address->Bottom_nth(i),
03450 dli->Depth);
03451 }
03452 }
03453
03454
03455
03456
03457
03458
03459 static void WBT_ARRAY_REF_STAR()
03460 {
03461 ARRAY_REF* this_address = (ARRAY_REF*) cnode;
03462 this_address->Print(stdout);
03463 }
03464
03465
03466
03467
03468
03469
03470 static void WBT_ARRAY_REF_LIST()
03471 {
03472 ARRAY_REF_LIST* this_address = (ARRAY_REF_LIST*) cnode;
03473 this_address->Print(stdout);
03474 }
03475
03476
03477
03478
03479
03480
03481 static void WBT_COMPUTE_FOOTPRINT_RVAL()
03482 {
03483 COMPUTE_FOOTPRINT_RVAL* this_address = (COMPUTE_FOOTPRINT_RVAL*) cnode;
03484 this_address->Print(stdout);
03485 }
03486
03487
03488
03489
03490
03491
03492 static void WBT_MHD_LEVEL()
03493 {
03494 MHD_LEVEL* this_address = (MHD_LEVEL*) cnode;
03495 this_address->Print(stdout);
03496 fprintf(stdout, "\n");
03497 }
03498
03499
03500
03501
03502
03503
03504 static void WBT_MHD()
03505 {
03506 MHD* this_address = (MHD*) cnode;
03507 this_address->Print(stdout);
03508 fprintf(stdout, "\n");
03509 }
03510
03511
03512
03513
03514
03515
03516 static void WBT_FORMULA()
03517 {
03518 FORMULA* this_address = (FORMULA*) cnode;
03519 this_address->Print(stdout);
03520 fprintf(stdout, "\n");
03521 }
03522
03523 static void WBT_FORMULA_EVALUATE()
03524 {
03525 INT count = -1;
03526 INT variable_type = -1;
03527 double vars_double[MAX_FORMULA_VARS];
03528 mINT32 vars_int32[MAX_FORMULA_VARS];
03529 mINT64 vars_int64[MAX_FORMULA_VARS];
03530
03531 FORMULA* this_address = (FORMULA*) cnode;
03532 fprintf(stdout,
03533 "Available variable types: [0] double [1] INT32 [2] INT64\n");
03534 fprintf(stdout, "Select a variable type by number: ");
03535 Load_Integer(&variable_type);
03536 fprintf(stdout, "Enter the number of values: ");
03537 Load_Integer(&count);
03538 fprintf(stdout, "Enter the values in order: \n");
03539 for (INT i = 0; i < count; i++) {
03540 fprintf(stdout, "[%d] ", i);
03541 switch (variable_type) {
03542 case 0:
03543 Load_Double(&vars_double[i]);
03544 this_address->Eval(count, vars_double);
03545 fprintf(stdout, "Value is %g\n", vars_double[i]);
03546 break;
03547 case 1:
03548 Load_mINT32(&vars_int32[i]);
03549 this_address->Eval(count, vars_int32);
03550 fprintf(stdout, "Value is %d\n", vars_int32[i]);
03551 break;
03552 case 2:
03553 Load_mINT64(&vars_int64[i]);
03554 this_address->Eval(count, vars_int64);
03555 fprintf(stdout, "Value is %lld\n", vars_int64[i]);
03556 break;
03557 }
03558 }
03559 }
03560
03561
03562
03563
03564
03565
03566 static void WBT_PAR_STAT()
03567 {
03568 PAR_STAT* this_address = (PAR_STAT*) cnode;
03569 this_address->Print(stdout, 0);
03570 fprintf(stdout, "\n");
03571 }
03572
03573
03574
03575
03576
03577
03578 static void WBT_MAT_INT()
03579 {
03580 MAT<INT>* this_address = (MAT<INT>*) cnode;
03581 this_address->Print(stdout);
03582 fprintf(stdout, "\n");
03583 }
03584
03585
03586
03587
03588
03589
03590 static void WBT_MAT_FRAC()
03591 {
03592 MAT<FRAC>* this_address = (MAT<FRAC>*) cnode;
03593 this_address->Print(stdout);
03594 fprintf(stdout, "\n");
03595 }
03596
03597
03598
03599
03600
03601
03602 static void WBT_LU_MAT_INT()
03603 {
03604 LU_MAT<INT>* this_address = (LU_MAT<INT>*) cnode;
03605 this_address->Print(stdout);
03606 fprintf(stdout, "\n");
03607 }
03608
03609
03610
03611
03612
03613
03614 static void WBT_LU_MAT_FRAC()
03615 {
03616 LU_MAT<FRAC>* this_address = (LU_MAT<FRAC>*) cnode;
03617 this_address->Print(stdout);
03618 fprintf(stdout, "\n");
03619 }
03620
03621
03622
03623
03624
03625
03626
03627
03628
03629
03630 static BOOL WBTR_Pre_Loop_Peeling()
03631 {
03632 WN* wn_loop = NULL;
03633 UINT32 iter_count = 0;
03634 BOOL unrolled = TRUE;
03635 BOOL preserve_loop_index = TRUE;
03636 fprintf(stdout, "Enter a loop address: ");
03637 if (!Load_Loop(&wn_loop))
03638 return FALSE;
03639 fprintf(stdout, "Enter iteration count: ");
03640 Load_UINT32(&iter_count);
03641 fprintf(stdout, "Do you want the peeled section unrolled [Y]? ");
03642 Load_Boolean(&unrolled, TRUE, TRUE);
03643 fprintf(stdout, "Do you want to preserve the loop index [Y]? ");
03644 Load_Boolean(&preserve_loop_index, TRUE, TRUE);
03645 fprintf(stdout, "Peeling %d iterations from the front of loop 0x%p\n",
03646 iter_count, wn_loop);
03647 Pre_loop_peeling(wn_loop, iter_count, unrolled, preserve_loop_index);
03648 return TRUE;
03649 }
03650
03651
03652
03653
03654
03655
03656 static BOOL WBTR_Post_Loop_Peeling()
03657 {
03658 WN* wn_loop = NULL;
03659 UINT32 iter_count = 0;
03660 BOOL unrolled = TRUE;
03661 BOOL preserve_loop_index = TRUE;
03662 fprintf(stdout, "Enter a loop address: ");
03663 if (!Load_Loop(&wn_loop))
03664 return FALSE;
03665 fprintf(stdout, "Enter iteration count: ");
03666 Load_UINT32(&iter_count);
03667 fprintf(stdout, "Do you want the peeled section unrolled [Y]? ");
03668 Load_Boolean(&unrolled, TRUE, TRUE);
03669 fprintf(stdout, "Do you want to preserve the loop index [Y]? ");
03670 Load_Boolean(&preserve_loop_index, TRUE, TRUE);
03671 fprintf(stdout, "Peeling %d iterations from the back of loop 0x%p\n",
03672 iter_count, wn_loop);
03673 Post_loop_peeling(wn_loop, iter_count, unrolled, preserve_loop_index);
03674 return TRUE;
03675 }
03676
03677
03678
03679
03680
03681
03682 static BOOL WBTR_Loop_Reversal()
03683 {
03684 WN* wn_loop = NULL;
03685 BOOL legality_check = TRUE;
03686 fprintf(stdout, "Enter a loop address: ");
03687 if (!Load_Loop(&wn_loop))
03688 return FALSE;
03689 fprintf(stdout, "Check for legality [Y]? ");
03690 Load_Boolean(&legality_check, TRUE, TRUE);
03691 if (legality_check) {
03692 if (!RV_Is_Legal(wn_loop)) {
03693 fprintf(stdout, "Reversal of loop 0x%p is NOT legal.\n", wn_loop);
03694 Error_Cleanup();
03695 return FALSE;
03696 }
03697 fprintf(stdout, "Reversal of loop 0x%p is legal.\n", wn_loop);
03698 }
03699 fprintf(stdout, "Reversing loop 0x%p\n", wn_loop);
03700 RV_Reverse_Loop(wn_loop);
03701 return TRUE;
03702 }
03703
03704 #define MAX_PERMUTE_LOOPS 20
03705
03706
03707
03708
03709
03710
03711
03712
03713
03714
03715 static BOOL Load_SNL_And_Permutation(WN** wn_outer_addr,
03716 WN** wn_inner_addr,
03717 INT permutation[])
03718 {
03719 WN* wn_outer = NULL;
03720 WN* wn_inner = NULL;
03721 BOOL legality_check = TRUE;
03722 fprintf(stdout, "Enter the outermost loop's address: ");
03723 if (!Load_Loop(&wn_outer))
03724 return FALSE;
03725 fprintf(stdout, "Enter the innermost loop's address: ");
03726 if (!Load_Loop(&wn_inner))
03727 return FALSE;
03728 INT permutation_count = 0;
03729 WN* wn = 0;
03730 for (wn = wn_inner; wn != NULL; wn = LWN_Get_Parent(wn)) {
03731 if (WN_opcode(wn) == OPC_DO_LOOP)
03732 permutation_count++;
03733 if (wn == wn_outer)
03734 break;
03735 }
03736 if (wn == NULL) {
03737 fprintf(stdout, "Inner loop not nested in outer loop.\n");
03738 Error_Cleanup();
03739 return FALSE;
03740 }
03741 if (permutation_count < 2) {
03742 fprintf(stdout, "Must have at least two loops in permutation.\n");
03743 Error_Cleanup();
03744 return FALSE;
03745 }
03746 if (permutation_count > MAX_PERMUTE_LOOPS) {
03747 fprintf(stdout, "Too many loops in this permutation.\n");
03748 Error_Cleanup();
03749 return FALSE;
03750 }
03751 for (INT i = 0; i < permutation_count; i++) {
03752 fprintf(stdout, "Enter Permutation Element (%d): ", i);
03753 Load_Integer(&permutation[i]);
03754 }
03755 if (!Is_Permutation_Vector(permutation, permutation_count)) {
03756 fprintf(stdout, "Permutation specified is not a possible permutation.\n");
03757 Error_Cleanup();
03758 return FALSE;
03759 }
03760 *wn_outer_addr = wn_outer;
03761 *wn_inner_addr = wn_inner;
03762 return TRUE;
03763 }
03764
03765
03766
03767
03768
03769
03770 static BOOL WBTR_Loop_Permutation()
03771 {
03772 WN* wn_outer = NULL;
03773 WN* wn_inner = NULL;
03774 BOOL legality_check = TRUE;
03775 INT permutation[MAX_PERMUTE_LOOPS];
03776 if (!Load_SNL_And_Permutation(&wn_outer, &wn_inner, permutation))
03777 return FALSE;
03778 INT nloops = Do_Loop_Depth(wn_inner) - Do_Loop_Depth(wn_outer) + 1;
03779 fprintf(stdout, "Check for legality [Y]? ");
03780 Load_Boolean(&legality_check, TRUE, TRUE);
03781 if (legality_check) {
03782 WN* wn_safe_outer = Minimal_Kernel(wn_outer, nloops);
03783 if (wn_outer != wn_safe_outer) {
03784 fprintf(stdout, "Safest outermost loop is 0x%p.\n", wn_safe_outer);
03785 Error_Cleanup();
03786 return FALSE;
03787 }
03788 if (SNL_Permutation_Needs_Distribution(wn_outer, permutation, nloops)) {
03789 fprintf(stdout, "This permutation is illegal due to sandwiched code.\n");
03790 Error_Cleanup();
03791 return FALSE;
03792 }
03793 SNL_DEP_MATRIX** sdm_inv = Inv_Dep_Info(wn_outer, nloops, FALSE, FALSE);
03794 if (!SNL_Legal_Perm_Deps(sdm_inv[nloops - 1], permutation, nloops)) {
03795 fprintf(stdout, "This permutation of loops has illegal dependences.\n");
03796 Error_Cleanup();
03797 return FALSE;
03798 }
03799 }
03800 BOOL is_general = General_Permutation(wn_outer, permutation, nloops);
03801 BOOL is_invariant = Invariant_Permutation(wn_outer, permutation, nloops);
03802 if (is_invariant) {
03803 fprintf(stdout, "This permutation of loops is legal and invariant.\n");
03804 SNL_INV_Permute_Loops(wn_outer, permutation, nloops, TRUE);
03805 } else if (is_general) {
03806 fprintf(stdout, "This permutation of loops is legal and general.\n");
03807 SNL_GEN_Permute_Loops(wn_outer, permutation, nloops, TRUE);
03808 } else {
03809 fprintf(stdout, "This permutation of loops is neither general ");
03810 fprintf(stdout, "nor invariant.\n");
03811 Error_Cleanup();
03812 return FALSE;
03813 }
03814 return TRUE;
03815 }
03816
03817
03818
03819
03820
03821
03822 static BOOL WBTR_Scalar_Expansion()
03823 {
03824 WN* wn_outer = NULL;
03825 WN* wn_inner = NULL;
03826 BOOL legality_check = TRUE;
03827 INT permutation[MAX_PERMUTE_LOOPS];
03828 if (!Load_SNL_And_Permutation(&wn_outer, &wn_inner, permutation))
03829 return FALSE;
03830 INT nloops = Do_Loop_Depth(wn_inner) - Do_Loop_Depth(wn_outer) + 1;
03831 SX_INFO sx_info(&LNO_default_pool);
03832 sx_info.Make_Sx_Info(wn_outer, nloops);
03833 fprintf(stdout, "Check for legality [Y]? ");
03834 Load_Boolean(&legality_check, TRUE, TRUE);
03835 if (legality_check) {
03836 WN* wn_safe_outer = Minimal_Kernel(wn_outer, nloops);
03837 if (wn_outer != wn_safe_outer) {
03838 fprintf(stdout, "Safest outermost loop is 0x%p.\n", wn_safe_outer);
03839 Error_Cleanup();
03840 return FALSE;
03841 }
03842 const SX_PNODE* p = NULL;
03843 INT ftd = sx_info.First_Transformable_Depth(&p);
03844 INT i;
03845 for (i = 0; i < nloops; i++)
03846 if (permutation[i] != i)
03847 break;
03848 if (ftd > Do_Loop_Depth(wn_outer) + i) {
03849 fprintf(stdout,
03850 "Scalar expansion for this permutation of loops is NOT legal.\n");
03851 Error_Cleanup();
03852 return FALSE;
03853 }
03854 fprintf(stdout,
03855 "Scalar expansion for this permutation of loops is legal.\n");
03856 }
03857 SX_PLIST* plist = &(sx_info.Plist);
03858 BOOL invariant = Invariant_Permutation(wn_outer, permutation, nloops);
03859 if (invariant)
03860 SNL_INV_Scalar_Expand(wn_outer, permutation, nloops, plist);
03861 else
03862 SNL_GEN_Scalar_Expand(wn_outer, permutation, nloops, plist);
03863 return TRUE;
03864 }
03865
03866
03867
03868
03869
03870
03871 static BOOL WBTR_Distribution()
03872 {
03873 WN* wn_outer = NULL;
03874 WN* wn_inner = NULL;
03875 BOOL legality_check = TRUE;
03876 INT permutation[MAX_PERMUTE_LOOPS];
03877 if (!Load_SNL_And_Permutation(&wn_outer, &wn_inner, permutation))
03878 return FALSE;
03879 INT nloops = Do_Loop_Depth(wn_inner) - Do_Loop_Depth(wn_outer) + 1;
03880 fprintf(stdout, "Check for legality [Y]? ");
03881 Load_Boolean(&legality_check, TRUE, TRUE);
03882 if (legality_check) {
03883 WN* wn_safe_outer = Minimal_Kernel(wn_outer, nloops);
03884 if (wn_outer != wn_safe_outer) {
03885 fprintf(stdout, "Safest outermost loop is 0x%p.\n", wn_safe_outer);
03886 Error_Cleanup();
03887 return FALSE;
03888 }
03889 if (!SNL_Permutation_Is_Distributable(wn_outer, permutation, nloops)) {
03890 fprintf(stdout, "Distribution for this permutation is not legal.\n");
03891 Error_Cleanup();
03892 return FALSE;
03893 }
03894 fprintf(stdout, "Distribution for this permutation of loops is legal.\n");
03895 }
03896 SNL_Distribute_For_Permutation(wn_outer, wn_inner, permutation, nloops);
03897 return TRUE;
03898 }
03899
03900
03901
03902
03903
03904
03905
03906 static BOOL WBTR_SNL_INV_Limited_SE_And_Dist()
03907 {
03908 WN* wn_outer = NULL;
03909 WN* wn_inner = NULL;
03910 BOOL legality_check = TRUE;
03911 INT permutation[MAX_PERMUTE_LOOPS];
03912 if (!Load_SNL_And_Permutation(&wn_outer, &wn_inner, permutation))
03913 return FALSE;
03914 SX_INFO sx_info(&LNO_default_pool);
03915 INT nloops = Do_Loop_Depth(wn_inner) - Do_Loop_Depth(wn_outer) + 1;
03916 sx_info.Make_Sx_Info(wn_outer, nloops);
03917 fprintf(stdout, "Check for legality [Y]? ");
03918 Load_Boolean(&legality_check, TRUE, TRUE);
03919 if (legality_check) {
03920 WN* wn_safe_outer = Minimal_Kernel(wn_outer, nloops);
03921 if (wn_outer != wn_safe_outer) {
03922 fprintf(stdout, "Safest outermost loop is 0x%p.\n", wn_safe_outer);
03923 Error_Cleanup();
03924 return FALSE;
03925 }
03926 const SX_PNODE* p = NULL;
03927 INT ftd = sx_info.First_Transformable_Depth(&p);
03928 INT i;
03929 for (i = 0; i < nloops; i++)
03930 if (permutation[i] != i)
03931 break;
03932 if (ftd < Do_Loop_Depth(wn_outer) + i) {
03933 fprintf(stdout,
03934 "Scalar expansion for this permutation of loops is NOT legal.\n");
03935 Error_Cleanup();
03936 return FALSE;
03937 }
03938 fprintf(stdout, "Scalar expansion and distribution ");
03939 fprintf(stdout, "for this permutation of loops is legal.\n");
03940 }
03941 SX_PLIST* plist = &(sx_info.Plist);
03942 SNL_TILE_INFO* ti_se = NULL;
03943 SE_New_Tile_Infos(wn_outer, plist, permutation, nloops, &LNO_local_pool,
03944 &ti_se, FALSE);
03945 SNL_INV_Limited_SE_And_Dist(wn_outer, ti_se, permutation, nloops, plist,
03946 FALSE);
03947 return TRUE;
03948 }
03949
03950
03951
03952
03953
03954
03955
03956
03957
03958
03959 struct WB_STRING_REASON {
03960 const char *type;
03961 const char *reason_string;
03962 SNL_INV_CACHE_BLOCK_REASON reason;
03963 };
03964
03965 static WB_STRING_REASON Tiling_Prefix_List[] =
03966 {
03967 "$tile", "SNL_INV_TILE_ONLY", SNL_INV_TILE_ONLY,
03968 "$seonly", "SNL_INV_SE_ONLY", SNL_INV_SE_ONLY,
03969 "$setile", "SNL_INV_TILE_SE", SNL_INV_TILE_SE,
03970 "$dsmtile", "SNL_INV_LEGO_TILE", SNL_INV_LEGO_TILE,
03971 "$datile", "SNL_INV_MP_TILE", SNL_INV_MP_TILE,
03972 "", "SNL_INV_UNDEFINED", SNL_INV_UNDEFINED
03973 };
03974
03975
03976
03977
03978
03979
03980 static BOOL WBTR_Loop_Tiling()
03981 {
03982 BOOL legality_check = TRUE;
03983 WN* wn_loop = NULL;
03984 INT tile_size = 0;
03985 const char* prefix = NULL;
03986 INT transform_number = -1;
03987 SYMBOL* sym_pid = NULL;
03988 SNL_INV_CACHE_BLOCK_REASON reason = SNL_INV_UNDEFINED;
03989 ARRAY_DIRECTED_GRAPH16 *dg = Array_Dependence_Graph;
03990 DU_MANAGER* du = WB_du_mgr;
03991 REDUCTION_MANAGER* rm = red_manager;
03992 fprintf(stdout, "Enter a loop address: ");
03993 if (!Load_Loop(&wn_loop))
03994 return FALSE;
03995 fprintf(stdout, "Enter a tile size: ");
03996 Load_Integer(&tile_size);
03997 fprintf(stdout, "Select an reason for tiling by number:\n");
03998 INT i;
03999 for (i = 0; Tiling_Prefix_List[i].type[0] != '\0'; i++)
04000 fprintf(stdout, " (%d) %s\n", i, Tiling_Prefix_List[i].reason_string);
04001 INT last_transform_number = i - 1;
04002 fprintf(stdout, "Select a transformation by number: ");
04003 Load_Integer(&transform_number);
04004 if (transform_number < 0 || transform_number > last_transform_number) {
04005 fprintf(stdout, "Incorrect number selected.\n");
04006 Error_Cleanup();
04007 return FALSE;
04008 }
04009 fprintf(stdout, "Check for legality [Y]? ");
04010 Load_Boolean(&legality_check, TRUE, TRUE);
04011 if (legality_check) {
04012 WN* wn_safe_loop = Minimal_Kernel(wn_loop, 1);
04013 if (wn_loop != wn_safe_loop) {
04014 fprintf(stdout, "Loop 0x%p was not safe for tiling\n", wn_loop);
04015 Error_Cleanup();
04016 return FALSE;
04017 }
04018 if (Step_Size(wn_loop) != 1) {
04019 fprintf(stdout, "Loop 0x%p does not have unity step\n", wn_loop);
04020 Error_Cleanup();
04021 return FALSE;
04022 }
04023 }
04024 prefix = Tiling_Prefix_List[transform_number].type;
04025 reason = Tiling_Prefix_List[transform_number].reason;
04026 SYMBOL oldsym(WN_index(wn_loop));
04027 INT required_length = strlen(prefix) + strlen(oldsym.Name()) + 1;
04028 char* Str_Buf = CXX_NEW_ARRAY(char, required_length, &LNO_local_pool);
04029 sprintf(Str_Buf, "%s%s", prefix, oldsym.Name());
04030 sym_pid = CXX_NEW(SYMBOL(Create_Preg_Symbol(Str_Buf, Do_Wtype(wn_loop))),
04031 &LNO_default_pool);
04032 Tile_Loop(wn_loop, tile_size, 0, reason, sym_pid, &LNO_default_pool);
04033 return TRUE;
04034 }
04035
04036
04037
04038
04039
04040
04041
04042
04043
04044
04045
04046
04047 static char get_command()
04048 {
04049 INT i = buffer_start;
04050 while (buffer[i] == ' ' || buffer[i] == '\t' || buffer[i] == ';') i++;
04051 buffer_start = i + 1;
04052 return buffer[i];
04053 }
04054
04055
04056
04057
04058
04059
04060 static void Initialize_Language() {
04061 switch (PU_src_lang(Get_Current_PU())) {
04062 case PU_C_LANG:
04063 case PU_CXX_LANG:
04064 WB_language = SRC_C;
04065 fprintf(stdout, "WHIRL-TO-SOURCE language is C. ");
04066 break;
04067 case PU_F90_LANG:
04068 case PU_F77_LANG:
04069 WB_language = SRC_FORTRAN;
04070 fprintf(stdout, "WHIRL-TO-SOURCE language is FORTRAN. ");
04071 break;
04072 default:
04073 WB_language = SRC_NONE;
04074 fprintf(stdout,
04075 "Can't do WHIRL-TO-SOURCE tranformations in this language. ");
04076 break;
04077 }
04078 }
04079
04080
04081
04082
04083
04084
04085
04086 static BOOL Unmappable_Character(char ch) {
04087 switch (ch) {
04088 case ' ':
04089 case '\t':
04090 case '\n':
04091 case 'Q':
04092 case 'q':
04093 case 'H':
04094 case 'h':
04095 return TRUE;
04096 default:
04097 return FALSE;
04098 }
04099 }
04100
04101
04102
04103
04104
04105
04106
04107 static void Initialize_Keymap() {
04108 char file_name[BUFFER_MAX];
04109 strcpy(file_name, getenv("HOME"));
04110 strcat(file_name, "/.wb_keymap");
04111 FILE* fp_keymap = fopen(file_name, "r");
04112 if (fp_keymap == NULL)
04113 return;
04114 BOOL print_log = TRUE;
04115 char key_buffer[BUFFER_MAX];
04116 INT line_number = 0;
04117 while (fgets(key_buffer, BUFFER_MAX-1, fp_keymap) != NULL) {
04118 line_number++;
04119 INT key_buffer_start = 0;
04120 scan_blanks_and_tabs(key_buffer, &key_buffer_start);
04121 if (strncasecmp(&key_buffer[key_buffer_start], "SILENT",
04122 strlen("SILENT")) == 0) {
04123 print_log = FALSE;
04124 } else if (strncasecmp(&key_buffer[key_buffer_start], "VERBOSE",
04125 strlen("VERBOSE")) == 0) {
04126 print_log = TRUE;
04127 } else if (strncasecmp(&key_buffer[key_buffer_start], "TRANSLATE",
04128 strlen("TRANSLATE")) == 0) {
04129 key_buffer_start += strlen("TRANSLATE");
04130 scan_blanks_and_tabs(key_buffer, &key_buffer_start);
04131 char old_char = key_buffer[key_buffer_start++];
04132 if (Unmappable_Character(old_char)) {
04133 fprintf(stdout,
04134 ".wb_keymap: Error on line %d: Cannot map %c\n",
04135 line_number, old_char);
04136 continue;
04137 }
04138 scan_blanks_and_tabs(key_buffer, &key_buffer_start);
04139 char new_char = key_buffer[key_buffer_start++];
04140 if (Unmappable_Character(new_char)) {
04141 fprintf(stdout,
04142 ".wb_keymap: Error on line %d: Cannot map %c\n",
04143 line_number, new_char);
04144 continue;
04145 }
04146 if (print_log)
04147 fprintf(stdout, ".wb_keymap: Translating '%c' to '%c'\n",
04148 old_char, new_char);
04149 WB_keymap[new_char] = old_char;
04150 } else {
04151 fprintf(stdout, ".wb_keymap: Error on line %d: Unrecognized command\n",
04152 line_number);
04153 }
04154 }
04155 fclose(fp_keymap);
04156 }
04157
04158
04159
04160
04161
04162
04163
04164
04165
04166
04167
04168
04169 extern void s_lno_debug(const char init_buffer[])
04170 {
04171 char ch;
04172 VOID_FUNC_PTR fp;
04173 BOOL reload;
04174
04175 last_ch = '\0';
04176 if (WB_global_fd == NULL) {
04177 fprintf(stdout, "Whirl browser only valid in Loop Nest Optimizer.\n");
04178 Error_Cleanup();
04179 return;
04180 }
04181 Initialize_Keymap();
04182 Initialize_Language();
04183 fprintf(stdout, "DAVINCI is %s. ", WB_davinci_mode ? "ON" : "OFF");
04184 fprintf(stdout, "\n");
04185 cnode = WB_global_fd;
04186 fprintf(stdout, "Root node is: ");
04187 print_this_node();
04188 prompt();
04189 buffer_start = 0;
04190 if (init_buffer[0] == '\0') {
04191 reload = TRUE;
04192 init_mode = FALSE;
04193 } else {
04194 reload = FALSE;
04195 INT i;
04196 for (i = 0; init_buffer[i] != '\0'; i++) {
04197 buffer[i] = init_buffer[i];
04198 fprintf(stdout, "%c", init_buffer[i]);
04199 }
04200 buffer[i] = '\n';
04201 fprintf(stdout, "\n");
04202 init_mode = TRUE;
04203 }
04204 while (TRUE) {
04205 if (reload) {
04206 load_buffer();
04207 reload = FALSE;
04208 }
04209 if (ch != '.' && ch != '\n')
04210 last_ch = ch;
04211 ch = get_command();
04212 if (ch == '\n') {
04213 prompt();
04214 reload = TRUE;
04215 init_mode = FALSE;
04216 continue;
04217 }
04218 fp = this_fp(WB_keymap[ch]);
04219 if (fp != NULL) {
04220 (*fp)();
04221 } else if (ch == 'Q' || ch == 'q') {
04222 cnode = NULL;
04223 return;
04224 } else {
04225 fprintf(stdout, "Bad character: %c\n", ch);
04226 }
04227 }
04228 }
04229