00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068 #define __STDC_LIMIT_MACROS
00069 #include <stdint.h>
00070 #include <stdio.h>
00071 #include <unistd.h>
00072 #if defined(BUILD_OS_DARWIN)
00073 #include <darwin_elf.h>
00074 #else
00075 #include <elf.h>
00076 #endif
00077 #include <sys/types.h>
00078 #include <signal.h>
00079 #include <alloca.h>
00080 #include <cmplrs/rcodes.h>
00081 #include <float.h>
00082 #include <ext/hash_set>
00083 #include <queue>
00084
00085 #include "defs.h"
00086 #include "erglob.h"
00087 #include "cxx_memory.h"
00088 #include "glob.h"
00089 #include "wn.h"
00090 #include "symtab.h"
00091 #include "pu_info.h"
00092 #include "ipc_file.h"
00093 #include "ipc_compile.h"
00094 #include "ipc_bread.h"
00095 #include "ipc_bwrite.h"
00096 #include "ipo_defs.h"
00097 #include <cmplrs/host.h>
00098 #include "ld_ipa_option.h"
00099 #include "ipa_option.h"
00100 #include "ipo_tlog_utils.h"
00101 #include "ipa_main.h"
00102 #include "ipa_cg.h"
00103 #include "ipo_const.h"
00104 #include "ipc_symtab_merge.h"
00105 #include "ipo_main.h"
00106 #include "ipc_weak.h"
00107 #include "ipo_pad.h"
00108 #include "ipo_split.h"
00109 #include "ipo_dce.h"
00110 #include "ipo_inline.h"
00111 #include "ipo_alias.h"
00112 #include "ipa_lno_write.h"
00113 #include "cgb.h"
00114 #include "cgb_ipa.h"
00115 #include "ipc_pic.h"
00116 #include "ipo_alias_class.h"
00117 #include "ir_bread.h"
00118 #include "ir_bwrite.h"
00119 #include "be_symtab.h"
00120
00121 #include "ipc_option.h"
00122
00123 #ifdef KEY
00124 #include "ipa_builtins.h"
00125 #include "ipo_parent.h"
00126 #endif
00127
00128 #ifndef KEY
00129 #include "inline_script_parser.h"
00130 #else
00131 extern void IPO_WN_Update_For_Struct_Opt (IPA_NODE *);
00132 #endif
00133 #include "ipa_reorder.h"
00134
00135 extern "C" void add_to_tmp_file_list (char*);
00136 #pragma weak add_to_tmp_file_list
00137
00138 extern MEM_POOL Ipo_mem_pool;
00139 extern WN_MAP Parent_Map;
00140
00141 extern char * preopt_path;
00142 extern int preopt_opened;
00143 static BOOL have_open_input_file = FALSE;
00144 static FILE *fin;
00145 struct reg_feedback {
00146 char _func_name[120];
00147 INT32 _stacked_callee_used;
00148 INT32 _stacked_caller_used;
00149 float _cost[96];
00150 reg_feedback() : _stacked_callee_used(0),
00151 _stacked_caller_used(0)
00152 {
00153 for (INT32 i = 0; i < 96; i++) {
00154 _cost[i] = 0;
00155 }
00156 }
00157 };
00158
00159 typedef reg_feedback* REG_FB_POINTER;
00160
00161 namespace {
00162 struct eqs {
00163 bool operator()(char* s1, char* s2) const
00164 { return strcmp(s1, s2) == 0; }
00165 };
00166 typedef __gnu_cxx::hash_map<char*, REG_FB_POINTER, __gnu_cxx::hash<char*>, eqs> REG_FB_MAP;
00167 };
00168
00169 static REG_FB_MAP REG_FB_INFO_TABLE;
00170
00171 struct reg_budget {
00172 INT32 _budget;
00173 IPA_NODE *_node;
00174 float _self_recursive_freq;
00175 reg_budget() : _budget(0),_node(NULL),
00176 _self_recursive_freq(0) {}
00177 };
00178
00179 typedef struct reg_budget* REG_BUDGET_POINTER;
00180 namespace {
00181 struct eq {
00182 bool operator()(char* s1, char* s2) const
00183 { return strcmp(s1, s2) == 0; }
00184 };
00185 typedef __gnu_cxx::hash_map<char*, REG_BUDGET_POINTER, __gnu_cxx::hash<char*>, eq> REG_BUDGET_MAP;
00186 };
00187
00188 static REG_BUDGET_MAP REG_BUDGET_TABLE;
00189
00190 struct reg_list {
00191 IPA_NODE *_node;
00192 float _spill_cost;
00193 struct reg_list *_next;
00194 struct reg_list *_prev;
00195 reg_list() : _node(NULL),_spill_cost(0),
00196 _next(NULL),_prev(NULL) {
00197 }
00198 };
00199
00200 INT IPO_Total_Inlined = 0;
00201 static float REC_OVERFLOW_COST = 20;
00202 static float OVERFLOW_COST = 20;
00203 BOOL one_got;
00204
00205 static MEM_POOL Recycle_mem_pool;
00206 MEM_POOL IPA_LNO_mem_pool;
00207 static IPA_LNO_WRITE_SUMMARY* IPA_LNO_Summary = NULL;
00208
00209 #ifdef KEY
00210
00211
00212
00213 struct inline_info {
00214 IPA_NODE *_node;
00215 IPA_EDGE *_edge;
00216 inline_info (IPA_NODE *n, IPA_EDGE *e) : _node(n), _edge(e) {}
00217 };
00218 vector<inline_info> inline_list;
00219 #endif
00220
00221
00222
00223
00224 typedef AUX_IPA_NODE<UINT32> NUM_CALLS_PROCESSED;
00225 static NUM_CALLS_PROCESSED* Num_In_Calls_Processed;
00226 static NUM_CALLS_PROCESSED* Num_Out_Calls_Processed;
00227
00228
00229
00230 static inline BOOL
00231 All_Calls_Processed (const IPA_NODE* node, const IPA_CALL_GRAPH* cg)
00232 {
00233
00234 return ((cg->Num_In_Edges (node) == (*Num_In_Calls_Processed)[node]) &&
00235 (cg->Num_Out_Edges (node) == (*Num_Out_Calls_Processed)[node]));
00236 }
00237
00238
00239 static void
00240 Init_Num_Calls_Processed (const IPA_CALL_GRAPH* cg, MEM_POOL* pool)
00241 {
00242 Num_In_Calls_Processed = CXX_NEW (NUM_CALLS_PROCESSED (cg, pool), pool);
00243 Num_Out_Calls_Processed = CXX_NEW (NUM_CALLS_PROCESSED (cg, pool), pool);
00244
00245
00246
00247
00248
00249 IPA_GRAPH* graph = cg->Graph ();
00250 NODE_ITER viter (graph, cg->Root ());
00251 for (NODE_INDEX child = viter.First_Succ ();
00252 child != -1;
00253 child = viter.Next_Succ ())
00254 ++(*Num_In_Calls_Processed)[graph->Node_User (child)];
00255
00256 }
00257
00258
00259 static BOOL
00260 PU_Deleted (const IPA_GRAPH* cg, NODE_INDEX idx, const IP_FILE_HDR* fhdr)
00261 {
00262 const IPA_NODE* node = cg->Node_User (idx);
00263
00264 if (node == NULL)
00265 return TRUE;
00266
00267 #ifdef KEY
00268
00269 if (node->Is_Builtin())
00270 return FALSE;
00271 #endif
00272
00273 const IP_PROC_INFO* proc_info = IP_FILE_HDR_proc_info (*fhdr);
00274
00275 return IP_PROC_INFO_state (proc_info[node->Proc_Info_Index ()]) ==
00276 IPA_DELETED;
00277 }
00278
00279 #ifdef KEY
00280 static BOOL
00281 PU_Written (const IPA_GRAPH* cg, const IPA_NODE* node, const IP_FILE_HDR* fhdr)
00282 {
00283 if (node == NULL)
00284 return TRUE;
00285
00286 const IP_PROC_INFO* proc_info = IP_FILE_HDR_proc_info (*fhdr);
00287
00288 return IP_PROC_INFO_state (proc_info[node->Proc_Info_Index ()]) ==
00289 IPA_WRITTEN;
00290 }
00291 #endif // KEY
00292
00293
00294
00295
00296
00297 typedef vector<IPA_NODE*> IPA_NODE_VECTOR;
00298
00299 static void
00300 Trans_Order_Walk (IPA_NODE_VECTOR& vect, mBOOL* visited, IPA_GRAPH* cg,
00301 NODE_INDEX root)
00302 {
00303 visited[root] = TRUE;
00304 NODE_ITER vitr (cg, root);
00305 NODE_INDEX child;
00306
00307 for (child = vitr.First_Succ ();
00308 child != -1;
00309 child = vitr.Next_Succ ())
00310 if (!visited[child])
00311 Trans_Order_Walk (vect, visited, cg, child);
00312
00313 IPA_NODE* node = cg->Node_User (root);
00314
00315 if (node == NULL)
00316 return;
00317
00318 #ifdef KEY
00319 if (node->Is_Builtin())
00320 return;
00321 #endif
00322
00323 if (node->Summary_Proc ()->Is_alt_entry ()) {
00324 IPA_SUCC_ITER succ_iter (node);
00325 for (succ_iter.First(); !succ_iter.Is_Empty(); succ_iter.Next()) {
00326 IPA_EDGE *edge = succ_iter.Current_Edge ();
00327 if (!edge->Is_Processed ()) {
00328 IPA_NODE* callee = IPA_Call_Graph->Callee (edge);
00329 ++(*Num_In_Calls_Processed)[callee];
00330 ++(*Num_Out_Calls_Processed)[node];
00331 edge->Set_Processed ();
00332 }
00333 }
00334 } else if (PU_uplevel (node->Get_PU ())) {
00335
00336
00337 const PU_Info* pu = node->PU_Info ();
00338 for (pu = PU_Info_child (pu); pu; pu = PU_Info_next (pu)) {
00339 const AUX_PU& aux_pu =
00340 Aux_Pu_Table [ST_pu (St_Table [PU_Info_proc_sym (pu)])];
00341 child = AUX_PU_node (aux_pu);
00342 if (!visited[child] &&
00343 !PU_Deleted (cg, child, AUX_PU_file_hdr (aux_pu)))
00344 Trans_Order_Walk (vect, visited, cg, child);
00345 }
00346 }
00347
00348 vect.push_back (node);
00349 }
00350
00351 #if defined(TARG_SL)
00352 typedef queue<NODE_INDEX> NODE_INDEX_QUEUE;
00353
00354
00355 static void
00356 Build_BFS_Order (IPA_NODE_VECTOR& vect, IPA_GRAPH* cg,
00357 NODE_INDEX root)
00358 {
00359 mBOOL *visited = (mBOOL *) alloca (GRAPH_vmax (cg) * sizeof(mBOOL));
00360 bzero (visited, GRAPH_vmax (cg) * sizeof(mBOOL));
00361 vect.reserve (GRAPH_vcnt (cg));
00362
00363 NODE_INDEX_QUEUE myqueue;
00364 myqueue.push(root);
00365
00366 while (!myqueue.empty()) {
00367
00368 NODE_INDEX cur = myqueue.front();
00369 myqueue.pop();
00370
00371 if (!visited[cur]) {
00372 visited[cur] = TRUE;
00373 NODE_ITER vitr (cg, cur);
00374 NODE_INDEX child;
00375 for (child = vitr.First_Succ (); child != -1;
00376 child = vitr.Next_Succ ())
00377 {
00378 if (!visited[child])
00379 myqueue.push(child);
00380 }
00381
00382 IPA_NODE* node = cg->Node_User (cur);
00383 if (node == NULL)
00384 continue;
00385 #ifdef KEY
00386 if (node->Is_Builtin())
00387 continue;
00388 #endif
00389
00390 vect.push_back(node);
00391 }
00392
00393 }
00394 }
00395 #endif // TARG_SL
00396
00397 static inline void
00398 Build_Transformation_Order (IPA_NODE_VECTOR& vect, IPA_GRAPH* cg,
00399 NODE_INDEX root)
00400 {
00401 mBOOL *visited = (mBOOL *) alloca (GRAPH_vmax (cg) * sizeof(mBOOL));
00402 bzero (visited, GRAPH_vmax (cg) * sizeof(mBOOL));
00403 vect.reserve (GRAPH_vcnt (cg));
00404 Trans_Order_Walk (vect, visited, cg, root);
00405
00406 }
00407
00408
00409
00410
00411 void
00412 Rename_Call_To_Cloned_PU (IPA_NODE *caller,
00413 IPA_NODE *callee,
00414 IPA_EDGE *e,
00415 IPA_CALL_GRAPH *cg)
00416 {
00417 IPA_NODE_CONTEXT context (caller);
00418
00419 cg->Map_Callsites (caller);
00420
00421 WN* call = e->Whirl_Node();
00422
00423 WN_st_idx (call) = ST_st_idx (callee->Func_ST());
00424
00425 }
00426
00427 #if defined(KEY) && !defined(_STANDALONE_INLINER) && !defined(_LIGHTWEIGHT_INLINER)
00428 static void Fixup_EHinfo_In_PU (IPA_NODE* node, WN * w = NULL)
00429 {
00430 if (w && WN_operator(w) == OPR_REGION && WN_region_is_EH (w) &&
00431 WN_block_empty (WN_region_pragmas (w)))
00432 {
00433 int sym_size;
00434 SUMMARY_SYMBOL * sym_array = IPA_get_symbol_file_array (node->File_Header(), sym_size);
00435 Is_True (sym_array != NULL, ("Missing SUMMARY_SYMBOL section"));
00436 INITV_IDX blk = INITO_val (WN_ereg_supp (w));
00437
00438
00439 if (INITV_flags (Initv_Table[blk]) != INITVFLAGS_UPDATED)
00440 {
00441 Set_INITV_flags (blk, INITVFLAGS_UPDATED);
00442 INITV_IDX types = INITV_next (INITV_blk (blk));
00443 for (; types; types = INITV_next (types))
00444 {
00445 if (INITV_kind (types) == INITVKIND_ZERO)
00446 continue;
00447 int index = TCON_uval (INITV_tc_val (types));
00448 if (index <= 0) continue;
00449 ST_IDX new_idx = sym_array[index].St_idx();
00450 INITV_IDX next = INITV_next (types);
00451 INITV_Set_VAL (Initv_Table[types], Enter_tcon (
00452 Host_To_Targ (MTYPE_U4, new_idx)), 1);
00453 Set_INITV_next (types, next);
00454 }
00455 }
00456 }
00457
00458 if (w == NULL)
00459 w = node->Whirl_Tree (FALSE);
00460
00461 if (!OPCODE_is_leaf (WN_opcode (w)))
00462 {
00463 if (WN_operator (w) == OPR_BLOCK)
00464 {
00465 WN * kid = WN_first (w);
00466 while (kid)
00467 {
00468 Fixup_EHinfo_In_PU (node, kid);
00469 kid = WN_next (kid);
00470 }
00471 }
00472 else
00473 {
00474 for (INT kidno=0; kidno<WN_kid_count(w); ++kidno)
00475 Fixup_EHinfo_In_PU (node, WN_kid(w, kidno));
00476 }
00477 }
00478 }
00479 #endif
00480
00481 static BOOL
00482 Inline_Call (IPA_NODE *caller, IPA_NODE *callee, IPA_EDGE *edge,
00483 IPA_CALL_GRAPH *cg)
00484 {
00485 Is_True (caller->Is_Processed () && callee->Is_Processed (),
00486 ("Node info not read before performing inlining"));
00487
00488 IPA_NODE_CONTEXT context (caller);
00489 cg->Map_Callsites (caller);
00490
00491 if (!Can_Inline_Call (caller, callee, edge))
00492 return FALSE;
00493
00494 #ifdef KEY
00495 Get_enclosing_region (caller, edge);
00496 #if !defined(_STANDALONE_INLINER) && !defined(_LIGHTWEIGHT_INLINER)
00497
00498
00499
00500 if (!caller->EHinfo_Updated())
00501 {
00502 PU p = caller->Get_PU();
00503 if ((PU_src_lang (p) & PU_CXX_LANG) && PU_has_region (p))
00504 Fixup_EHinfo_In_PU (caller);
00505 caller->Set_EHinfo_Updated();
00506 }
00507 if (!callee->EHinfo_Updated())
00508 {
00509 PU p = callee->Get_PU();
00510 if ((PU_src_lang (p) & PU_CXX_LANG) && PU_has_region (p))
00511 {
00512 IPA_NODE_CONTEXT temp_context (callee);
00513 Fixup_EHinfo_In_PU (callee);
00514 }
00515 callee->Set_EHinfo_Updated();
00516 }
00517 #endif // !_STANDALONE_INLINER && !_LIGHTWEIGHT_INLINER
00518 #endif // KEY
00519
00520 #if Is_True_On
00521 if ( Get_Trace ( TKIND_ALLOC, TP_IPA) ) {
00522 fprintf ( TFile, "\n%s%s\tMemory allocation information before inlining\n%s%s\n",
00523 DBar, DBar, DBar, DBar );
00524 MEM_Trace ();
00525 }
00526 #endif
00527
00528 IPO_INLINE ip_inline (caller, callee, edge);
00529 ip_inline.Process ();
00530
00531 #if Is_True_On
00532 if ( Get_Trace ( TKIND_ALLOC, TP_IPA) ) {
00533 fprintf ( TFile, "\n%s%s\tMemory allocation information after inlining\n%s%s\n",
00534 DBar, DBar, DBar, DBar );
00535 MEM_Trace ();
00536 }
00537 #endif
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548 if ( Trace_IPA || Trace_Perf ) {
00549 fprintf ( TFile, "%s inlined into ", DEMANGLE (callee->Name()) );
00550 fprintf ( TFile, "%s (edge# %d)", DEMANGLE (caller->Name()), edge->Edge_Index () );
00551 if ( IPA_Skip_Report ) {
00552 fprintf ( TFile, " (%d)\n", caller->Node_Index() );
00553 } else {
00554 fprintf ( TFile, "\n" );
00555 }
00556 }
00557 if ( INLINE_List_Actions ) {
00558 fprintf ( stderr, "%s inlined into ", DEMANGLE (callee->Name()) );
00559 fprintf ( stderr, "%s (edge# %d)\n", DEMANGLE (caller->Name()), edge->Edge_Index () );
00560 if ( IPA_Skip_Report ) {
00561 fprintf ( stderr, " (%d)\n", caller->Node_Index() );
00562 } else {
00563 fprintf ( stderr, "\n" );
00564 }
00565
00566
00567
00568 #ifdef Enable_ISP_Verify
00569 FILE *inline_action = fopen(inline_action_log, "a+");
00570 char *caller_key, *callee_key;
00571
00572
00573 WN* call_wn = edge->Whirl_Node();
00574 USRCPOS callsite_srcpos;
00575 USRCPOS_srcpos(callsite_srcpos) = WN_Get_Linenum (call_wn);
00576 char callsite_linestr[1024];
00577 sprintf(callsite_linestr, "%d", USRCPOS_linenum(callsite_srcpos));
00578
00579
00580 char *caller_file = (char *) alloca(strlen(caller->File_Header().file_name)+1);
00581 strcpy(caller_file, caller->File_Header().file_name);
00582 char *callee_file = (char *) alloca(strlen(callee->File_Header().file_name)+1);
00583 strcpy(callee_file, callee->File_Header().file_name);
00584 char *caller_func = (char *) alloca(strlen(DEMANGLE (caller->Name()))+1);
00585 strcpy(caller_func, DEMANGLE (caller->Name()));
00586 char *callee_func = (char *) alloca(strlen(DEMANGLE (callee->Name()))+1);
00587 strcpy(callee_func, DEMANGLE (callee->Name()));
00588
00589
00590 ISP_Fix_Filename(caller_file);
00591 ISP_Fix_Filename(callee_file);
00592 ISP_Fix_Filename(caller_func);
00593 ISP_Fix_Filename(callee_func);
00594
00595
00596 caller_key = (char *) alloca(strlen(caller_file)+strlen(caller_func)+2);
00597 strcpy(caller_key, "");
00598 strcat(caller_key, caller_file);
00599 strcat(caller_key, caller_func);
00600
00601
00602 callee_key = (char *) alloca(strlen(callsite_linestr)+strlen(callee_file)+strlen(callee_func)+3);
00603 strcpy(callee_key, "");
00604 strcat(callee_key, callsite_linestr);
00605 strcat(callee_key, callee_file);
00606 strcat(callee_key, callee_func);
00607
00608 fprintf(inline_action, "[%s] inlined into [%s]\n", callee_key, caller_key);
00609 fclose(inline_action);
00610 #endif
00611 }
00612
00613 return TRUE;
00614
00615 }
00616
00617 #ifdef KEY
00618 extern void IPO_Process_Icalls (IPA_NODE *);
00619 extern void IPA_update_ehinfo_in_pu (IPA_NODE *);
00620 #endif
00621
00622 static IPA_NODE *
00623 IPO_Process_node (IPA_NODE* node, IPA_CALL_GRAPH* cg)
00624 {
00625 if (Is_Skip_Equal(node->Name())) {
00626 if ( Trace_IPA || Trace_Perf )
00627 fprintf ( TFile, "%s is skipped \n", DEMANGLE (node->Name()) );
00628 return node;
00629 }
00630
00631 if (node->Summary_Proc()->Is_alt_entry ()) {
00632 return node;
00633 }
00634
00635 IP_READ_pu_infos (node->File_Header());
00636
00637 IPA_NODE_CONTEXT context (node);
00638
00639 #ifdef KEY
00640 if (PU_src_lang (node->Get_PU()) & PU_CXX_LANG)
00641 IPA_update_ehinfo_in_pu (node);
00642
00643 if (IPA_Enable_Icall_Opt && node->Has_Pending_Icalls()) {
00644 IPO_Process_Icalls (node);
00645 }
00646 #endif
00647
00648 if (IPA_Enable_Padding) {
00649 IPO_Pad_Whirl (node);
00650 }
00651
00652 if (IPA_Enable_Common_Const && node->Has_Propagated_Const()) {
00653 IPO_propagate_globals(node);
00654 }
00655
00656 #ifdef KEY
00657 if (IPA_Enable_Struct_Opt)
00658 IPO_WN_Update_For_Struct_Opt(node);
00659 #endif
00660
00661 if(IPA_Enable_Reorder && reorder_candidate.size)
00662 IPO_Modify_WN_for_field_reorder(node) ;
00663 else
00664 Compare_whirl_tree(node);
00665
00666 if (
00667 #if defined(TARG_SL)
00668 !ld_ipa_opt[LD_IPA_IPISR].flag &&
00669 #endif
00670 IPA_Enable_Cloning && node->Is_Clone_Candidate()) {
00671
00672 IPA_NODE *cloned_node = cg->Create_Clone(node);
00673 cloned_node->Set_Propagated_Const ();
00674
00675 if (Trace_IPA || Trace_Perf) {
00676 fprintf (TFile, "%s from file %s is cloned\n",
00677 DEMANGLE (node->Name()), node->Input_File_Name());
00678 }
00679
00680
00681 node->Write_PU();
00682
00683 node = cloned_node;
00684 }
00685
00686 if (IPA_Enable_Cprop && node->Has_Propagated_Const()) {
00687
00688 BOOL is_fortran = PU_f77_lang(node->Get_PU()) ||
00689 PU_f90_lang(node->Get_PU());
00690
00691 IPA_Propagate_Constants (node, (IPA_Enable_Cprop2 &&
00692 !is_fortran &&
00693 !node->Has_No_Aggr_Cprop()));
00694
00695 #if 0
00696 WN *pu_wn = node->Whirl_Tree();
00697 REGION_Initialize(pu_wn, FALSE);
00698
00699 Current_PU = WN_st(pu_wn);
00700
00701 MEM_POOL_Push(&MEM_local_pool);
00702
00703 Set_Error_Phase ("Global Optimizer");
00704 IPO_Load_Preopt();
00705 DU_MANAGER* du_mgr = Create_Du_Manager(MEM_pu_nz_pool_ptr);
00706 ALIAS_MANAGER* alias_mgr = Create_Alias_Manager(MEM_pu_nz_pool_ptr);
00707
00708 WN *opt_pu = Pre_Optimizer(PREOPT_IPA1_PHASE, pu_wn, du_mgr, alias_mgr);
00709 node->Set_Whirl_Tree(opt_pu);
00710
00711 Delete_Du_Manager(du_mgr,MEM_pu_nz_pool_ptr);
00712 Delete_Alias_Manager(alias_mgr,MEM_pu_nz_pool_ptr);
00713
00714 MEM_POOL_Pop(&MEM_local_pool);
00715 #endif
00716 }
00717
00718 return node;
00719 }
00720
00721
00722 static void
00723 IPO_Process_edge (IPA_NODE* caller, IPA_NODE* callee, IPA_EDGE* edge,
00724 IPA_CALL_GRAPH* cg)
00725 {
00726 if (caller->Summary_Proc()->Is_alt_entry ()) {
00727 return;
00728 }
00729
00730
00731
00732
00733
00734 BOOL action_taken = FALSE;
00735
00736 #ifdef TODO
00737 if (IPA_Enable_Array_Sections) {
00738 if (callee->Has_use_kill()) {
00739 Mark_use_kill_param(caller, callee, edge);
00740 }
00741 }
00742 #endif // TODO
00743
00744 if (IPA_Enable_Addressing && IPA_Enable_Simple_Alias &&
00745 IPA_Enable_Readonly_Ref) {
00746
00747
00748 if (edge->Has_Readonly_Param() || edge->Has_Pass_Not_Saved_Param())
00749 Mark_readonly_param (caller, edge, cg);
00750 }
00751
00752 if (edge->Has_Propagated_Const() && callee->Has_Propagated_Const()) {
00753 if (IPA_Enable_Cloning && callee->Is_Clone()) {
00754 Rename_Call_To_Cloned_PU (caller, callee, edge, cg);
00755 }
00756 if (IPA_Enable_Cprop2 && !callee->Has_No_Aggr_Cprop())
00757 Reset_param_list (caller, callee, edge, cg);
00758 }
00759
00760 if (IPA_Enable_DCE && edge->Is_Deletable ())
00761 action_taken = Delete_Call (caller, callee, edge, cg);
00762 else if (IPA_Enable_Inline && edge->Has_Inline_Attrib () &&
00763 !callee->Has_Noinline_Attrib()) {
00764 #if defined(KEY) && !defined(_STANDALONE_INLINER) && !defined(_LIGHTWEIGHT_INLINER)
00765 if (caller != callee) {
00766 #endif
00767 MEM_POOL_Popper ipo_pool (&Ipo_mem_pool);
00768 action_taken = Inline_Call (caller, callee, edge, cg);
00769 if (action_taken)
00770 IPO_Total_Inlined++;
00771 #if defined(KEY) && !defined(_STANDALONE_INLINER) && !defined(_LIGHTWEIGHT_INLINER)
00772 } else {
00773
00774
00775 inline_info inline_later (caller, edge);
00776 inline_list.push_back (inline_later);
00777 return;
00778 }
00779 #endif
00780 }
00781
00782 #if defined(KEY) && !defined(_STANDALONE_INLINER) && !defined(_LIGHTWEIGHT_INLINER)
00783 static INT pure_call_opt_count = 0;
00784 if (!action_taken &&
00785 IPA_Enable_Pure_Call_Opt &&
00786 !callee->Summary_Proc()->Has_side_effect())
00787 {
00788 IPA_NODE_CONTEXT context (caller);
00789
00790 if (!edge->Whirl_Node())
00791 cg->Map_Callsites (caller);
00792
00793 WN * ret_val, * ret_val_kid;
00794
00795 WN * call = edge->Whirl_Node();
00796 ret_val = WN_next(call);
00797
00798 if (ret_val)
00799 {
00800 ret_val_kid = WN_kid0 (ret_val);
00801 BOOL types_ok = WN_rtype (call) != MTYPE_M &&
00802 WN_desc (call) == MTYPE_V;
00803 BOOL transform = (ret_val_kid && WN_operator (ret_val) == OPR_STID &&
00804 WN_operator (ret_val_kid) == OPR_LDID &&
00805 WN_load_offset (ret_val_kid) == -1 &&
00806 types_ok);
00807 if (transform) pure_call_opt_count++;
00808 if (transform &&
00809 pure_call_opt_count > IPA_Pure_Call_skip_before)
00810 {
00811 WN * new_call = WN_Create (OPR_PURE_CALL_OP,
00812 WN_desc (ret_val),
00813 MTYPE_V,
00814 WN_kid_count (call));
00815 WN_st_idx (new_call) = WN_st_idx (call);
00816 for (int i=0; i<WN_kid_count(call); ++i)
00817 WN_kid(new_call,i) = WN_kid(call,i);
00818
00819 IPA_WN_Delete (caller->Map_Table(), ret_val_kid);
00820
00821 WN_kid (ret_val, 0) = new_call;
00822
00823
00824 if (WN_prev (call))
00825 WN_next (WN_prev (call)) = ret_val;
00826 else
00827 {
00828 WN * block =
00829 WN_Get_Parent (call, caller->Parent_Map(), caller->Map_Table());
00830
00831 Is_True (block, ("NULL parent of call node"));
00832 Is_True (WN_operator(block) == OPR_BLOCK,
00833 ("Parent of stmt not a block"));
00834
00835 WN_first (block) = ret_val;
00836 }
00837 WN_prev (ret_val) = WN_prev (call);
00838
00839 IPA_WN_Delete (caller->Map_Table(), call);
00840
00841 cg->Graph()->Delete_Edge (edge->Edge_Index());
00842 return;
00843 }
00844 }
00845 }
00846 #endif
00847
00848 if (!action_taken) {
00849
00850
00851
00852
00853 callee->Set_Undeletable();
00854
00855
00856 if (IPA_Enable_Cord) {
00857 fprintf (Call_graph_file, "%s\t%s\t%f\t%f\t%f\n", caller->Name (),
00858 callee->Name (), edge->Has_frequency () ?
00859 #ifdef KEY
00860 (edge->Get_frequency()).Value() : 0,
00861 (caller->Get_frequency()).Value(),
00862 (callee->Get_frequency()).Value()
00863 #else
00864 (edge->Get_frequency())._value : 0,
00865 (caller->Get_frequency())._value,
00866 (callee->Get_frequency())._value
00867 #endif
00868 );
00869 }
00870
00871 }
00872
00873
00874 ++(*Num_In_Calls_Processed)[callee];
00875 ++(*Num_Out_Calls_Processed)[caller];
00876 #ifdef _DEBUG_CALL_GRAPH
00877 printf("Processed %s --> %s\n", caller->Name(), callee->Name());
00878 #endif // _DEBUG_CALL_GRAPH
00879 edge->Set_Processed ();
00880
00881 }
00882
00883 extern void WN_free_input (void *handle, off_t mapped_size);
00884
00885 static inline void
00886 Delete_Proc (IPA_NODE *node)
00887 {
00888 Set_ST_is_not_used (node->Func_ST ());
00889 Delete_Function_In_File (node->File_Header(), node->Proc_Info_Index ());
00890 node->Un_Read_PU();
00891
00892 if (node->File_Header().num_written == IP_FILE_HDR_num_procs(node->File_Header()))
00893 WN_free_input(IP_FILE_HDR_input_map_addr(node->File_Header()), node->File_Header().mapped_size);
00894
00895 }
00896
00897 static void
00898 Perform_Transformation (IPA_NODE* caller, IPA_CALL_GRAPH* cg)
00899 {
00900
00901 Is_True (caller != NULL, ("Invalid IPA_NODE"));
00902
00903 #ifdef TODO
00904
00905
00906
00907
00908
00909
00910
00911 if (IPA_Space_Access_Mode == SAVE_SPACE_MODE &&
00912 caller->Get_partition_group () != partition_num)
00913 return;
00914
00915 if ( IPA_Enable_Recycle ) {
00916 MEM_POOL_Push (&Recycle_mem_pool);
00917 }
00918 #endif
00919
00920 Init_inline();
00921
00922 if (!caller->Is_Processed ()) {
00923 caller = IPO_Process_node (caller, cg);
00924 caller->Set_Processed ();
00925 }
00926
00927 IPA_SUCC_ITER succ_iter (caller);
00928 for (succ_iter.First(); !succ_iter.Is_Empty(); succ_iter.Next()) {
00929
00930 IPA_EDGE *edge = succ_iter.Current_Edge ();
00931 IPA_NODE *callee = cg->Callee (edge);
00932
00933 #ifdef KEY
00934 if (caller->Is_Recursive())
00935 callee->Set_Undeletable();
00936 #endif
00937
00938 #ifdef _DEBUG_CALL_GRAPH
00939 printf("%s ----> %s\n", caller->Name(), callee->Name());
00940 #endif // _DEBUG_CALL_GRAPH
00941
00942
00943 if (cg->Graph()->Is_Recursive_Edge(edge->Edge_Index()))
00944 callee->Clear_Clone_Candidate();
00945
00946 #ifdef TODO
00947 if (!callee->Is_Processed () &&
00948 ((IPA_Space_Access_Mode != SAVE_SPACE_MODE) ||
00949 (callee->Get_partition_group () == COMMON_PARTITION) ||
00950 (callee->Get_partition_group () == partition_num))) {
00951 callee = IPO_Process_node (callee, cg);
00952 callee->Set_Processed ();
00953 }
00954 #else
00955 if (!callee->Is_Processed ()) {
00956 callee = IPO_Process_node (callee, cg);
00957 callee->Set_Processed ();
00958 }
00959 #endif // TODO
00960
00961 #if 0
00962 if (cg->Graph()->Is_Recursive_Edge(edge->Edge_Index())) {
00963 caller->Set_Undeletable();
00964 callee->Set_Undeletable();
00965 }
00966 #endif
00967
00968 if (!edge->Is_Processed ())
00969 IPO_Process_edge (caller, callee, edge, cg);
00970
00971 if (caller == callee)
00972 continue;
00973
00974 #ifdef TODO
00975 if (IPA_Space_Access_Mode == SAVE_SPACE_MODE &&
00976 callee->Get_partition_group() != partition_num &&
00977
00978
00979
00980 ((IP_FILE_HDR_sp_partition_group(shd_callee) !=
00981 partition_num) || (partition_num == COMMON_PARTITION)))
00982 continue;
00983 #endif
00984
00985 if (! caller->Summary_Proc ()->Is_alt_entry () &&
00986 All_Calls_Processed (callee, cg)) {
00987 if (callee->Is_Deletable ()) {
00988 Delete_Proc (callee);
00989 } else {
00990 if (IPA_Enable_Array_Sections)
00991 IPA_LNO_Map_Node(callee, IPA_LNO_Summary);
00992 #ifdef KEY
00993 if (IPA_Enable_PU_Reorder == REORDER_DISABLE &&
00994 !Opt_Options_Inconsistent &&
00995 !IPA_Enable_Source_PU_Order)
00996 {
00997 #endif // KEY
00998 IPA_Rename_Builtins(callee);
00999 callee->Write_PU ();
01000 #ifdef _DEBUG_CALL_GRAPH
01001 printf("Writing %s \n", callee->Name());
01002 #endif // _DEBUG_CALL_GRAPH
01003 #ifdef KEY
01004 }
01005 #endif // KEY
01006 }
01007 }
01008
01009 }
01010
01011 #if defined(KEY) && !defined(_STANDALONE_INLINER) && !defined(_LIGHTWEIGHT_INLINER)
01012
01013 for (vector<inline_info>::iterator iter = inline_list.begin();
01014 iter != inline_list.end(); ++iter)
01015 {
01016 inline_info i = *iter;
01017 IPA_NODE *r_caller = i._node;
01018 IPA_EDGE *r_edge = i._edge;
01019 IPA_NODE *r_callee = cg->Callee (r_edge);
01020 FmtAssert (r_caller == r_callee && IPA_Enable_Inline &&
01021 r_edge->Has_Inline_Attrib () &&
01022 !r_callee->Has_Noinline_Attrib(),
01023 ("Unexpected attributes during recursive inlining"));
01024 MEM_POOL_Popper ipo_pool (&Ipo_mem_pool);
01025 BOOL action_taken = Inline_Call (r_caller, r_callee, r_edge, cg);
01026 if (action_taken)
01027 {
01028 IPO_Total_Inlined++;
01029
01030
01031 r_callee->Clear_Cloned_Symtab();
01032 }
01033 ++(*Num_In_Calls_Processed)[r_callee];
01034 ++(*Num_Out_Calls_Processed)[r_caller];
01035 #ifdef _DEBUG_CALL_GRAPH
01036 printf("Processed %s --> %s\n", r_caller->Name(), r_callee->Name());
01037 #endif // _DEBUG_CALL_GRAPH
01038 r_edge->Set_Processed ();
01039 }
01040 inline_list.clear ();
01041 #endif
01042
01043
01044
01045
01046
01047 IPA_SUCC_ITER succ_iter2 (caller);
01048 for (succ_iter2.First(); !succ_iter2.Is_Empty(); succ_iter2.Next()) {
01049 IPA_EDGE* edge = succ_iter2.Current_Edge();
01050 IPA_NODE* callee = IPA_Call_Graph->Callee(edge);
01051
01052 callee->Clear_Cloned_Symtab();
01053 }
01054
01055 if (All_Calls_Processed (caller, cg)) {
01056 if (caller->Is_Deletable ())
01057 Delete_Proc (caller);
01058 else {
01059 if (IPA_Enable_Array_Sections)
01060 IPA_LNO_Map_Node(caller, IPA_LNO_Summary);
01061 #ifdef KEY
01062 if (IPA_Enable_PU_Reorder == REORDER_DISABLE &&
01063 !Opt_Options_Inconsistent &&
01064 !IPA_Enable_Source_PU_Order)
01065 {
01066 #endif // KEY
01067 IPA_Rename_Builtins(caller);
01068 caller->Write_PU ();
01069 #ifdef _DEBUG_CALL_GRAPH
01070 printf("Writing %s \n", caller->Name());
01071 #endif // _DEBUG_CALL_GRAPH
01072 #ifdef KEY
01073 }
01074 #endif // KEY
01075
01076 }
01077 }
01078
01079 #ifdef TODO
01080 if (IPA_Enable_Recycle) {
01081 caller->Cleanup_State(cg);
01082 MEM_POOL_Pop(&Recycle_mem_pool);
01083 }
01084 #endif
01085
01086 }
01087
01088 static void
01089 Preorder_annotate_PU_and_kids(const char *const input_file_name,
01090 PU_Info * current_pu)
01091 {
01092 MEM_POOL_Push(MEM_pu_nz_pool_ptr);
01093
01094 Cur_PU_Feedback = NULL;
01095
01096
01097
01098
01099
01100 Elf64_Word feedback_size = PU_Info_subsect_size (current_pu, WT_FEEDBACK);
01101
01102
01103 Read_Local_Info(MEM_pu_nz_pool_ptr, current_pu);
01104
01105 #if 0
01106 if (PU_Info_state(current_pu, WT_AC_INTERNAL) != Subsect_InMem) {
01107 ErrMsg(EC_IR_Scn_Read, "alias class internal map", input_file_name);
01108 }
01109 #endif
01110
01111 Ip_alias_class->Finalize_memops(PU_Info_tree_ptr(current_pu));
01112
01113
01114
01115 Set_PU_Info_state(current_pu, WT_AC_INTERNAL, Subsect_Missing);
01116
01117
01118
01119 PU_Info_subsect_offset (current_pu, WT_FEEDBACK) = feedback_size;
01120 Write_PU_Info(current_pu);
01121
01122
01123 for (current_pu = PU_Info_child(current_pu);
01124 current_pu != NULL;
01125 current_pu = PU_Info_next(current_pu)) {
01126 Preorder_annotate_PU_and_kids(input_file_name, current_pu);
01127 }
01128
01129
01130 MEM_POOL_Pop(MEM_pu_nz_pool_ptr);
01131 }
01132
01133 #define AC_FILE_EXT ".acl"
01134
01135 static void
01136 Perform_Alias_Class_Annotation(void)
01137 {
01138 Write_ALIAS_CLASS_Map = TRUE;
01139 Write_AC_INTERNAL_Map = FALSE;
01140
01141
01142 for (vector<char *>::iterator name = Ip_alias_class_files.begin();
01143 name != Ip_alias_class_files.end();
01144 ++name) {
01145
01146 void *input_file = Open_Local_Input(*name);
01147
01148
01149 char *output_file_name = (char *) malloc(strlen(*name) + strlen(AC_FILE_EXT) + 1);
01150 output_file_name = strcpy(output_file_name, *name);
01151 output_file_name = strcat(output_file_name, AC_FILE_EXT);
01152 Output_File *output_file = Open_Output_Info(output_file_name);
01153 add_to_tmp_file_list(output_file_name);
01154
01155
01156
01157
01158
01159 if (WN_get_dst(input_file) == -1) {
01160 #ifdef KEY
01161 ErrMsg(EC_IR_Scn_Read, "dst", *name);
01162 #else
01163 ErrMsg(EC_IR_Scn_Read, "dst", name);
01164 #endif
01165 }
01166
01167
01168
01169
01170 PU_Info *pu_info_tree = WN_get_PU_Infos(input_file, NULL);
01171 for (PU_Info *current_pu = pu_info_tree;
01172 current_pu != NULL;
01173 current_pu = PU_Info_next(current_pu)) {
01174 Preorder_annotate_PU_and_kids(*name, current_pu);
01175 }
01176
01177
01178 WN_write_PU_Infos(pu_info_tree, output_file);
01179 WN_write_dst(Current_DST, output_file);
01180
01181 #if defined(TARG_SL)
01182 if (ld_ipa_opt[LD_IPA_IPISR].flag)
01183 WN_write_isr_cg(ipisr_cg, output_file);
01184 #endif
01185
01186
01187 Close_Output_Info();
01188 Free_Local_Input();
01189
01190 if (!IPA_Debug_AC_Temp_Files) {
01191 if (keep) {
01192 const char *const save_file_ext = ".save";
01193 char *save_file_name = (char *) malloc(strlen(*name) +
01194 strlen(save_file_ext) + 1);
01195 save_file_name = strcpy(save_file_name, *name);
01196 save_file_name = strcat(save_file_name, save_file_ext);
01197
01198 if (rename(*name, save_file_name) != 0) {
01199 ErrMsg(EC_Ipa_Rename, *name, save_file_name);
01200 }
01201 free(save_file_name);
01202 }
01203 if (rename(output_file_name, *name) != 0) {
01204 ErrMsg(EC_Ipa_Rename, output_file_name, *name);
01205 }
01206 }
01207
01208 free(output_file_name);
01209 }
01210 if (IPA_Debug_AC_Temp_Files) {
01211 for (vector<char *>::iterator name = Ip_alias_class_files.begin();
01212 name != Ip_alias_class_files.end();
01213 ++name) {
01214 if (keep) {
01215 const char *const save_file_ext = ".save";
01216 char *save_file_name = (char *) malloc(strlen(*name) +
01217 strlen(save_file_ext) + 1);
01218 save_file_name = strcpy(save_file_name, *name);
01219 save_file_name = strcat(save_file_name, save_file_ext);
01220
01221 if (rename(*name, save_file_name) != 0) {
01222 ErrMsg(EC_Ipa_Rename, *name, save_file_name);
01223 }
01224 }
01225 char *output_file_name = (char *) malloc(strlen(*name) +
01226 strlen(AC_FILE_EXT) + 1);
01227 output_file_name = strcpy(output_file_name, *name);
01228 output_file_name = strcat(output_file_name, AC_FILE_EXT);
01229 if (rename(output_file_name, *name) != 0) {
01230 ErrMsg(EC_Ipa_Rename, output_file_name, *name);
01231 }
01232 }
01233 }
01234 }
01235
01236
01237 static void
01238 Evaluate_RSE_Cost(MEM_POOL *pool) {
01239 if (! have_open_input_file) {
01240 fin = fopen("struc_feedback","r");
01241 have_open_input_file = TRUE;
01242 while (!feof(fin)) {
01243 REG_FB_POINTER reg_fb = CXX_NEW(struct reg_feedback,pool);
01244 fread(reg_fb,1,sizeof(struct reg_feedback),fin);
01245 REG_FB_INFO_TABLE[reg_fb->_func_name] = reg_fb;
01246 }
01247 fclose(fin);
01248 }
01249 }
01250
01251 static void
01252 Construct_Budget_Table(IPA_CALL_GRAPH *cg,MEM_POOL *pool) {
01253 IPA_NODE_ITER cg_iter(cg,PREORDER);
01254 for (cg_iter.First(); !cg_iter.Is_Empty(); cg_iter.Next()) {
01255 IPA_NODE* node = cg_iter.Current();
01256 if (node) {
01257 if (! node->Is_Deletable()) {
01258 REG_BUDGET_POINTER reg_budget_ptr = CXX_NEW(struct reg_budget,pool);
01259 reg_budget_ptr->_node = node;
01260 REG_BUDGET_TABLE[IPA_Node_Name(node)] = reg_budget_ptr;
01261 }
01262 }
01263 }
01264 }
01265
01266
01267 static IPA_EDGE *
01268 Get_Most_Frequent_Succ(IPA_NODE *seed,IPA_CALL_GRAPH *cg) {
01269 IPA_SUCC_ITER succ_iter (seed);
01270 IPA_EDGE *result = NULL;
01271 float max_weight = -100;
01272 for (succ_iter.First(); !succ_iter.Is_Empty(); succ_iter.Next()) {
01273 IPA_EDGE *edge = succ_iter.Current_Edge ();
01274 if ((!edge) || (edge->Is_Deletable())) continue;
01275 IPA_NODE *node = cg->Callee(edge);
01276 if (node == seed) {
01277 FB_FREQ edge_freq = edge->Get_frequency();
01278 REG_BUDGET_POINTER reg_budget_ptr = REG_BUDGET_TABLE[IPA_Node_Name(node)];
01279 reg_budget_ptr->_self_recursive_freq += edge_freq.Value();
01280 continue;
01281 }
01282
01283 if ((! node->Is_Deletable()) && (node->Get_Partition_Num() == 0)) {
01284 FB_FREQ edge_freq = edge->Get_frequency();
01285 FB_FREQ node_freq = node->Get_frequency();
01286 if (edge_freq > node_freq) {
01287 DevWarn("STANGE! %s HAS HIGHER EDGE FREQ!",IPA_Node_Name(node));
01288 }
01289 REG_FB_POINTER reg_fb = REG_FB_INFO_TABLE[IPA_Node_Name(node)];
01290 if (! reg_fb) {
01291 DevWarn("Function %s has no reg_fb!",IPA_Node_Name(node));
01292 continue;
01293 }
01294 INT32 stack_regs_used = reg_fb->_stacked_callee_used +
01295 reg_fb->_stacked_caller_used;
01296 float weight = (edge_freq.Value())*stack_regs_used;
01297 if ((edge_freq.Value()/node_freq.Value()) > 0.3) {
01298 if (weight > max_weight) {
01299 max_weight = weight;
01300 result = edge;
01301 }
01302 }
01303 }
01304 }
01305
01306 return result;
01307 }
01308 static void
01309 Print_Partition(IPA_NODE_VECTOR par) {
01310 for (IPA_NODE_VECTOR::iterator first = par.begin ();
01311 first != par.end ();++first) {
01312 IPA_NODE *node = *first;
01313 REG_BUDGET_POINTER reg_budget_ptr = REG_BUDGET_TABLE[IPA_Node_Name(node)];
01314 DevWarn("PARTITION %d HAS FUNCTION %s SELFRECURSIVE %f",node->Get_Partition_Num(),IPA_Node_Name(node),reg_budget_ptr->_self_recursive_freq);
01315 }
01316 }
01317
01318 static void
01319 Print_List(reg_list *head) {
01320 INT32 count = 0;
01321 for (reg_list *begin = head;begin != NULL;begin = begin->_next) {
01322 count++;
01323 if (begin->_node) {
01324 DevWarn("THE %d REG'S SPILL COST IS %f FUNCTION %s",count,begin->_spill_cost,IPA_Node_Name(begin->_node));
01325 }
01326 }
01327 }
01328
01329
01330 static IPA_EDGE *
01331 Get_Most_Frequent_Pred(IPA_NODE *seed,IPA_CALL_GRAPH *cg) {
01332 IPA_PRED_ITER pred_iter (seed);
01333 IPA_EDGE *result = NULL;
01334 float max_weight = -100;
01335 for (pred_iter.First(); !pred_iter.Is_Empty(); pred_iter.Next()) {
01336 IPA_EDGE *edge = pred_iter.Current_Edge ();
01337 if ((!edge) || (edge->Is_Deletable())) continue;
01338 IPA_NODE *node = cg->Caller(edge);
01339 if (node == seed) {
01340
01341
01342
01343
01344 continue;
01345 }
01346
01347 if ((! node->Is_Deletable()) && (node->Get_Partition_Num() == 0)) {
01348 FB_FREQ edge_freq = edge->Get_frequency();
01349 FB_FREQ node_freq = node->Get_frequency();
01350 REG_FB_POINTER reg_fb = REG_FB_INFO_TABLE[IPA_Node_Name(node)];
01351 if (! reg_fb) {
01352 DevWarn("Function %s has no reg_fb!",IPA_Node_Name(node));
01353 continue;
01354 }
01355 INT32 stack_regs_used = reg_fb->_stacked_callee_used +
01356 reg_fb->_stacked_caller_used;
01357 float weight = edge_freq.Value()*stack_regs_used;
01358 if ((edge_freq/node_freq) > 0.3) {
01359 if (weight > max_weight) {
01360 max_weight = weight;
01361 result = edge;
01362 }
01363 }
01364 }
01365 }
01366
01367 return result;
01368 }
01369
01370 static BOOL
01371 Pred_Thre(IPA_NODE *seed,IPA_EDGE *pred,IPA_CALL_GRAPH *cg) {
01372 if (pred == NULL) return FALSE;
01373 IPA_NODE *caller = cg->Caller(pred);
01374 reg_feedback *reg_fb = REG_FB_INFO_TABLE[IPA_Node_Name(caller)];
01375 if ((caller->Get_frequency()/seed->Get_frequency()) > 0.1) {
01376 return TRUE;
01377 }
01378 return FALSE;
01379 }
01380
01381 static BOOL
01382 Succ_Thre(IPA_NODE *seed,IPA_EDGE *succ,IPA_CALL_GRAPH *cg) {
01383 if (succ == NULL) return FALSE;
01384 IPA_NODE *callee = cg->Callee(succ);
01385 reg_feedback *reg_fb = REG_FB_INFO_TABLE[IPA_Node_Name(callee)];
01386 if ((callee->Get_frequency()/seed->Get_frequency()) > 0.1) {
01387 return TRUE;
01388 }
01389
01390 return FALSE;
01391 }
01392
01393 static void
01394 Get_Next_Partition (IPA_CALL_GRAPH *cg,IPA_NODE_VECTOR& partition,
01395 INT32 partition_num,IPA_NODE *entry) {
01396
01397 float max_weight = -100;
01398 IPA_NODE *seed = NULL;
01399 IPA_NODE_ITER cg_iter(IPA_Call_Graph,PREORDER);
01400 for (cg_iter.First(); !cg_iter.Is_Empty(); cg_iter.Next()) {
01401 IPA_NODE* node = cg_iter.Current();
01402 if (node) {
01403 if (! node->Is_Deletable()) {
01404 REG_FB_POINTER reg_fb = REG_FB_INFO_TABLE[IPA_Node_Name(node)];
01405 if (!reg_fb) {
01406 DevWarn("Function %s has no reg_fb!",IPA_Node_Name(node));
01407 continue;
01408 }
01409
01410 INT32 stack_regs_used = reg_fb->_stacked_caller_used +
01411 reg_fb->_stacked_callee_used;
01412 if ((stack_regs_used > 20) &&
01413 (reg_fb->_stacked_callee_used > 15)) {
01414 FB_FREQ freq = node->Get_frequency();
01415 float weight = freq.Value() * stack_regs_used;
01416 if ((weight > max_weight)&&(node->Get_Partition_Num()==0)) {
01417 max_weight = weight;
01418 seed = node;
01419 }
01420 }
01421 }
01422 }
01423 }
01424 if (seed == NULL) return;
01425 seed->Set_Partition_Num(partition_num);
01426 partition.push_back(seed);
01427
01428 IPA_EDGE *edge = Get_Most_Frequent_Succ(seed,cg);
01429 while (Succ_Thre(seed,edge,cg)) {
01430 IPA_NODE *callee = cg->Callee(edge);
01431 callee->Set_Partition_Num(partition_num);
01432 partition.push_back(callee);
01433 IPA_NODE *caller = callee;
01434 edge = Get_Most_Frequent_Succ(caller,cg);
01435 }
01436
01437 edge = Get_Most_Frequent_Pred(seed,cg);
01438 while (Pred_Thre(seed,edge,cg)) {
01439 IPA_NODE *caller = cg->Caller(edge);
01440 entry = caller;
01441 caller->Set_Partition_Num(partition_num);
01442 partition.push_back(caller);
01443 IPA_NODE *callee = caller;
01444 edge = Get_Most_Frequent_Pred(callee,cg);
01445 }
01446
01447
01448
01449
01450
01451
01452
01453
01454
01455 }
01456
01457 static BOOL
01458 Compare_Cost(reg_list *list,IPA_CALL_GRAPH *cg,INT32 partition_num) {
01459 float spill_cost = list->_spill_cost;
01460 float freq = 0;
01461 IPA_NODE *node = list->_node;
01462 IPA_SUCC_ITER succ_iter(node);
01463 for (succ_iter.First(); !succ_iter.Is_Empty(); succ_iter.Next()) {
01464 IPA_EDGE* edge = succ_iter.Current_Edge();
01465 if ((!edge) || (edge->Is_Deletable())) continue;
01466 IPA_NODE* callee = cg->Callee(edge);
01467 if (callee->Get_Partition_Num() == partition_num) {
01468 if (callee == node) {
01469 reg_budget *budget = REG_BUDGET_TABLE[IPA_Node_Name(node)];
01470 freq = freq + (edge->Get_frequency()).Value()*REC_OVERFLOW_COST;
01471 } else {
01472 freq = freq + (edge->Get_frequency()).Value()*OVERFLOW_COST;
01473 }
01474 }
01475 }
01476
01477
01478 if (spill_cost > freq) {
01479 return TRUE;
01480 } else {
01481 return FALSE;
01482 }
01483 }
01484
01485 static BOOL
01486 Compare_Self_Recursive_Cost(reg_list *list) {
01487 float spill_cost = list->_spill_cost;
01488 IPA_NODE *node = list->_node;
01489 if (!node->Is_Deletable()) {
01490 reg_budget *budget = REG_BUDGET_TABLE[IPA_Node_Name(node)];
01491 if (spill_cost > (budget->_self_recursive_freq*REC_OVERFLOW_COST)) {
01492 return TRUE;
01493 } else {
01494 return FALSE;
01495 }
01496 }
01497 }
01498
01499 static reg_list*
01500 Construct_List(IPA_NODE_VECTOR par) {
01501 struct reg_list* head = (reg_list *) malloc(sizeof(reg_list));
01502 struct reg_list* tail = (reg_list *) malloc(sizeof(reg_list));
01503 head->_node = NULL;
01504 tail->_node = NULL;
01505 head->_spill_cost = FLT_MAX;
01506 tail->_spill_cost = -FLT_MAX;
01507 tail->_next = NULL;
01508 tail->_prev = head;
01509 head->_prev = NULL;
01510 head->_next = tail;
01511 for (IPA_NODE_VECTOR::iterator first = par.begin ();
01512 first != par.end ();++first) {
01513 IPA_NODE *node = *first;
01514 if (! node->Is_Deletable()) {
01515
01516 REG_FB_POINTER reg_fb = REG_FB_INFO_TABLE[IPA_Node_Name(node)];
01517 if (reg_fb == NULL) {
01518 DevWarn("Function %s has no reg_fb!",IPA_Node_Name(node));
01519 continue;
01520 }
01521
01522 for (INT32 i = 0;i < 96;i++) {
01523 if (reg_fb->_cost[i] > 0) {
01524 struct reg_list* list = (reg_list*) malloc(sizeof(reg_list))
01525 ;
01526 list->_spill_cost = reg_fb->_cost[i];
01527 list->_node = node;
01528 for (reg_list *begin = head;begin != NULL;
01529 begin = begin->_next) {
01530 if (list->_spill_cost > begin->_spill_cost) {
01531 list->_prev = begin->_prev;
01532 list->_next = begin;
01533 begin->_prev->_next = list;
01534 begin->_prev = list;
01535 break;
01536 }
01537 }
01538 }
01539 }
01540 }
01541 }
01542
01543 return head;
01544 }
01545
01546 static void
01547 Delete_List(reg_list* head) {
01548 }
01549
01550 static void
01551 Print_Budget(IPA_NODE_VECTOR par) {
01552 for (IPA_NODE_VECTOR::iterator first = par.begin ();
01553 first != par.end ();++first) {
01554 IPA_NODE *node = *first;
01555 REG_FB_POINTER reg_fb = REG_FB_INFO_TABLE[IPA_Node_Name(node)];
01556 REG_BUDGET_POINTER reg_budget_ptr =
01557 REG_BUDGET_TABLE[IPA_Node_Name(node)];
01558 INT32 ori = reg_fb->_stacked_callee_used+reg_fb->_stacked_caller_used;
01559 INT32 now = reg_budget_ptr->_budget;
01560 DevWarn("ORIGINAL %d NOW %d FOR FUNCTION %s",ori,now,IPA_Node_Name(node));
01561 }
01562 }
01563
01564 static void
01565 Distribute_Partition(IPA_NODE_VECTOR par,IPA_CALL_GRAPH *cg,INT32 partition_num){
01566 struct reg_list* head = Construct_List(par);
01567 Print_List(head);
01568 INT32 count = 0;
01569 for (reg_list *begin = head; begin != NULL; begin = begin->_next) {
01570 IPA_NODE *node = begin->_node;
01571 if (node) {
01572 REG_BUDGET_POINTER reg_budget_ptr =
01573 REG_BUDGET_TABLE[IPA_Node_Name(node)];
01574 if (count > 100) {
01575 BOOL use = Compare_Cost(begin,cg,partition_num);
01576 if (use) {
01577 reg_budget_ptr->_budget++;
01578 count++;
01579 }
01580 } else {
01581 if (reg_budget_ptr->_self_recursive_freq > 0) {
01582 if (Compare_Self_Recursive_Cost(begin)) {
01583 count++;
01584 reg_budget_ptr->_budget++;
01585 }
01586 } else {
01587 reg_budget_ptr->_budget++;
01588 count++;
01589 }
01590 }
01591 }
01592 }
01593 Print_Budget(par);
01594
01595 }
01596
01597 static void Initialize_Partition_Num(IPA_CALL_GRAPH *cg) {
01598 IPA_NODE_ITER cg_iter(IPA_Call_Graph,PREORDER);
01599 for (cg_iter.First(); !cg_iter.Is_Empty(); cg_iter.Next()) {
01600 IPA_NODE* node = cg_iter.Current();
01601 if (node) {
01602 node->Set_Partition_Num(0);
01603 }
01604 }
01605
01606 }
01607
01608 static INT32
01609 Count_Total_Regs(IPA_NODE_VECTOR partition) {
01610 INT32 count = 0;
01611 for (IPA_NODE_VECTOR::iterator iter = partition.begin ();
01612 iter != partition.end ();++iter) {
01613 IPA_NODE *node = *iter;
01614 REG_FB_POINTER reg_fb = REG_FB_INFO_TABLE[IPA_Node_Name(node)];
01615 count = count + reg_fb->_stacked_callee_used
01616 + reg_fb->_stacked_caller_used;
01617 }
01618
01619 return count;
01620 }
01621
01622 static void
01623 Stacked_Regs_Distribution(IPA_CALL_GRAPH *cg) {
01624 BOOL finished = FALSE;
01625 Initialize_Partition_Num(cg);
01626
01627 INT32 partition_num = 1;
01628 IPA_NODE *entry;
01629
01630 while (!finished) {
01631 IPA_NODE_VECTOR partition;
01632 Get_Next_Partition(cg,partition,partition_num,entry);
01633 if (!partition.empty()) {
01634 Print_Partition(partition);
01635 INT32 total = Count_Total_Regs(partition);
01636 BOOL no_self_recursive_node = TRUE;
01637 for (IPA_NODE_VECTOR::iterator iter = partition.begin();
01638 iter != partition.end();++iter) {
01639 IPA_NODE *n = *iter;
01640 REG_BUDGET_POINTER p = REG_BUDGET_TABLE[IPA_Node_Name(n)];
01641 if (p->_self_recursive_freq > 0) {
01642 no_self_recursive_node = FALSE;
01643 break;
01644 }
01645 }
01646
01647 if ((total < 96) && (no_self_recursive_node)) {
01648 DevWarn("REGISTER USAGE OF THIS PARTITION LESS THAN 96!");
01649 for (IPA_NODE_VECTOR::iterator iter = partition.begin();
01650 iter != partition.end();++iter) {
01651 (*iter)->Set_Partition_Num(-1);
01652 }
01653 continue;
01654 } else {
01655 Distribute_Partition(partition,cg,partition_num);
01656 }
01657 } else {
01658 finished = TRUE;
01659 }
01660 partition_num++;
01661 if (partition_num == 10) finished = TRUE;
01662 }
01663 }
01664
01665 #ifdef KEY
01666 #include <queue>
01667 struct order_node_by_freq {
01668 bool operator() (IPA_NODE * first, IPA_NODE * second)
01669 {
01670 return first->Get_frequency() < second->Get_frequency();
01671 }
01672 };
01673
01674
01675
01676
01677
01678 struct order_node_by_file_id {
01679 bool operator() (IPA_NODE * first, IPA_NODE * second)
01680 {
01681
01682
01683
01684
01685
01686
01687
01688
01689
01690 if (first->File_Id() == second->File_Id() &&
01691 first->File_Id() != -1 )
01692 return PU_Info_subsect_offset(first->PU_Info(), WT_TREE) >
01693 PU_Info_subsect_offset(second->PU_Info(), WT_TREE);
01694
01695
01696 return first->File_Id() > second->File_Id();
01697 }
01698 };
01699 static void
01700 IPA_Remove_Regions (IPA_NODE_VECTOR v, IPA_CALL_GRAPH * cg)
01701 {
01702 SCOPE * old_scope = Scope_tab;
01703
01704 for (IPA_NODE_VECTOR::iterator node = v.begin ();
01705 node != v.end (); ++node)
01706
01707 {
01708 PU pu = Pu_Table[ST_pu((*node)->Func_ST())];
01709
01710 if (!(PU_src_lang (pu) & PU_CXX_LANG) || !PU_has_region (pu))
01711 continue;
01712
01713 IPA_NODE_CONTEXT context (*node);
01714 cg->Map_Callsites (*node);
01715 WN_MAP Node_Parent_Map = (*node)->Parent_Map();
01716 WN_MAP_TAB * Node_Map_Tab = PU_Info_maptab ((*node)->PU_Info());
01717
01718 IPA_SUCC_ITER succ_iter (*node);
01719 BOOL changed = false;
01720 for (succ_iter.First(); !succ_iter.Is_Empty(); succ_iter.Next())
01721 {
01722 IPA_EDGE *edge = succ_iter.Current_Edge ();
01723 IPA_NODE *callee = cg->Callee (edge);
01724
01725 if (callee->PU_Can_Throw())
01726 continue;
01727
01728
01729 WN * call = edge->Whirl_Node();
01730 Is_True (call, ("Call whirl node absent in IPA edge"));
01731 WN * parent = WN_Get_Parent (call, Node_Parent_Map, Node_Map_Tab);
01732 for (; parent; parent = WN_Get_Parent (parent, Node_Parent_Map, Node_Map_Tab))
01733 {
01734 if (WN_operator(parent) != OPR_REGION || !WN_region_is_EH(parent))
01735 continue;
01736 if (WN_block_empty (WN_region_pragmas (parent)))
01737 {
01738 WN * body = WN_region_body (parent);
01739 if (WN_first (body) == WN_last (body) &&
01740 WN_first (body) == call)
01741 {
01742 changed = true;
01743
01744 WN * parent_of_region = WN_Get_Parent (parent,
01745 Node_Parent_Map, Node_Map_Tab);
01746
01747 Is_True (parent_of_region,
01748 ("Region node not within any block"));
01749 Is_True (WN_prev (parent) ||
01750 (WN_operator (parent_of_region) ==
01751 OPR_BLOCK && WN_first (parent_of_region) ==
01752 parent), ("Error removing EH region"));
01753
01754
01755 if (!WN_prev (parent))
01756 WN_first (parent_of_region) = call;
01757 else
01758 WN_next (WN_prev (parent)) = call;
01759 WN_prev (call) = WN_prev (parent);
01760
01761
01762 if (!WN_next (parent))
01763 WN_last (parent_of_region) = call;
01764 else
01765 WN_prev (WN_next (parent)) = call;
01766 WN_next (call) = WN_next (parent);
01767
01768 WN_first (body) = WN_last (body) = NULL;
01769
01770 WN_prev (parent) = WN_next (parent) = NULL;
01771 }
01772 }
01773 }
01774 }
01775 if (changed)
01776 {
01777 WN_Parentize ((*node)->Whirl_Tree (FALSE), Node_Parent_Map, Node_Map_Tab);
01778 changed = false;
01779 }
01780 }
01781 Scope_tab = old_scope;
01782 }
01783
01784
01785
01786
01787
01788 static void
01789 check_for_nested_PU (IPA_NODE * node)
01790 {
01791 PU_Info * info = node->PU_Info();
01792
01793 if (info)
01794 {
01795 PU_Info * child = PU_Info_child (info);
01796
01797 while (child)
01798 {
01799 IPA_NODE * child_node = Get_Node_From_PU (child);
01800 if (child_node == NULL)
01801 {
01802 child = PU_Info_next (child);
01803 continue;
01804 }
01805 #ifdef Is_True_On
01806 int lexical_level = PU_lexical_level (child_node->Func_ST());
01807 Is_True (lexical_level > GLOBAL_SYMTAB+1,
01808 ("Nested PU's level should be greater than 2"));
01809 Is_True (node->File_Id() == child_node->File_Id(),
01810 ("Parent and child PU are in different files"));
01811 if (!PU_ftn_lang (Pu_Table[ST_pu (child_node->Func_ST())]))
01812 DevWarn ("Encountered nested PU in non-Fortran langage");
01813 #endif
01814
01815
01816 if (!PU_Written (IPA_Call_Graph->Graph(), child_node,
01817 &child_node->File_Header()) &&
01818 !PU_Deleted (IPA_Call_Graph->Graph(), child_node->Node_Index(),
01819 &child_node->File_Header()))
01820 {
01821 check_for_nested_PU (child_node);
01822 #if defined(TARG_SL)
01823 if (ld_ipa_opt[LD_IPA_IPISR].flag) {
01824 ErrMsg(EC_Ipa_Outfile, "Encountered nested PU when -ipisr is turned on");
01825 }
01826 #endif
01827 IPA_Rename_Builtins (child_node);
01828 child_node->Write_PU();
01829 }
01830 child = PU_Info_next (child);
01831 }
01832 }
01833 }
01834 #endif // KEY
01835
01836 #if defined(TARG_SL)
01837
01838
01839
01840
01841
01842
01843
01844
01845 vector<mINT32> ipisr_cg;
01846 #endif
01847
01848 static void
01849 IPO_main (IPA_CALL_GRAPH* cg)
01850 {
01851 MEM_POOL_Constructor ipo_pool (&Ipo_mem_pool, "Inline mem pool", FALSE);
01852 MEM_POOL_Constructor recycle_pool (&Recycle_mem_pool,
01853 "Recycle_mem_pool", FALSE);
01854 MEM_POOL_Constructor array_pool (&IPA_LNO_mem_pool, "IPA_LNO_mem_pool",
01855 FALSE);
01856
01857 Set_Error_Phase ("IPA Transformation");
01858
01859 if (IPA_Enable_Array_Sections) {
01860 IPA_LNO_Summary = CXX_NEW(IPA_LNO_WRITE_SUMMARY(array_pool.Pool ()),
01861 array_pool.Pool ());
01862 }
01863
01864 if (IPA_Enable_Padding)
01865 IPO_Pad_Symtab (IPA_Common_Table);
01866
01867 if (IPA_Enable_Split_Common)
01868 IPO_Split_Common ();
01869
01870
01871 if(IPA_Enable_Reorder && reorder_candidate.size){
01872 IPO_get_new_ordering();
01873 IPO_reorder_Fld_Tab();
01874 }
01875
01876 Init_Num_Calls_Processed (cg, ipo_pool.Pool ());
01877
01878 #ifdef KEY
01879 IPA_Create_Builtins();
01880 #endif
01881
01882 IPA_NODE_VECTOR walk_order;
01883
01884 Build_Transformation_Order (walk_order, cg->Graph(), cg->Root());
01885
01886 #ifdef KEY
01887 if (IPA_Enable_EH_Region_Removal)
01888 IPA_Remove_Regions (walk_order, cg);
01889 #endif
01890
01891 for (IPA_NODE_VECTOR::iterator first = walk_order.begin ();
01892 first != walk_order.end ();
01893 ++first) {
01894
01895
01896
01897
01898
01899
01900
01901 Perform_Transformation (*first, cg);
01902
01903 }
01904
01905 #if defined(TARG_SL)
01906
01907
01908
01909
01910 if (IPA_Enable_PU_Reorder == REORDER_BY_BFS)
01911 {
01912
01913 IPA_NODE_VECTOR emit_order, emit_queue;
01914 Build_BFS_Order (emit_order, cg->Graph(), cg->Root());
01915
01916 mINT32 cnt = 0;
01917
01918
01919 for (IPA_NODE_VECTOR::iterator first = emit_order.begin ();
01920 first != emit_order.end (); ++first)
01921 {
01922 IPA_NODE* emit = *first;
01923 if (!PU_Deleted (cg->Graph(), emit->Node_Index(),
01924 &emit->File_Header()) &&
01925 !PU_Written (cg->Graph(), emit,
01926 &emit->File_Header())
01927 ) {
01928
01929 check_for_nested_PU (emit);
01930 IPA_Rename_Builtins(emit);
01931 emit->Write_PU();
01932 emit->Set_Emit_Id(cnt++);
01933 emit_queue.push_back(emit);
01934 }
01935 }
01936
01937
01938 for (IPA_NODE_VECTOR::iterator first = emit_queue.begin ();
01939 first != emit_queue.end (); ++first)
01940 {
01941 IPA_NODE* callee = *first;
01942 IPA_PRED_ITER pred_iter(callee);
01943 vector<mINT32> visited;
01944
01945
01946 for (pred_iter.First(); !pred_iter.Is_Empty(); pred_iter.Next()) {
01947
01948 IPA_EDGE *edge = pred_iter.Current_Edge ();
01949 if (edge == NULL) continue;
01950
01951 IPA_NODE *caller = cg->Caller (edge);
01952 mINT32 id = caller->Emit_Id();
01953
01954
01955
01956 Is_True(emit_queue.end()
01957 != find(emit_queue.begin(), emit_queue.end(), caller),
01958 ("In IPISR, the caller is not in the emit queue!\n"));
01959
01960
01961 if (visited.end() == find(visited.begin(), visited.end(), id)) {
01962 ipisr_cg.push_back(id);
01963 visited.push_back(id);
01964 }
01965 }
01966
01967 ipisr_cg.push_back(-1);
01968 }
01969 }
01970 #endif // TARG_SL
01971
01972 #ifdef KEY
01973 {
01974 if (IPA_Enable_Source_PU_Order || Opt_Options_Inconsistent)
01975 {
01976 priority_queue<IPA_NODE*, vector<IPA_NODE*>, order_node_by_file_id> emit_order;
01977 for (IPA_NODE_VECTOR::iterator first = walk_order.begin ();
01978 first != walk_order.end (); ++first)
01979 {
01980 if (!PU_Deleted (cg->Graph(), (*first)->Node_Index(),
01981 &(*first)->File_Header()))
01982 {
01983 emit_order.push (*first);
01984 }
01985 }
01986 while (!emit_order.empty())
01987 {
01988 IPA_NODE *emit = emit_order.top();
01989 emit_order.pop();
01990 if (!PU_Written (cg->Graph(), emit,
01991 &emit->File_Header()))
01992 {
01993
01994 check_for_nested_PU (emit);
01995 IPA_Rename_Builtins(emit);
01996 IPA_NODE::next_file_id = emit_order.empty() ? -1 : emit_order.top()->File_Id();
01997 emit->Write_PU();
01998 }
01999 }
02000 }
02001 else if (IPA_Enable_PU_Reorder == REORDER_BY_EDGE_FREQ)
02002 {
02003 for (vector<IPA_NODE*>::iterator it = emit_order.begin();
02004 it != emit_order.end(); ++it)
02005 {
02006 IPA_NODE * n = *it;
02007 if (!PU_Deleted (cg->Graph(), n->Node_Index(),
02008 &n->File_Header()) &&
02009 !PU_Written (cg->Graph(), n,
02010 &n->File_Header()))
02011 {
02012 IPA_Rename_Builtins(n);
02013 n->Write_PU();
02014 }
02015 }
02016 emit_order.clear();
02017
02018 for (IPA_NODE_VECTOR::iterator first = walk_order.begin ();
02019 first != walk_order.end (); ++first)
02020 {
02021 if (!PU_Deleted (cg->Graph(), (*first)->Node_Index(),
02022 &(*first)->File_Header()) &&
02023 !PU_Written (cg->Graph(), *first,
02024 &(*first)->File_Header()))
02025 {
02026 check_for_nested_PU (*first);
02027 IPA_Rename_Builtins(*first);
02028 (*first)->Write_PU();
02029 }
02030 }
02031 }
02032 else if (IPA_Enable_PU_Reorder == REORDER_BY_NODE_FREQ)
02033 {
02034 priority_queue<IPA_NODE*, vector<IPA_NODE*>, order_node_by_freq> emit_order;
02035 for (IPA_NODE_VECTOR::iterator first = walk_order.begin ();
02036 first != walk_order.end (); ++first)
02037 {
02038 if (!PU_Deleted (cg->Graph(), (*first)->Node_Index(),
02039 &(*first)->File_Header()))
02040 {
02041 emit_order.push (*first);
02042 }
02043 }
02044
02045 while (!emit_order.empty())
02046 {
02047 IPA_NODE *emit = emit_order.top();
02048 emit_order.pop();
02049
02050 if (!PU_Written (cg->Graph(), emit,
02051 &emit->File_Header()))
02052 {
02053
02054 check_for_nested_PU (emit);
02055 IPA_Rename_Builtins(emit);
02056 emit->Write_PU();
02057 }
02058 }
02059 }
02060 }
02061 #endif // KEY
02062
02063 if(IPA_Enable_Reorder)
02064 IPO_Finish_reorder();
02065
02066 IP_flush_output ();
02067
02068 if (IPA_Enable_Array_Sections)
02069 IPA_LNO_Write_Summary (IPA_LNO_Summary);
02070
02071 Clear_Common_Block_Element_Map ();
02072
02073 if ( Trace_IPA || Trace_Perf ) {
02074 fprintf ( TFile, "Total number of edges = %d\n", IPA_Call_Graph->Edge_Size() );
02075 }
02076
02077 if ( INLINE_List_Actions ) {
02078 fprintf ( stderr, "Total number of edges = %d\n", IPA_Call_Graph->Edge_Size() );
02079 }
02080 }
02081
02082
02083 static BOOL BE_symtab_initialized = FALSE;
02084
02085
02086
02087
02088 static void
02089 BE_Symtab_Initialize()
02090 {
02091 if (!BE_symtab_initialized) {
02092 BE_symtab_initialize_be_scopes();
02093 BE_symtab_alloc_scope_level (GLOBAL_SYMTAB);
02094 for (SYMTAB_IDX scope_level = 0;
02095 scope_level <= GLOBAL_SYMTAB;
02096 ++scope_level) {
02097
02098
02099 if (Scope_tab[scope_level].st_tab != NULL) {
02100 Scope_tab[scope_level].st_tab->
02101 Register(*Be_scope_tab[scope_level].be_st_tab);
02102 }
02103 else {
02104 Is_True(scope_level == 0,
02105 ("Nonexistent st_tab for level %d", scope_level));
02106 }
02107 }
02108 BE_symtab_initialized = TRUE;
02109 }
02110 }
02111
02112
02113
02114
02115 static void
02116 BE_Symtab_Finalize()
02117 {
02118 if (BE_symtab_initialized) {
02119 for (SYMTAB_IDX idx = GLOBAL_SYMTAB + 1; idx > 0; --idx) {
02120
02121
02122 SYMTAB_IDX scope_level = idx - 1;
02123 if (Scope_tab[scope_level].st_tab != NULL) {
02124 Scope_tab[scope_level].st_tab->
02125 Un_register(*Be_scope_tab[scope_level].be_st_tab);
02126 Be_scope_tab[scope_level].be_st_tab->Clear();
02127 }
02128 else {
02129 Is_True(scope_level == 0,
02130 ("Nonexistent st_tab for level %d", scope_level));
02131 }
02132 }
02133
02134 BE_symtab_free_be_scopes();
02135 BE_symtab_initialized = FALSE;
02136 }
02137 }
02138
02139
02140 void
02141 Perform_Interprocedural_Optimization (void)
02142 {
02143 if (IP_File_header.size() == 0) {
02144 if (IPA_Enable_ipacom) {
02145 ipa_compile_init ();
02146 ipacom_doit (NULL);
02147 exit (RC_SYSTEM_ERROR);
02148 } else {
02149 Signal_Cleanup (0);
02150 #ifdef KEY
02151 exit(1);
02152 #endif
02153 }
02154 }
02155
02156 Set_ipa_tlog_phase(PHASE_IPA);
02157
02158 if (IPA_Enable_ipacom) {
02159 ipa_compile_init ();
02160 }
02161
02162 #ifdef TODO
02163
02164 if( IPA_Enable_Feedback ) {
02165 setup_IPA_feedback();
02166 }
02167 #endif
02168
02169 BE_Symtab_Initialize();
02170
02171 Perform_Interprocedural_Analysis ();
02172
02173
02174
02175 #ifdef Is_True_On
02176 CGB_IPA_Initialize(IPA_Call_Graph);
02177 #endif
02178
02179 if (IPA_Enable_AutoGnum)
02180 Autognum_Driver ();
02181
02182 if (IPA_Enable_ipacom)
02183 ipacom_process_symtab (IP_global_symtab_name());
02184
02185 CXX_MEM_POOL ip_alias_class_mem_pool ("Alias class pool", FALSE);
02186
02187
02188
02189
02190
02191
02192
02193
02194
02195 IP_ALIAS_CLASSIFICATION ip_alias_class_instance(ip_alias_class_mem_pool());
02196 Ip_alias_class = &ip_alias_class_instance;
02197 if (IPA_Enable_Alias_Class) {
02198 Ip_alias_class->Init_maps();
02199 }
02200
02201 #if Is_True_On
02202 if ( Get_Trace ( TKIND_ALLOC, TP_IPA) ) {
02203 fprintf ( TFile,
02204 "\n%s%s\tMemory allocation information before IPO_main\n%s%s\n",
02205 DBar, DBar, DBar, DBar );
02206 MEM_Trace ();
02207 }
02208 #endif
02209
02210 if (Get_Trace(TP_IPA, IPA_TRACE_TUNING_NEW)) {
02211 fprintf(TFile, "\t+++++++++++++++++++++++++++++++++++++++\n");
02212 IPA_Call_Graph->Print_vobose(TFile);
02213 fprintf(TFile, "\t+++++++++++++++++++++++++++++++++++++++\n");
02214 }
02215
02216 IPO_main (IPA_Call_Graph);
02217
02218 #if Is_True_On
02219 if ( Get_Trace ( TKIND_ALLOC, TP_IPA) ) {
02220 fprintf ( TFile,
02221 "\n%s%s\tMemory allocation information after IPO_main\n%s%s\n",
02222 DBar, DBar, DBar, DBar );
02223 MEM_Trace ();
02224 }
02225 #endif
02226
02227
02228
02229
02230 if (IPA_Enable_Alias_Class) {
02231 Ip_alias_class->
02232 Classify_initialized_data(Scope_tab[GLOBAL_SYMTAB].inito_tab);
02233 }
02234
02235 IP_write_global_symtab();
02236
02237 if (IPA_Enable_Alias_Class) {
02238 Perform_Alias_Class_Annotation();
02239 }
02240
02241 #if Is_True_On
02242 if ( Get_Trace ( TKIND_ALLOC, TP_IPA) ) {
02243 fprintf ( TFile,
02244 "\n%s%s\tMemory allocation information after alias class annotation\n%s%s\n",
02245 DBar, DBar, DBar, DBar );
02246 MEM_Trace ();
02247 }
02248 #endif
02249
02250 Ip_alias_class->Release_resources();
02251 Ip_alias_class = NULL;
02252
02253 #if Is_True_On
02254 {
02255 for (IP_FILE_HDR_TABLE::iterator f = IP_File_header.begin();
02256 f != IP_File_header.end();
02257 ++f) {
02258 Is_True(IP_FILE_HDR_all_procs_processed(*f),
02259 ("At end of IPA, file header %d has %u PUs, %u processed PUs",
02260 IP_FILE_HDR_file_name(*f) ? IP_FILE_HDR_file_name(*f) : "***",
02261 IP_FILE_HDR_num_procs(*f),
02262 IP_FILE_HDR_num_procs_processed(*f)));
02263 }
02264 }
02265 #endif
02266
02267 BE_Symtab_Finalize();
02268
02269 if (IPA_Enable_ipacom) {
02270 #ifdef Is_True_On
02271 CGB_IPA_Terminate();
02272 #endif
02273 ipacom_doit (IPA_Enable_Opt_Alias ? Ipa_File_Name : NULL);
02274 exit (RC_SYSTEM_ERROR);
02275 } else {
02276 #ifdef Is_True_On
02277 CGB_IPA_Terminate();
02278 #endif
02279 kill (getpid (), SIGQUIT);
02280 }
02281
02282
02283
02284 }
02285
02286
02287 void
02288 Print_inline_decision (void) {
02289
02290 FILE *orc_script = fopen ("orc_script.log", "w");
02291 INT32 callsite_linenum;
02292 INT32 callsite_colnum;
02293 USRCPOS callsite_srcpos;
02294 char *caller_filename, *callee_filename;
02295 char *caller_funcname, *callee_funcname;
02296
02297 IPA_NODE_ITER cg_iter(IPA_Call_Graph, PREORDER);
02298 fprintf (orc_script, "\n#BEGIN_INLINE\n\n");
02299
02300 for (cg_iter.First(); !cg_iter.Is_Empty(); cg_iter.Next()) {
02301
02302 IPA_NODE* node = cg_iter.Current();
02303 if (node) {
02304
02305 IPA_NODE_CONTEXT context (node);
02306 IPA_Call_Graph->Map_Callsites (node);
02307
02308
02309 IP_FILE_HDR& caller_hdr = node->File_Header ();
02310 caller_filename = (char *) alloca(strlen(caller_hdr.file_name)+1);
02311 strcpy(caller_filename, caller_hdr.file_name);
02312
02313 fprintf (orc_script, "COMPILE (\"%s\",%s,NOREG) {\n",
02314 DEMANGLE(caller_filename), DEMANGLE(IPA_Node_Name(node)));
02315 BOOL seen_callee = FALSE;
02316
02317 IPA_SUCC_ITER succ_iter(node);
02318 for (succ_iter.First(); !succ_iter.Is_Empty(); succ_iter.Next()) {
02319 IPA_EDGE* tmp_edge = succ_iter.Current_Edge();
02320 if (tmp_edge) {
02321 EDGE_INDEX tmp_idx = tmp_edge->Edge_Index();
02322 WN* call_wn = tmp_edge->Whirl_Node();
02323 IPA_NODE* callee =IPA_Call_Graph->Callee( tmp_idx );
02324
02325 IP_FILE_HDR& callee_hdr = callee->File_Header ();
02326
02327 if (call_wn == NULL) {
02328 fprintf (orc_script, "Warning: no source line number found for call-edge [%s --> %s]\n", node->Name(), callee->Name());
02329 callsite_linenum = 0;
02330 callsite_colnum = -1;
02331 } else {
02332 USRCPOS_srcpos(callsite_srcpos) = WN_Get_Linenum (call_wn);
02333 callsite_linenum = USRCPOS_linenum(callsite_srcpos);
02334 callsite_colnum = USRCPOS_column(callsite_srcpos);
02335 }
02336
02337 callee_filename = (char *) alloca(strlen(callee_hdr.file_name)+1);
02338 strcpy (callee_filename, callee_hdr.file_name);
02339
02340 if (IPA_Enable_Inline && tmp_edge->Has_Inline_Attrib () &&
02341 !callee->Has_Noinline_Attrib()) {
02342 fprintf (orc_script, " INLINE (%d,%d,\"%s\",%s,NOREG) {\n }\n",
02343 callsite_linenum,callsite_colnum, callee_filename,
02344 DEMANGLE(IPA_Node_Name(callee)) );
02345 seen_callee = TRUE;
02346 } else {
02347
02348 fprintf (orc_script, " CALL (%d,%d,\"%s\",%s,NOREG)\n",
02349 callsite_linenum,callsite_colnum, callee_filename,
02350 DEMANGLE(IPA_Node_Name(callee)) );
02351 }
02352 }
02353 }
02354
02355 fprintf(orc_script, "}\n");
02356 }
02357 }
02358
02359 fprintf(orc_script, "\n#END_INLINE\n\n");
02360 fclose (orc_script);
02361 }