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 #define __STDC_LIMIT_MACROS
00060 #include <stdint.h>
00061 #include <stdio.h>
00062 #if defined(BUILD_OS_DARWIN)
00063 #include <darwin_elf.h>
00064 #else
00065 #include <elf.h>
00066 #endif
00067 #include <sys/elf_whirl.h>
00068 #include <cmplrs/host.h>
00069 #ifndef _LIGHTWEIGHT_INLINER
00070 #include <dem.h>
00071 #endif
00072 #define USE_STANDARD_TYPES // override unwanted defines in defs.h
00073 #include "defs.h"
00074
00075 #include "wn.h"
00076 #include "wn_map.h"
00077 #include "stab.h"
00078 #include "config.h"
00079 #include "config_ipa.h"
00080 #include "config_opt.h"
00081 #include "dwarf_DST_mem.h"
00082 #include "pu_info.h"
00083 #include "ir_bread.h"
00084 #include "ir_bwrite.h"
00085 #include "tracing.h"
00086 #include "glob.h"
00087 #include "ipo_tlog_utils.h"
00088 #include "erglob.h"
00089 #include "privatize_common.h"
00090
00091 #include "ip_graph.h"
00092 #include "ipc_file.h"
00093 #include "ipc_option.h"
00094 #include "ipc_symtab.h"
00095 #include "ipc_bread.h"
00096 #include "ipl_summary.h"
00097 #include "ipl_summarize.h"
00098 #include "inline_summarize.h"
00099 #include "ipa_cg.h"
00100
00101 #include "ipa_inline.h"
00102 #include "ipo_inline.h"
00103 #include "inline.h"
00104 #include "inline_utils.h"
00105 #include "ipc_symtab_merge.h"
00106 #include "ipa_nested_pu.h"
00107 #include "privatize_common.h"
00108 #include "inline_split_common.h"
00109 #ifdef KEY
00110 #include "ipo_inline_util.h"
00111 #include "ipa_trace.h"
00112 #endif
00113
00114 #include "mempool.h"
00115
00116 #ifdef IPA_DEBUG
00117 #include "ir_reader.h"
00118 #include "wn_simp.h"
00119 #endif
00120
00121 #include "timelib.h"
00122
00123
00124
00125
00126 #ifndef KEY
00127 #define BZERO(b, len) \
00128 bzero((void *)(b), (int)(len))
00129
00130 #endif
00131
00132 const UINT32 inliner_main_file_index = 0;
00133 SCOPE** Inliner_Aux_Pu_Table;
00134
00135 static MEM_POOL scope_mpool;
00136 static MEM_POOL inline_mpool;
00137
00138 static WN* pu;
00139 static BOOL is_cplusplus;
00140 #ifndef _LIGHTWEIGHT_INLINER
00141 static char dem_name[MAXDBUF];
00142 static char dem_name2[MAXDBUF];
00143 #endif
00144
00145 static int ITotal_Inlined = 0;
00146 static int ITotal_Not_Inlined = 0;
00147
00148 typedef enum phases
00149 {
00150 PHASE_INPUT = 0,
00151 PHASE_SUMMARIZE = 1,
00152 PHASE_ANALYZE = 2,
00153 PHASE_DFE = 3,
00154 PHASE_COMMON_SPLIT = 4,
00155 PHASE_OUTPUT = 5,
00156 PHASE_INLINING = 6,
00157 PHASE_CALL_GRAPH = 7,
00158 } PHASES;
00159
00160 #define LAST_PHASE 8
00161
00162 static double result_times[LAST_PHASE] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 };
00163
00164 MEM_POOL *PU_pool;
00165
00166 SUMMARY *Summary;
00167
00168 extern MEM_POOL Ipo_mem_pool;
00169 extern WN_MAP Parent_Map;
00170 extern BOOL Debug_On;
00171 extern BOOL Verbose;
00172 BOOL Trace_CopyProp = FALSE;
00173 BOOL Trace_Inline = FALSE;
00174 #ifdef _LIGHTWEIGHT_INLINER
00175 SCOPE* Orig_Scope_tab;
00176 #endif // _LIGHTWEIGHT_INLINER
00177
00178
00179 extern IP_FILE_HDR_TABLE IP_File_header;
00180
00181
00182 #ifdef _LIGHTWEIGHT_INLINER
00183 AUX_PU_TAB Aux_Pu_Table;
00184 #endif // _LIGHTWEIGHT_INLINER
00185
00186 static void
00187 Perform_inline (IPA_NODE* caller_node, IPA_NODE* callee_node,
00188 IPA_EDGE* edge);
00189 static void
00190 inline_init(IP_FILE_HDR& hdr);
00191
00192 DYN_ARRAY<char*>* Ipl_Symbol_Names = NULL;
00193 DYN_ARRAY<char*>* Ipl_Function_Names = NULL;
00194
00195 static void
00196 Read_PU(PU_Info *current_pu);
00197
00198 struct INLINE_COUNTER
00199 {
00200 UINT32 Num_Calls_Inlined;
00201
00202
00203
00204 UINT32 Num_Calls_Processed;
00205
00206
00207 };
00208
00209 typedef AUX_IPA_NODE<INLINE_COUNTER> INLINE_COUNTERS;
00210
00211 static INLINE_COUNTERS* inline_counters;
00212
00213 static void
00214 set_timer(void)
00215 {
00216 if (INLINE_Get_Time_Info) {
00217 clear_timer(1);
00218 start_timer(1);
00219 }
00220 }
00221
00222 static void
00223 get_timer(PHASES p)
00224 {
00225 if (INLINE_Get_Time_Info) {
00226 stop_timer(1);
00227 result_times[p] += get_timer_time(1);
00228 }
00229 }
00230
00231 static void
00232 time_summary(void)
00233 {
00234
00235 if (INLINE_Get_Time_Info) {
00236
00237 double total_result_times = 0.0;
00238 FILE* fp = stderr;
00239
00240 for (int i = 0; i < LAST_PHASE; ++i)
00241 total_result_times += result_times[i];
00242
00243 if (Trace_Inline)
00244 fp = TFile;
00245
00246 fprintf(fp, "Time summary information from the inliner:\n\n");
00247 fprintf(fp, " PHASES:\t\t\tabsolute time\n");
00248 fprintf(fp, " -------------------------------------\n");
00249 fprintf(fp, " INPUT\t\t\t\t%5.2fsec\n", result_times[PHASE_INPUT]);
00250 fprintf(fp, " SUMMARIZE\t\t\t%5.2fsec\n", result_times[PHASE_SUMMARIZE]);
00251 fprintf(fp, " ANALYZE\t\t\t%5.2fsec\n", result_times[PHASE_ANALYZE]);
00252 fprintf(fp, " DFE\t\t\t\t%5.2fsec\n", result_times[PHASE_DFE]);
00253 fprintf(fp, " COMMON_SPLIT\t\t\t%5.2fsec\n", result_times[PHASE_COMMON_SPLIT]);
00254 fprintf(fp, " OUTPUT\t\t\t%5.2fsec\n", result_times[PHASE_OUTPUT]);
00255 fprintf(fp, " INLINING\t\t\t%5.2fsec\n", result_times[PHASE_INLINING]);
00256 fprintf(fp, " CALL_GRAPH\t\t\t%5.2fsec\n", result_times[PHASE_CALL_GRAPH]);
00257 fprintf(fp, " ---------------------------------------------------------------\n");
00258 fprintf(fp, " Total time:\t\t\t%5.2fsec\n", total_result_times);
00259
00260 }
00261
00262 }
00263
00264 static void
00265 write_pu_info(PU_Info *pu)
00266 {
00267 set_timer();
00268
00269 Write_PU_Info (pu);
00270
00271 get_timer(PHASE_OUTPUT);
00272 }
00273
00274 static inline BOOL
00275 All_Calls_Processed (const IPA_NODE* node, const IPA_CALL_GRAPH* cg)
00276 {
00277
00278 UINT32 num_p = (*inline_counters)[node].Num_Calls_Processed;
00279
00280 return cg->Num_In_Edges (node) == num_p;
00281 }
00282
00283 static inline BOOL
00284 All_Calls_Inlined (const IPA_NODE* node, const IPA_CALL_GRAPH* cg)
00285 {
00286 INT num_edges = cg->Num_In_Edges (node);
00287 #ifdef _LIGHTWEIGHT_INLINER
00288 if (INLINE_Inlined_Pu_Call_Graph && (num_edges > 1)) {
00289 if (Pred_Is_Root(node))
00290 num_edges -= 1;
00291 }
00292 #endif // _LIGHTWEIGHT_INLINER
00293 UINT32 num_i = (*inline_counters)[node].Num_Calls_Inlined;
00294 return num_edges == num_i;
00295 }
00296
00297
00298
00299
00300
00301 static void
00302 IP_local_inline(SUMMARY* summary, BOOL compute_summary)
00303 {
00304 Summary = summary;
00305 Trace_Inline = Get_Trace ( TP_INLINE, 2 );
00306
00307 #ifndef _LIGHTWEIGHT_INLINER
00308
00309 if (INLINE_Enable_Copy_Prop) {
00310 Trace_CopyProp = Get_Trace ( TP_INLINE, 1 );
00311
00312 if (Trace_CopyProp) {
00313 demangle(ST_name(WN_st(pu)),dem_name);
00314 fprintf (TFile, "\nComputing summary info for function: %s \n",dem_name);
00315 }
00316 }
00317 #endif // _LIGHTWEIGHT_INLINER
00318
00319 Init_Aux_Symbol_Info (CURRENT_SYMTAB);
00320 Recompute_Addr_Taken (pu, Summary);
00321 if (compute_summary) {
00322
00323 set_timer();
00324
00325 Summary->Process_procedure (pu);
00326
00327 get_timer(PHASE_SUMMARIZE);
00328
00329 }
00330 }
00331
00332
00333
00334
00335
00336
00337 static BOOL
00338 Is_do_inline (EDGE_INDEX ed, IPA_EDGE_INDEX ipa_ed)
00339 {
00340
00341 IPA_NODE& callee = *(IPA_Call_Graph->Callee(ed));
00342 IPA_NODE& caller = *(IPA_Call_Graph->Caller(ed));
00343 IPA_EDGE& edge = *(IPA_Call_Graph->Edge(ipa_ed));
00344
00345 if (&caller == &callee)
00346 return FALSE;
00347
00348 if (callee.Has_Varargs ())
00349 return FALSE;
00350
00351 if (IPA_Call_Graph->Graph()->Is_Recursive_Edge (edge.Edge_Index ()))
00352 return FALSE;
00353
00354 #ifndef _LIGHTWEIGHT_INLINER
00355 if (!edge.Has_Noinline_Attrib() &&
00356 (edge.Has_Must_Inline_Attrib() || edge.Has_Inline_Attrib())) {
00357 #else // _LIGHTWEIGHT_INLINER
00358 if (!edge.Has_Noinline_Attrib() &&
00359 (edge.Has_Must_Inline_Attrib() || edge.Has_Inline_Attrib() ||
00360 callee.Has_Must_Inline_Attrib() || callee.Has_Inline_Attrib())) {
00361 #endif // _LIGHTWEIGHT_INLINER
00362
00363 if ( INLINE_List_Actions ) {
00364 #ifndef _LIGHTWEIGHT_INLINER
00365 if (callee.Summary_Proc()->Get_lang() == LANG_CPLUS) {
00366 demangle (callee.Name(), dem_name);
00367 demangle(caller.Name(), dem_name2);
00368 fprintf ( stderr, "Inlining %s into %s (edge# %d)\n",
00369 dem_name, dem_name2, ed );
00370 if ( Tracing_Enabled ) {
00371 fprintf ( TFile, "%s inlined into %s:",
00372 dem_name, dem_name2 );
00373 fflush ( TFile );
00374 }
00375 }
00376 else {
00377 fprintf ( stderr, "Inlining %s into %s (edge# %d)\n",
00378 callee.Name(), caller.Name(), ed );
00379 }
00380 #else
00381 fprintf ( stderr, "Inlining %s into %s (edge# %d)\n",
00382 callee.Name(), caller.Name(), ed );
00383 #endif
00384 }
00385 if ( Tracing_Enabled ) {
00386 fprintf ( TFile, "%s inlined into %s:",
00387 callee.Name(), caller.Name() );
00388 fflush ( TFile );
00389 }
00390
00391 return TRUE;
00392 }
00393 return FALSE;
00394 }
00395
00396
00397
00398
00399
00400
00401
00402 static void
00403 Write_inline_pu(IPA_NODE* node)
00404 {
00405 Current_Map_Tab = PU_Info_maptab(node->PU_Info());
00406
00407 if (!node->Is_Deletable ()) {
00408 Scope_tab = node->Scope();
00409 #ifdef Is_True
00410 CURRENT_SYMTAB = node->Lexical_Level();
00411 WN_verifier(node->Whirl_Tree());
00412 #endif
00413
00414 write_pu_info (node->PU_Info());
00415
00416 }
00417 node->Set_Processed();
00418 #ifdef _LIGHTWEIGHT_INLINER
00419 if (INLINE_Use_Malloc_Mempool && INLINE_Free_Malloc_Mempool)
00420 node->Free_inlined_list();
00421 #endif // _LIGHTWEIGHT_INLINER
00422
00423 Parent_Map = node->Parent_Map();
00424 MEM_POOL_Pop(node->Mem_Pool());
00425 MEM_POOL_Delete(node->Mem_Pool());
00426
00427 }
00428
00429 static void
00430 Write_inline_succ_pu()
00431 {
00432 IPA_NODE_ITER cg_iter (POSTORDER, Malloc_Mem_Pool);
00433
00434 for (cg_iter.First (); !cg_iter.Is_Empty(); cg_iter.Next ()) {
00435 IPA_NODE* node = cg_iter.Current ();
00436
00437 if (node && !node->Is_Non_Local() && !node->Is_Processed ())
00438 Write_inline_pu (node);
00439 }
00440 }
00441
00442 static void
00443 Write_callee(IPA_NODE* callee, BOOL non_local, BOOL inline_performed)
00444 {
00445 if (All_Calls_Processed (callee, IPA_Call_Graph)) {
00446 if (IPA_Enable_DFE
00447 #ifdef KEY
00448 && OPT_Cyg_Instrument == 0
00449 #endif
00450 && All_Calls_Inlined (callee, IPA_Call_Graph)
00451 && !callee->Is_Externally_Callable ()
00452 #ifdef KEY
00453 && ! PU_no_delete(Pu_Table[ST_pu(callee->Func_ST())])
00454 #endif
00455 ) {
00456 callee->Set_Deletable();
00457
00458 Set_ST_is_not_used(callee->Func_ST());
00459 }
00460
00461 #ifndef _LIGHTWEIGHT_INLINER
00462 if (non_local) {
00463 callee->Set_Deletable();
00464 Set_ST_sclass(callee->Func_ST(), SCLASS_EXTERN);
00465 if (inline_performed)
00466 Set_ST_is_not_used(callee->Func_ST());
00467 }
00468
00469 #endif // _LIGHTWEIGHT_INLINER
00470
00471 if (!INLINE_Keep_PU_Order || callee->Is_Deletable())
00472
00473
00474
00475 Write_inline_pu(callee);
00476
00477 }
00478 }
00479
00480 static void
00481 Write_caller(IPA_NODE* node)
00482 {
00483 if (!INLINE_Keep_PU_Order) {
00484 if (All_Calls_Processed (node, IPA_Call_Graph))
00485 Write_inline_pu(node);
00486 }
00487 }
00488
00489 static void
00490 Inline_callees_into_caller(IPA_NODE* caller)
00491 {
00492 caller->Scope ();
00493
00494 IPA_SUCC_ITER succ_iter (caller->Node_Index());
00495
00496
00497 for (succ_iter.First(); !succ_iter.Is_Empty(); succ_iter.Next()) {
00498
00499 set_timer();
00500
00501 IPA_EDGE* e = succ_iter.Current_Edge();
00502 EDGE_INDEX call = e->Edge_Index();
00503
00504 e->Set_Whirl_Node(e->Summary_Callsite()->Get_wn());
00505
00506 IPA_NODE* callee = IPA_Call_Graph->Callee(call);
00507
00508 Current_Map_Tab = PU_Info_maptab(caller->PU_Info());
00509 #ifdef KEY
00510
00511
00512 Get_enclosing_region (caller, e);
00513 #endif
00514
00515 BOOL inline_performed = FALSE;
00516 if (Is_do_inline(call, e->Array_Index()) && !caller->Is_Deletable()) {
00517
00518 MEM_POOL_Popper pool (&Ipo_mem_pool);
00519 if ( Get_Trace ( TKIND_ALLOC, TP_IPA ) ) {
00520 fprintf ( TFile,
00521 "\n%s%s\tMemory allocation information before inlining\n%s%s\n",
00522 DBar, DBar, DBar, DBar );
00523 MEM_Trace ();
00524 }
00525
00526 callee->Scope ();
00527
00528 Perform_inline(caller, callee, e);
00529
00530 if ( Get_Trace ( TKIND_ALLOC, TP_IPA ) ) {
00531 fprintf ( TFile,
00532 "\n%s%s\tMemory allocation information "
00533 "after inlining\n%s%s\n",
00534 DBar, DBar, DBar, DBar );
00535
00536 MEM_Trace ();
00537 }
00538
00539 ++((*inline_counters)[callee].Num_Calls_Inlined);
00540
00541 if (Verbose) {
00542 fprintf (stderr, " %s [i] ", callee->Name());
00543 #ifdef TRACE_CALL_GRAPH
00544 fprintf (stderr, " icnt[%d, 0x%x] ", (*inline_counters)[callee].Num_Calls_Inlined, &((*inline_counters)[callee].Num_Calls_Inlined));
00545 #endif // TRACE_CALL_GRAPH
00546 if (callee->Is_Deletable())
00547 fputs ("[d] ", stderr);
00548 fputs("\n", stderr);
00549 fflush (stderr);
00550 }
00551 ITotal_Inlined++;
00552 inline_performed = TRUE;
00553 }
00554 else
00555 ITotal_Not_Inlined++;
00556
00557 ++((*inline_counters)[callee].Num_Calls_Processed);
00558
00559 get_timer(PHASE_INLINING);
00560
00561 #ifdef Is_True_On
00562 Scope_tab = callee->Scope();
00563 Verify_SYMTAB (callee->Lexical_Level());
00564 #endif
00565
00566 #ifdef _LIGHTWEIGHT_INLINER
00567 if (!INLINE_Inlined_Pu_Call_Graph)
00568 #endif // _LIGHTWEIGHT_INLINER
00569 Write_callee(callee, (&caller->File_Header() != &callee->File_Header()), inline_performed);
00570
00571 }
00572
00573 IPA_SUCC_ITER succ_iter2 (caller->Node_Index());
00574
00575 for (succ_iter2.First(); !succ_iter2.Is_Empty(); succ_iter2.Next()) {
00576
00577 IPA_EDGE* edge = succ_iter2.Current_Edge();
00578 IPA_NODE* callee = IPA_Call_Graph->Callee(edge);
00579
00580 callee->Clear_Cloned_Symtab();
00581 }
00582
00583 #ifdef Is_True_On
00584 Scope_tab = caller->Scope();
00585 Verify_SYMTAB (GLOBAL_SYMTAB);
00586 Verify_SYMTAB (caller->Lexical_Level());
00587 #endif
00588
00589 #ifdef _LIGHTWEIGHT_INLINER
00590 if (!INLINE_Inlined_Pu_Call_Graph)
00591 #endif // _LIGHTWEIGHT_INLINER
00592 Write_caller(caller);
00593
00594 }
00595
00596
00597 static void
00598 Perform_inlining()
00599 {
00600
00601 Init_inline();
00602
00603 IPA_NODE_ITER cg_iter (POSTORDER, Malloc_Mem_Pool);
00604
00605 MEM_POOL_Constructor ipo_pool (&Ipo_mem_pool, "Ipo_mem_pool", 0);
00606
00607 if (INLINE_Enable_Auto_Inlining) {
00608 MEM_POOL_Constructor pool (&inline_mpool, "inline_mpool", TRUE);
00609
00610 set_timer();
00611
00612 Perform_Inline_Analysis(IPA_Call_Graph, &inline_mpool);
00613
00614 get_timer(PHASE_ANALYZE);
00615
00616 inline_counters = CXX_NEW (INLINE_COUNTERS (IPA_Call_Graph, &Ipo_mem_pool),
00617 &Ipo_mem_pool);
00618
00619 }
00620 else if (INLINE_Inlined_Pu_Call_Graph)
00621 inline_counters = CXX_NEW (INLINE_COUNTERS (IPA_Call_Graph, Malloc_Mem_Pool),
00622 Malloc_Mem_Pool);
00623 else
00624 inline_counters = CXX_NEW (INLINE_COUNTERS (IPA_Call_Graph, &Ipo_mem_pool),
00625 &Ipo_mem_pool);
00626
00627
00628 for (cg_iter.First (); !cg_iter.Is_Empty(); cg_iter.Next ()) {
00629
00630 IPA_NODE* caller = cg_iter.Current ();
00631
00632 if (caller == NULL) {
00633 if ( ! INLINE_Keep_PU_Order )
00634 #ifdef _LIGHTWEIGHT_INLINER
00635 if (!INLINE_Inlined_Pu_Call_Graph)
00636 #endif // _LIGHTWEIGHT_INLINER
00637 Write_inline_succ_pu();
00638 } else {
00639 Inline_callees_into_caller(caller);
00640 #ifdef DEBUG_SYMTAB
00641 Scope_tab = caller->Scope();
00642 Print_local_symtab(TFile, Scope_tab[caller->Lexical_Level()]);
00643 fflush(TFile);
00644 #endif // DEBUG_SYMTAB
00645 }
00646 }
00647
00648 if (Verbose)
00649 fputc ('\n', stderr);
00650
00651 if ( INLINE_List_Actions ) {
00652 fprintf ( stderr, "Total number of edges = %d\n", IPA_Call_Graph->Edge_Size() );
00653 }
00654
00655 }
00656
00657
00658
00659
00660
00661
00662
00663
00664 static void
00665 Perform_inline (IPA_NODE* caller_node, IPA_NODE* callee_node,
00666 IPA_EDGE* edge)
00667 {
00668
00669 IPO_INLINE ip_inline(caller_node, callee_node, edge);
00670
00671 ip_inline.Process();
00672 }
00673
00674
00675
00676 static INT
00677 Inliner_Read_PUs (IP_FILE_HDR& file_header, PU_Info *pu_tree, INT num_PU)
00678 {
00679 PU_Info *current_pu;
00680
00681 MEM_POOL rename_pool;
00682 MEM_POOL_Initialize(&rename_pool, "Rename_Pool", TRUE);
00683
00684 for (current_pu = pu_tree;
00685 current_pu != NULL;
00686 current_pu = PU_Info_next (current_pu)) {
00687
00688 IP_PROC_INFO *proci = &(IP_FILE_HDR_proc_info(file_header)[num_PU]);
00689 Set_IP_PROC_INFO_pu_info(*proci, current_pu);
00690 Set_IP_PROC_INFO_state(*proci, IPA_ORIG);
00691
00692 #ifdef _LIGHTWEIGHT_INLINER
00693 if (INLINE_Inlined_Pu_Call_Graph && !PU_Info_child(current_pu)) {
00694
00695
00696
00697
00698 const PU& this_pu = Pu_Table[ST_pu(St_Table[PU_Info_proc_sym(current_pu)])];
00699 if (!PU_is_inline_function(this_pu)) {
00700 #ifdef TRACE_CALL_GRAPH
00701 printf ("NO inline tag ----------- %s\n", ST_name(PU_Info_proc_sym(current_pu)));
00702 #endif // TRACE_CALL_GRAPH
00703 continue;
00704 }
00705 #ifdef TRACE_CALL_GRAPH
00706 printf ("HAS inline tag ----------- %s\n", ST_name(PU_Info_proc_sym(current_pu)));
00707 #endif // TRACE_CALL_GRAPH
00708 }
00709 #endif // _LIGHTWEIGHT_INLINER
00710
00711 Read_PU (current_pu);
00712
00713 pu = PU_Info_tree_ptr(current_pu);
00714
00715 #ifdef _LIGHTWEIGHT_INLINER
00716
00717 if (INLINE_Inlined_Pu_Call_Graph2 && !PU_Info_child(current_pu)) {
00718
00719
00720
00721 const PU& this_pu = Pu_Table[ST_pu(St_Table[PU_Info_proc_sym(current_pu)])];
00722
00723 if (!Need_To_Inline_Callee(pu) && !PU_is_inline_function(this_pu)) {
00724 IP_local_inline ((SUMMARY *)IP_FILE_HDR_summary(file_header), FALSE);
00725 write_pu_info (current_pu);
00726
00727 continue;
00728 }
00729 #ifdef TRACE_CALL_GRAPH
00730 else
00731 printf ("HAS inline tag or HAS call to inline function ----------- %s\n", ST_name(PU_Info_proc_sym(current_pu)));
00732 #endif // TRACE_CALL_GRAPH
00733 }
00734
00735 #endif // _LIGHTWEIGHT_INLINER
00736
00737
00738
00739
00740 Current_PU_Info = current_pu;
00741
00742
00743 const PU& this_pu = Get_Current_PU ();
00744 if (PU_has_mp(this_pu)) {
00745 MEM_POOL_Push(&rename_pool);
00746 RENAMING_STACK rename_common_stack(&rename_pool);
00747 rename_common_stack.Push(new RENAMING_SCOPE(NULL, &rename_pool));
00748
00749 Rename_Privatized_COMMON(pu, &rename_common_stack);
00750 MEM_POOL_Pop(&rename_pool);
00751 }
00752
00753
00754 SCOPE *new_scope_tab = (SCOPE *) MEM_POOL_Alloc (Malloc_Mem_Pool,
00755 (CURRENT_SYMTAB+1) * sizeof(SCOPE));
00756
00757 SYMTAB_IDX i;
00758 for (i = 0; i <= CURRENT_SYMTAB; ++i) {
00759 new_scope_tab[i] = Scope_tab[i];
00760 }
00761
00762 Inliner_Aux_Pu_Table[ST_pu(St_Table[PU_Info_proc_sym(current_pu)])] = new_scope_tab;
00763
00764 IP_local_inline ((SUMMARY *)IP_FILE_HDR_summary(file_header), TRUE);
00765
00766 num_PU += 1;
00767
00768 if (PU_Info_child(current_pu)) {
00769 num_PU = Inliner_Read_PUs(file_header, PU_Info_child(current_pu), num_PU);
00770 Set_IP_FILE_HDR_has_nested_pu(file_header);
00771 }
00772
00773 if ((current_pu) && (PU_Info_state (current_pu, WT_FREQ) == Subsect_InMem))
00774 ErrMsg( EC_FB_File_Fmt, "Standalone Inliner", "Use -IPA with feedback files");
00775
00776
00777 }
00778 return num_PU;
00779 }
00780
00781
00782 static PU_Info *
00783 Inliner_Write_PUs (PU_Info *pu_tree, INT *p_num_PU)
00784 {
00785 PU_Info *current_pu;
00786 PU_Info *prev_pu = NULL;
00787
00788 for (current_pu = pu_tree; current_pu != NULL; current_pu = PU_Info_next (current_pu)) {
00789
00790 Current_Map_Tab = PU_Info_maptab(current_pu);
00791
00792 BOOL deletable = FALSE;
00793 IPA_NODE* node = NULL;
00794 NODE_INDEX cg_node =
00795 AUX_PU_node (Aux_Pu_Table[ST_pu (St_Table[PU_Info_proc_sym(current_pu)])]);
00796 if (cg_node != INVALID_NODE_INDEX)
00797 node = (IPA_Call_Graph->Graph()->Node_User(cg_node));
00798
00799 if (node) {
00800 #ifdef _LIGHTWEIGHT_INLINER
00801 const PU& this_pu = Pu_Table[ST_pu(St_Table[PU_Info_proc_sym(current_pu)])];
00802 if ((INLINE_Inlined_Pu_Call_Graph || INLINE_Inlined_Pu_Call_Graph) && PU_is_inline_function(this_pu))
00803 #endif // _LIGHTWEIGHT_INLINER
00804 {
00805 if (IPA_Enable_DFE
00806 #ifdef KEY
00807 && ! OPT_Cyg_Instrument
00808 #endif
00809 && All_Calls_Inlined (node, IPA_Call_Graph)
00810 && !node->Is_Externally_Callable ()
00811 #ifdef KEY
00812 && ! PU_no_delete(Pu_Table[ST_pu(node->Func_ST())])
00813 #endif
00814 ) {
00815
00816 node->Set_Deletable();
00817
00818 Set_ST_is_not_used(node->Func_ST());
00819 }
00820 }
00821 deletable = node->Is_Deletable();
00822 }
00823
00824
00825 if (IPA_Enable_DFE && deletable) {
00826 if (prev_pu) {
00827 PU_Info_next(prev_pu) = PU_Info_next(current_pu);
00828 }
00829 else {
00830 pu_tree = PU_Info_next(current_pu);
00831 }
00832 }
00833 else {
00834
00835
00836
00837 #ifdef _LIGHTWEIGHT_INLINER
00838 if (INLINE_Inlined_Pu_Call_Graph && node) {
00839 Scope_tab = node->Scope();
00840 write_pu_info (current_pu);
00841 }
00842 else {
00843 if ( INLINE_Keep_PU_Order && node ) {
00844 Scope_tab = node->Scope();
00845 write_pu_info (current_pu);
00846 }
00847 }
00848 #else // _LIGHTWEIGHT_INLINER
00849 if ( INLINE_Keep_PU_Order )
00850 write_pu_info (current_pu);
00851 #endif // _LIGHTWEIGHT_INLINER
00852
00853 prev_pu = current_pu;
00854 }
00855
00856 if (PU_Info_child(current_pu)) {
00857 PU_Info_child(current_pu) =
00858 Inliner_Write_PUs(PU_Info_child(current_pu), p_num_PU);
00859 }
00860 *p_num_PU += 1;
00861 }
00862
00863 return pu_tree;
00864 }
00865
00866 #ifdef _LIGHTWEIGHT_INLINER
00867
00868 static void
00869 Process_Uninlinable_PU (const IP_FILE_HDR& file_header, PU_Info *current_pu, int& num_PU)
00870 {
00871
00872 Read_PU (current_pu);
00873
00874 pu = PU_Info_tree_ptr(current_pu);
00875
00876 if (num_PU == 0 || !Need_To_Inline_Callee(pu)) {
00877 IP_local_inline ((SUMMARY *)IP_FILE_HDR_summary(file_header), FALSE);
00878 write_pu_info (current_pu);
00879 }
00880 else {
00881
00882 IP_PROC_INFO *proci = &(IP_FILE_HDR_proc_info(file_header)[num_PU]);
00883 Set_IP_PROC_INFO_pu_info(*proci, current_pu);
00884 Set_IP_PROC_INFO_state(*proci, IPA_ORIG);
00885
00886
00887 Current_PU_Info = current_pu;
00888
00889 SCOPE *new_scope_tab = (SCOPE *) MEM_POOL_Alloc (Malloc_Mem_Pool,
00890 (CURRENT_SYMTAB+1) * sizeof(SCOPE));
00891
00892 SYMTAB_IDX i;
00893 for (i = 0; i <= CURRENT_SYMTAB; ++i) {
00894 new_scope_tab[i] = Scope_tab[i];
00895 }
00896
00897 Inliner_Aux_Pu_Table[ST_pu(St_Table[PU_Info_proc_sym(current_pu)])] = new_scope_tab;
00898
00899 IP_local_inline ((SUMMARY *)IP_FILE_HDR_summary(file_header), TRUE);
00900
00901 INT proc_idx = ((SUMMARY *)IP_FILE_HDR_summary(file_header))->Get_procedure_idx();
00902
00903
00904 NODE_INDEX index = INVALID_NODE_INDEX;
00905 IPA_NODE* caller = Add_One_Node((IP_FILE_HDR&)file_header, inliner_main_file_index, proc_idx, index);
00906
00907 Add_Edges_For_Node((IP_FILE_HDR&)file_header, num_PU, NULL, NULL);
00908
00909
00910 Inline_callees_into_caller(caller);
00911
00912 #ifdef DEBUG_SYMTAB
00913 Scope_tab = caller->Scope();
00914 Print_local_symtab(TFile, Scope_tab[caller->Lexical_Level()]);
00915 fflush(TFile);
00916 #endif // DEBUG_SYMTAB
00917
00918
00919 num_PU += 1;
00920 }
00921
00922 }
00923
00924
00925
00926
00927
00928
00929
00930 static PU_Info *
00931 Process_Remaining_PUs (const IP_FILE_HDR& file_header, PU_Info *pu_tree, int& num_PU)
00932 {
00933 PU_Info *current_pu;
00934
00935 for (current_pu = pu_tree; current_pu != NULL; current_pu = PU_Info_next (current_pu)) {
00936 Current_Map_Tab = PU_Info_maptab(current_pu);
00937 const PU& this_pu = Pu_Table[ST_pu(St_Table[PU_Info_proc_sym(current_pu)])];
00938 NODE_INDEX cg_node =
00939 AUX_PU_node (Aux_Pu_Table[ST_pu (St_Table[PU_Info_proc_sym(current_pu)])]);
00940 if (cg_node == INVALID_NODE_INDEX) {
00941
00942
00943 Process_Uninlinable_PU(file_header, current_pu, num_PU);
00944 }
00945
00946 if (PU_Info_child(current_pu)) {
00947 PU_Info_child(current_pu) =
00948 Process_Remaining_PUs(file_header, PU_Info_child(current_pu), num_PU);
00949 }
00950 }
00951
00952 return pu_tree;
00953 }
00954
00955 #else // _LIGHTWEIGHT_INLINER
00956
00957
00958
00959
00960 void
00961 Process_Nonlocal_File(char* input_name, void* handle)
00962 {
00963 PU_Info *pu_tree;
00964 INT32 PU_count, num_PU;
00965
00966 if (handle == NULL)
00967 handle = Open_Input_Info (input_name);
00968
00969
00970 IP_FILE_HDR& file_header = Setup_Inliner_File_Header (input_name, (char *)handle);
00971
00972 const MEM_POOL* mpool = IP_FILE_HDR_mem_pool(file_header);
00973 MEM_POOL_Push((MEM_POOL *)(mpool));
00974
00975 Process_Global_Symtab (handle, file_header);
00976 IP_READ_pu_infos(file_header);
00977 IPA_update_summary_st_idx(file_header);
00978 }
00979
00980 #endif // _LIGHTWEIGHT_INLINER
00981
00982
00983
00984
00985 static void
00986 Process_Local_File(char* input_name, void *handle, INT& num_PU)
00987 {
00988 PU_Info *pu_tree;
00989 INT32 PU_count;
00990
00991 if (handle == NULL)
00992 handle = Open_Input_Info (input_name);
00993
00994
00995 IP_FILE_HDR& file_header = Setup_Inliner_File_Header (input_name, (char *)handle);
00996
00997 const MEM_POOL* mpool = IP_FILE_HDR_mem_pool(file_header);
00998 MEM_POOL_Push((MEM_POOL *)(mpool));
00999
01000 pu_tree = Read_Global_Info (&PU_count);
01001 inline_init(file_header);
01002
01003 Initialize_Special_Global_Symbols ();
01004
01005 #ifdef _LIGHTWEIGHT_INLINER
01006
01007 const AUX_PU aux_pu;
01008 Aux_Pu_Table.Insert (aux_pu);
01009
01010 #else // _LIGHTWEIGHT_INLINER
01011
01012 Initialize_Auxiliary_Tables();
01013
01014 #endif // _LIGHTWEIGHT_INLINER
01015
01016 Set_IP_FILE_HDR_pu_list(file_header, pu_tree);
01017 Set_IP_FILE_HDR_num_procs(file_header, PU_count);
01018
01019 INT size_proc = 0;
01020 if (PU_count != 0) {
01021
01022 size_proc = PU_count < 32 ? PU_count + 8 : PU_count + PU_count / 4;
01023 }
01024
01025 Set_IP_FILE_HDR_proc_info(file_header,
01026 (IP_PROC_INFO*) MEM_POOL_Alloc (Malloc_Mem_Pool, (sizeof(IP_PROC_INFO)*size_proc)));
01027 Set_IP_FILE_HDR_max_size (file_header, size_proc);
01028
01029 Set_IP_FILE_HDR_dst(file_header, Current_DST);
01030
01031 UINT size = sizeof(SCOPE*) * PU_Table_Size ();
01032
01033 if (!Inliner_Aux_Pu_Table)
01034 Inliner_Aux_Pu_Table = (SCOPE**) MEM_POOL_Alloc (&scope_mpool, size);
01035 else
01036 Inliner_Aux_Pu_Table = (SCOPE**) MEM_POOL_Realloc (&scope_mpool, Inliner_Aux_Pu_Table, size, size*2);
01037
01038 num_PU = Inliner_Read_PUs(file_header, pu_tree, 0);
01039
01040 ((SUMMARY *)IP_FILE_HDR_summary(file_header))->Set_global_addr_taken_attrib ();
01041
01042 Set_IP_FILE_HDR_file_info(file_header, File_info);
01043
01044 UINT32 aux_idx;
01045 for (INT i = 1; i < PU_Table_Size (); ++i) {
01046 AUX_PU& aux_pu = Aux_Pu_Table.New_entry (aux_idx);
01047 aux_pu.construct();
01048 }
01049
01050 }
01051
01052
01053
01054
01055
01056 BOOL
01057 Inliner(char* input_name, char* output_name)
01058 {
01059 void *handle;
01060 PU_Info *pu_tree;
01061 INT32 PU_count, num_PU;
01062
01063 MEM_POOL_Push(&MEM_src_pool);
01064 MEM_POOL_Push(&MEM_pu_pool);
01065 MEM_POOL_Push(&MEM_local_pool);
01066
01067
01068 Initialize_Symbol_Tables(FALSE);
01069
01070 New_Scope (GLOBAL_SYMTAB, Malloc_Mem_Pool, FALSE);
01071
01072 MEM_POOL_Initialize(&scope_mpool, "scope_mpool", TRUE);
01073 MEM_POOL_Push(&scope_mpool);
01074
01075 #ifdef _LIGHTWEIGHT_INLINER
01076 Orig_Scope_tab = Scope_tab;
01077
01078 if (!INLINE_Inlined_Pu_Call_Graph)
01079 #endif // _LIGHTWEIGHT_INLINER
01080 (void) Open_Output_Info (output_name);
01081
01082 Process_Local_File(input_name, NULL, num_PU);
01083
01084 #ifndef _LIGHTWEIGHT_INLINER
01085
01086 Process_Non_Local_Files();
01087
01088 Process_Non_Local_Libraries();
01089
01090 if (INLINE_Enable_Split_Common) {
01091 set_timer();
01092
01093 INLINE_Split_Common ();
01094
01095 get_timer(PHASE_COMMON_SPLIT);
01096 }
01097
01098 #else // _LIGHTWEIGHT_INLINER
01099 if (INLINE_Inlined_Pu_Call_Graph && (num_PU == 0)) {
01100
01101 Free_Input_Info ();
01102
01103 set_timer();
01104
01105 Copy_Input_Info_To_Output(input_name, output_name);
01106
01107 get_timer(PHASE_OUTPUT);
01108
01109 time_summary();
01110
01111 return FALSE;
01112 }
01113
01114 if (INLINE_Inlined_Pu_Call_Graph)
01115 (void) Open_Output_Info (output_name);
01116
01117 INLINE_Enable_Copy_Prop = FALSE;
01118
01119 #endif // _LIGHTWEIGHT_INLINER
01120
01121
01122 Fix_Aliased_Commons ();
01123
01124
01125 #ifdef IPA_DEBUG
01126 if (!Verbose)
01127 WN_Simplifier_Enable(FALSE);
01128 #endif
01129
01130 Set_ipa_tlog_phase(PHASE_INLINER);
01131
01132 set_timer();
01133
01134 Build_Call_Graph();
01135
01136 if (Get_Trace (TP_INLINE, IPA_TRACE_TUNING))
01137 {
01138 FILE *tmp_call_graph = fopen("cg_dump.log", "w");
01139
01140 if(tmp_call_graph != NULL)
01141 {
01142 fprintf(tmp_call_graph, "\t+++++++++++++++++++++++++++++++++++++++\n");
01143 IPA_Call_Graph->Print(tmp_call_graph);
01144 fprintf(tmp_call_graph, "\t+++++++++++++++++++++++++++++++++++++++\n");
01145 }
01146 fclose(tmp_call_graph);
01147 }
01148
01149 get_timer(PHASE_CALL_GRAPH);
01150
01151 #ifdef _LIGHTWEIGHT_INLINER
01152 if (!(INLINE_Inlined_Pu_Call_Graph || INLINE_Inlined_Pu_Call_Graph2))
01153 #endif // _LIGHTWEIGHT_INLINER
01154 {
01155 MEM_POOL_Pop(&scope_mpool);
01156 MEM_POOL_Delete(&scope_mpool);
01157 }
01158
01159 #ifdef TRACE_CALL_GRAPH
01160
01161 FILE* f;
01162 f = fopen("/usr/tmp/call.graph", "a+");
01163 if (IPA_Call_Graph)
01164 IPA_Call_Graph->Print(f);
01165 fclose(f);
01166 #endif
01167
01168 for (UINT i = 0; i < IP_File_header.size(); ++i) {
01169 if (IP_FILE_HDR_has_nested_pu(IP_File_header[i])) {
01170 Build_Nested_Pu_Relations();
01171 break;
01172 }
01173 }
01174
01175 if ( Get_Trace ( TKIND_ALLOC, TP_IPA ) ) {
01176 fprintf ( TFile,
01177 "\n%s%s\tMemory allocation information after Build_call_graph\n%s%s\n",
01178 DBar, DBar, DBar, DBar );
01179 MEM_Trace ();
01180 }
01181
01182 Total_Prog_Size = Orig_Prog_Weight;
01183 if (Trace_Inline)
01184 fprintf(TFile, "\nTotal Prog Size is %d\n",Total_Prog_Size);
01185
01186 if (IPA_Enable_DFE) {
01187 #ifdef _LIGHTWEIGHT_INLINER
01188 if (!(INLINE_Inlined_Pu_Call_Graph || INLINE_Inlined_Pu_Call_Graph2))
01189 #endif // _LIGHTWEIGHT_INLINER
01190 {
01191 set_timer();
01192
01193 Total_Prog_Size = Orig_Prog_Weight - Eliminate_Dead_Func(FALSE);
01194
01195 get_timer(PHASE_DFE);
01196
01197 }
01198 }
01199
01200 #ifdef TRACE_CALL_GRAPH
01201
01202 f = fopen("/usr/tmp/call.graph2", "a+");
01203 if (IPA_Call_Graph)
01204 IPA_Call_Graph->Print(f);
01205 fclose(f);
01206 #endif
01207
01208 Perform_inlining();
01209
01210 #ifdef _LIGHTWEIGHT_INLINER
01211 if (INLINE_Inlined_Pu_Call_Graph || INLINE_Inlined_Pu_Call_Graph2) {
01212
01213
01214
01215 if (INLINE_Inlined_Pu_Call_Graph) {
01216 (void)Process_Remaining_PUs(IP_File_header[inliner_main_file_index], IP_FILE_HDR_pu_list(IP_File_header[inliner_main_file_index]), num_PU);
01217
01218 ((SUMMARY *)IP_FILE_HDR_summary(IP_File_header[inliner_main_file_index]))->Set_global_addr_taken_attrib ();
01219 }
01220
01221 MEM_POOL_Pop(&scope_mpool);
01222 MEM_POOL_Delete(&scope_mpool);
01223 }
01224
01225 #endif // _LIGHTWEIGHT_INLINER
01226
01227 Current_DST = IP_FILE_HDR_dst(IP_File_header[inliner_main_file_index]);
01228 num_PU = 0;
01229 pu_tree = Inliner_Write_PUs(IP_FILE_HDR_pu_list(IP_File_header[inliner_main_file_index]), &num_PU);
01230
01231 set_timer();
01232
01233 Write_Global_Info(pu_tree);
01234
01235 get_timer(PHASE_OUTPUT);
01236
01237 Free_Input_Info ();
01238
01239 time_summary();
01240
01241 return TRUE;
01242 }
01243
01244
01245
01246
01247 static void
01248 Read_PU(PU_Info *current_pu)
01249 {
01250 MEM_POOL *m;
01251
01252
01253 m = (MEM_POOL*) MEM_POOL_Alloc(Malloc_Mem_Pool, sizeof(MEM_POOL));
01254 MEM_POOL_Initialize (m, NULL, 1);
01255 MEM_POOL_Push (m);
01256
01257 #ifdef _LIGHTWEIGHT_INLINER
01258 Scope_tab = Orig_Scope_tab;
01259 #endif // _LIGHTWEIGHT_INLINER
01260
01261 set_timer();
01262
01263 Read_Local_Info (m, current_pu);
01264
01265 get_timer(PHASE_INPUT);
01266
01267 PU_pool = m;
01268 }
01269
01270
01271
01272
01273 static void inline_init(IP_FILE_HDR& hdr)
01274 {
01275 SUMMARY *summary;
01276 summary = CXX_NEW (SUMMARY(Malloc_Mem_Pool), Malloc_Mem_Pool);
01277
01278 Set_IP_FILE_HDR_summary(hdr, (char *)summary);
01279 }
01280
01281
01282