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 #define __STDC_LIMIT_MACROS
00057 #include <stdint.h>
00058 #include <alloca.h>
00059 #if defined(BUILD_OS_DARWIN)
00060 #include <darwin_elf.h>
00061 #else
00062 #include <elf.h>
00063 #endif
00064 #include "defs.h"
00065 #include "mempool.h"
00066 #include "clone.h"
00067 #include "tlog.h"
00068 #include "ipc_symtab_merge.h"
00069 #include "ipl_summary.h"
00070 #include "ipaa.h"
00071 #include "ipa_cg.h"
00072 #include "ipa_cprop.h"
00073 #include "ipa_cprop_annot.h"
00074 #include "ipa_feedback.h"
00075 #include "ipa_inline.h"
00076 #include "ipa_option.h"
00077 #include "ipa_summary.h"
00078
00079
00080 UINT32 IPA_Max_Total_Clones;
00081 UINT32 IPA_Num_Total_Clones = 0;
00082
00083 INT IPA_Constant_Count = 0;
00084 MEM_POOL Global_mem_pool;
00085
00086
00087 static void
00088 Ipa_cprop_tlog (IPA_NODE* node)
00089 {
00090 char buffer[64];
00091
00092 VALUE_DYN_ARRAY* formal_annot = node->Cprop_Annot();
00093 if (formal_annot && formal_annot != (VALUE_DYN_ARRAY*) -1) {
00094 for (INT32 i = 0; i < formal_annot->Elements(); ++i) {
00095 if ((*formal_annot)[i].Is_constant()) {
00096 sprintf(buffer, "Position %d", i);
00097 Generate_Tlog("IPA", "Constant_Propagation", 0,
00098 DEMANGLE(node->Name()), "Formal parameter constant",
00099 buffer, "");
00100 }
00101 }
00102 }
00103
00104 if (IPA_Enable_Common_Const) {
00105 GLOBAL_ANNOT* gannot = node->Global_Annot();
00106 for (UINT32 i = 0; i < GLOBAL_ANNOT::Size; ++i) {
00107 if (!gannot->Top(i) && !gannot->Bottom(i)) {
00108 const GLOBAL_DYN_ARRAY& gvals = gannot->Global_Value_Array(i);
00109 for (INT32 j = 0; j < gvals.Elements(); ++j) {
00110 if (gvals[j].Value()) {
00111 sprintf(buffer, "offset = %lld size = %d",
00112 gvals[j].Offset(), gvals[j].Size());
00113 Generate_Tlog("IPA", "Constant_Propagation", 0,
00114 DEMANGLE(node->Name()), "Common block constant",
00115 ST_name(GLOBAL_ANNOT::Common_ST[i]), buffer);
00116 }
00117 }
00118 }
00119 }
00120 }
00121 }
00122
00123
00124
00125
00126
00127 void
00128 Init_Cprop_Annotations (IPA_NODE* node)
00129 {
00130 if (IPA_Enable_Common_Const) {
00131 if (node->Is_Quasi_Clone()) {
00132
00133 IPA_NODE* origin = IPA_Call_Graph->Clone_Origin(node);
00134 node->Set_Global_Annot(CXX_NEW(GLOBAL_ANNOT(origin->Global_Annot(),
00135 &Global_mem_pool),
00136 &Global_mem_pool));
00137 }
00138 else {
00139 GLOBAL_ANNOT* gannot = CXX_NEW(GLOBAL_ANNOT(&Global_mem_pool),
00140 &Global_mem_pool);
00141 node->Set_Global_Annot(gannot);
00142
00143
00144
00145
00146 if (node->Is_Externally_Callable() ||
00147 node->Summary_Proc()->Is_alt_entry() ||
00148 node->Summary_Proc()->Has_alt_entry()) {
00149 gannot->Set_Bottom();
00150 }
00151 else {
00152 for (UINT32 i = 0; i < GLOBAL_ANNOT::Size; ++i) {
00153 INT32 key = ST_IDX_index(GLOBAL_ANNOT::Common_ST[i]);
00154
00155 if (!node->Mod_Ref_Info()->Is_eref_elmt(key)) {
00156 gannot->Set_Bottom(i);
00157 }
00158 }
00159 }
00160 }
00161 }
00162
00163 INT count = node->Num_Formals();
00164 if (count > 0) {
00165 if (node->Is_Externally_Callable() && !IPA_Enable_Cloning) {
00166 node->Set_Cprop_Annot (NULL);
00167 node->Clear_Propagated_Const();
00168 return;
00169 }
00170
00171 VALUE_DYN_ARRAY* annot = CXX_NEW(VALUE_DYN_ARRAY(Malloc_Mem_Pool),
00172 Malloc_Mem_Pool);
00173 annot->Force_Alloc_array (count);
00174 annot->Setidx (count-1);
00175 for (INT j = 0; j < count; ++j) {
00176 (*annot)[j].Init();
00177 }
00178 node->Set_Cprop_Annot(annot);
00179 if (node->Has_Varargs()) {
00180 (*annot)[count-1].Set_not_const();
00181 }
00182 }
00183 else {
00184 node->Set_Cprop_Annot (NULL);
00185 node->Clear_Propagated_Const();
00186 }
00187 }
00188
00189
00190
00191
00192
00193
00194
00195 void
00196 IPA_CPROP_DF_FLOW::InitializeNode(void* node)
00197 {
00198 Init_Cprop_Annotations ((IPA_NODE*)node);
00199 }
00200
00201
00202
00203
00204
00205 static BOOL
00206 Edge_has_new_cprop_annot(const IPA_EDGE* edge,
00207 IPA_EDGE** clone_edges,
00208 UINT32 num_clone_edges)
00209 {
00210 if (edge->Cprop_Annot()) {
00211 for (UINT32 i = 0; i < num_clone_edges; ++i) {
00212 if (Edges_Have_Equiv_Cprop_Annots(edge, clone_edges[i])) {
00213 return FALSE;
00214 }
00215 }
00216 }
00217 return TRUE;
00218 }
00219
00220 #ifdef KEY
00221 static void
00222 Clone_Trace (const IPA_NODE * clone, const IPA_EDGE * e)
00223 {
00224 Is_True (IPA_Clone_List_Actions, ("Tracing when it is disabled"));
00225
00226 VALUE_DYN_ARRAY * actuals = e->Cprop_Annot();
00227 Is_True (actuals && actuals != (void*)-1, ("Clone_Trace: Invalid actuals"));
00228
00229 for (UINT32 i=0; i<actuals->Elements(); ++i)
00230 {
00231 SUMMARY_VALUE * value = &(*actuals)[i];
00232 if (value->Is_int_const())
00233 fprintf (stderr, "argument %d has constant value %lld\n", i+1, value->Get_int_const_value());
00234 else if (value->Is_const_st() && MTYPE_is_integral (value->Get_mtype()))
00235 fprintf (stderr, "argument %d has constant value %lld\n", i+1, TCON_i0 (Tcon_Table[value->Get_tcon_idx()]));
00236 }
00237 }
00238
00239 static void
00240 Report_Reason (const IPA_EDGE * e, const char * reason, float count=0.0,
00241 float limit=0.0)
00242 {
00243 if (!IPA_Clone_List_Actions) return;
00244
00245 fprintf (stderr, "%s not cloned for call in %s: ", DEMANGLE (IPA_Call_Graph->Callee (e)->Name()), DEMANGLE (IPA_Call_Graph->Caller (e)->Name()));
00246 if (limit)
00247 fprintf (stderr, reason, count, limit);
00248 else
00249 fprintf (stderr, reason);
00250 }
00251
00252
00253 const UINT32 max_param_count = 10;
00254 const float min_hotness = 7.0;
00255 const UINT32 callee_limit = 500;
00256
00257
00258 static float
00259 compute_hotness_during_cloning (IPA_EDGE *e, IPA_NODE *c, INT s)
00260 {
00261 FB_FREQ cycle_ratio = (e->Get_frequency () / c->Get_frequency () *
00262 c->Get_cycle_count ()) / Total_cycle_count;
00263 float cycle_ratio_float = cycle_ratio.Value();
00264 float size_ratio = (float) s / ((float) MIN (Total_Prog_Size, Orig_Prog_Weight));
00265 float result_float = (cycle_ratio_float / size_ratio * 100.0);
00266 return (result_float);
00267 }
00268
00269 static BOOL
00270 Node_should_be_cloned (IPA_NODE * n , IPA_EDGE * e)
00271 {
00272 if (e->Has_frequency() && e->Get_frequency().Value() == 0.0)
00273 {
00274 Report_Reason (e, "Edge is never invoked\n");
00275 return FALSE;
00276 }
00277
00278 IPA_NODE * caller = IPA_Call_Graph->Caller (e);
00279 if (caller->Summary_Proc()->Is_Never_Invoked() ||
00280 n->Summary_Proc()->Is_Never_Invoked())
00281 {
00282 Report_Reason (e, "Edge is never invoked\n");
00283 return FALSE;
00284 }
00285
00286 VALUE_DYN_ARRAY * formals = n->Cprop_Annot();
00287 VALUE_DYN_ARRAY * actuals = e->Cprop_Annot();
00288
00289
00290 if (formals == NULL || actuals == NULL ||
00291 formals == (void*)-1 || actuals == (void*)-1)
00292 {
00293 #ifdef Is_True_On
00294 if (formals == (void*)-1 || actuals == (void*)-1)
00295 DevWarn ("cprop_annot == -1 during ipa cloning analysis");
00296 #endif
00297 Report_Reason (e, "No parameters?\n");
00298 return FALSE;
00299 }
00300
00301 UINT32 param_count = formals->Elements() < actuals->Elements() ?
00302 formals->Elements() : actuals->Elements();
00303
00304
00305 if (param_count > max_param_count)
00306 {
00307 Report_Reason (e, "Number of parameters %f > max (%f)\n", (float) param_count, (float) max_param_count);
00308 return FALSE;
00309 }
00310
00311 UINT32 callee_weight = Effective_weight (n);
00312 if (n->Get_feedback())
00313 {
00314 float hotness = compute_hotness_during_cloning (e, n, callee_weight);
00315 if (hotness < min_hotness)
00316 {
00317 Report_Reason (e, "Hotness (%f) < min hotness (%f)\n", hotness, min_hotness);
00318 return FALSE;
00319 }
00320 }
00321
00322 if (callee_weight > callee_limit)
00323 {
00324 Report_Reason (e, "Callee size (%f) > callee limit (%f)\n", (float) callee_weight, (float) callee_limit);
00325 return FALSE;
00326 }
00327
00328 return TRUE;
00329 }
00330 #endif // KEY
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344 static BOOL
00345 Node_can_be_cloned(IPA_NODE* node)
00346 {
00347 if (IPA_Max_Node_Clones == 0 ||
00348 IPA_Num_Total_Clones >= IPA_Max_Total_Clones ||
00349 node->Summary_Proc()->Is_alt_entry() ||
00350 node->Summary_Proc()->Has_alt_entry() ||
00351 node->Is_Quasi_Clone() ||
00352 node->Is_Nested_PU() ||
00353 PU_Info_child(node->PU_Info()) ||
00354 node->Has_Incoming_Back_Edge()) {
00355 return FALSE;
00356 }
00357
00358 IPA_CLONE_ARRAY* clone_array = IPA_Call_Graph->Clone_Array (node);
00359
00360 return (clone_array == NULL ||
00361 clone_array->Elements() < IPA_Max_Node_Clones);
00362 }
00363
00364
00365
00366
00367
00368 void*
00369 IPA_CPROP_DF_FLOW::Meet (void*, void* vertex, INT* change)
00370 {
00371 IPA_NODE* n = (IPA_NODE*) vertex;
00372 BOOL call_from_alt_entry = FALSE;
00373
00374
00375 IPA_EDGE** clone_edges =
00376 (IPA_EDGE**) alloca(IPA_Max_Node_Clones * sizeof(IPA_EDGE*));
00377 UINT32 num_clone_edges = 0;
00378
00379
00380 IPA_PRED_ITER edge_iter(n);
00381 for (edge_iter.First(); !edge_iter.Is_Empty(); edge_iter.Next()) {
00382
00383 IPA_EDGE* e = edge_iter.Current_Edge();
00384 if (e && e->Cprop_Annot() != (void*) -1) {
00385
00386
00387 IPA_NODE* caller = IPA_Call_Graph->Caller (e);
00388
00389 if (caller->Summary_Proc()->Has_alt_entry() ||
00390 caller->Summary_Proc()->Is_alt_entry()) {
00391 call_from_alt_entry = TRUE;
00392 }
00393
00394
00395 if (Edge_has_new_cprop_annot(e, clone_edges, num_clone_edges)) {
00396
00397
00398 if (num_clone_edges < IPA_Max_Node_Clones && Node_can_be_cloned(n)
00399 #ifdef KEY
00400 && Node_should_be_cloned(n, e)
00401 #endif
00402 ) {
00403 IPA_CLONING_ACTION action =
00404 Union_Formal_Cprop_Annot_With_Cloning(n, e);
00405 if (action == NEEDS_CLONING) {
00406 clone_edges[num_clone_edges++] = e;
00407 IPA_Num_Total_Clones++;
00408 }
00409 else if (action == ANNOTATION_CHANGED) {
00410 *change = TRUE;
00411 }
00412 }
00413 else {
00414
00415
00416 if (Union_Formal_Cprop_Annot(n, e)) {
00417 *change = TRUE;
00418 }
00419 }
00420 }
00421 }
00422 }
00423
00424 if (num_clone_edges > 0 && !call_from_alt_entry) {
00425 for (UINT32 i = 0; i < num_clone_edges; ++i) {
00426
00427
00428 IPA_NODE* clone_node=IPA_Call_Graph->Create_Quasi_Clone(clone_edges[i]);
00429
00430
00431 (void) Meet(0, clone_node, change);
00432 (void) Trans(0, 0, clone_node, change);
00433
00434 if (Get_Trace(TP_IPA, IPA_TRACE_CPROP_CLONING)) {
00435 extern char* IPA_Node_Name(IPA_NODE*);
00436 fprintf(TFile, "%s in file %s is cloned: %s\n",
00437 DEMANGLE(n->Name()),
00438 n->Input_File_Name(),
00439 IPA_Node_Name(clone_node));
00440 }
00441 #ifdef KEY
00442 if (IPA_Clone_List_Actions)
00443 {
00444 extern char* IPA_Node_Name(IPA_NODE*);
00445 fprintf(stderr, "%s is cloned (%s) for call from %s\n",
00446 DEMANGLE(n->Name()),
00447 IPA_Node_Name(clone_node),
00448 DEMANGLE (IPA_Call_Graph->Caller (clone_edges[i])->Name()));
00449 Clone_Trace (clone_node, clone_edges[i]);
00450 }
00451 #endif
00452 }
00453
00454 extern BOOL IPA_Should_Rebuild_DFN;
00455 IPA_Should_Rebuild_DFN = TRUE;
00456 *change = TRUE;
00457 }
00458
00459 return 0;
00460 }
00461
00462
00463
00464
00465
00466
00467 void*
00468 IPA_CPROP_DF_FLOW::Trans ( void *, void *, void *vertex, INT *change )
00469 {
00470 IPA_NODE *n = (IPA_NODE*)vertex;
00471
00472 MEM_POOL_Push (&Ipa_cprop_pool);
00473
00474 if (Intra_PU_Formal_Cprop (n)) {
00475 *change = TRUE;
00476 }
00477
00478 if (IPA_Enable_Common_Const) {
00479 if (Intra_PU_Global_Cprop(n)) {
00480 *change = TRUE;
00481 }
00482 }
00483
00484 MEM_POOL_Pop (&Ipa_cprop_pool);
00485
00486 return 0;
00487 }
00488
00489
00490
00491
00492 void
00493 IPA_CPROP_DF_FLOW::Print_entry ( FILE *fp, void *, void *node )
00494 {
00495 if (node) {
00496 IPA_NODE* n = (IPA_NODE*) node;
00497 if (n->Has_Propagated_Const()) {
00498 Print_constants(fp, n);
00499 if (IPA_Enable_Common_Const) {
00500 GLOBAL_ANNOT* gannot = n->Global_Annot();
00501 if (gannot && !gannot->Bottom()) {
00502 fprintf(fp, "\n%s common block constants:\n", DEMANGLE(n->Name()));
00503 gannot->Print(fp);
00504 }
00505 }
00506 }
00507 }
00508 }
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518 void
00519 IPA_CPROP_DF_FLOW::Print_constants(FILE* fp, IPA_NODE* n)
00520 {
00521 VALUE_DYN_ARRAY* outc = n->Cprop_Annot();
00522 if (outc == NULL || outc == (VALUE_DYN_ARRAY*) -1) return;
00523
00524 INT idx = outc->Lastidx();
00525 INT i;
00526
00527 #ifdef TODO
00528 if( fp == IPA_Feedback_con_fd ) {
00529 BOOL has_printed = FALSE;
00530 for (i = 0; i <= idx; i++) {
00531 SUMMARY_VALUE *value = &((*outc)[i]);
00532
00533 if (value->Is_constant ()) {
00534 if (has_printed)
00535 fputs (", ", fp);
00536 else
00537 fprintf (fp, "\n\nProcedure '%s' formal args:\n ",
00538 DEMANGLE (n->Name()));
00539
00540 fprintf (fp, " #%d = ", i+1);
00541 if (value->Is_addr_of ()) {
00542 fprintf (fp, "&%s",
00543 ST_name (St_Table[value->Get_global_st_idx ()]));
00544 } else
00545 value->Print_const_value (fp);
00546 has_printed = TRUE;
00547 }
00548 }
00549 if (has_printed)
00550 fputc ('\n', fp);
00551 }
00552 else {
00553 #endif // TODO
00554
00555 fprintf(fp, "%s formal constants:\n", DEMANGLE(n->Name()));
00556 for (i = 0; i <= idx; i++) {
00557 SUMMARY_VALUE *value = &((*outc)[i]);
00558 if (value->Is_constant ()) {
00559 fprintf (fp, " F#%d: ", i);
00560 value->Print_const_value (fp);
00561 fputs("\n", fp);
00562 ++IPA_Constant_Count;
00563 }
00564 }
00565
00566 #ifdef TODO
00567 }
00568 #endif
00569 }
00570
00571
00572
00573
00574
00575 BOOL
00576 IPA_CPROP_DF_FLOW::Valid_predecessors(IPA_NODE* node)
00577 {
00578 NODE_ITER v_iter(IPA_Call_Graph->Graph(), node->Node_Index());
00579
00580 for (NODE_INDEX vtx = v_iter.First_Pred();
00581 vtx != -1;
00582 vtx = v_iter.Next_Pred()) {
00583
00584 if (IPA_Call_Graph->Graph()->Node_User(vtx) != NULL) {
00585 return TRUE;
00586 }
00587 }
00588
00589 return FALSE;
00590 }
00591
00592
00593
00594
00595 BOOL
00596 IPA_CPROP_DF_FLOW::Valid_successors_without_cprop(IPA_NODE* node)
00597 {
00598 VALUE_DYN_ARRAY *cprop_annot;
00599
00600
00601 if (cprop_annot = node->Cprop_Annot()) {
00602 for (INT i=0; i<=cprop_annot->Lastidx(); ++i) {
00603 SUMMARY_VALUE *value = &((*cprop_annot)[i]);
00604 if (value->Is_constant ()) {
00605 return TRUE;
00606 }
00607 }
00608 }
00609
00610 NODE_ITER v_iter(IPA_Call_Graph->Graph(), node->Node_Index());
00611
00612 for (NODE_INDEX vtx = v_iter.First_Succ();
00613 vtx != -1;
00614 vtx = v_iter.Next_Succ()) {
00615
00616 if (IPA_Call_Graph->Graph()->Node_User(vtx) != NULL) {
00617 return TRUE;
00618 }
00619 }
00620
00621 return FALSE;
00622 }
00623
00624
00625
00626
00627
00628
00629
00630
00631 void
00632 IPA_CPROP_DF_FLOW::PerformCloning (IPA_NODE* node)
00633 {
00634
00635 if (node->Summary_Proc()->Is_alt_entry() ||
00636 node->Summary_Proc()->Has_alt_entry())
00637 return;
00638
00639 VALUE_DYN_ARRAY* cprop_annot = node->Cprop_Annot();
00640
00641 if (cprop_annot == NULL || cprop_annot == (VALUE_DYN_ARRAY *) -1)
00642 return;
00643
00644 BOOL fix_caller = FALSE;
00645
00646 if (node->Is_Externally_Callable()) {
00647
00648
00649
00650 for (INT i=0; i<=cprop_annot->Lastidx(); ++i) {
00651 if ((*cprop_annot)[i].Is_constant()) {
00652
00653
00654
00655 node->Set_Clone_Candidate();
00656
00657
00658
00659
00660 NODE_ITER v_iter(IPA_Call_Graph->Graph(), node->Node_Index());
00661 for (NODE_INDEX to = v_iter.First_Succ();
00662 to != -1;
00663 to = v_iter.Next_Succ())
00664 {
00665 IPA_NODE *to_node = IPA_Call_Graph->Graph()->Node_User(to);
00666 if (to_node)
00667 to_node->Set_No_Aggr_Cprop();
00668 }
00669
00670 #ifdef TODO
00671 Total_Prog_Size += node->Weight ();
00672 #endif
00673 fix_caller = TRUE;
00674 break;
00675 }
00676 }
00677 } else {
00678
00679
00680 for (INT i=0; i<=cprop_annot->Lastidx(); ++i) {
00681 if ((*cprop_annot)[i].Is_constant()) {
00682 node->Set_Propagated_Const();
00683 fix_caller = TRUE;
00684 break;
00685 }
00686 }
00687 }
00688
00689
00690
00691 if (fix_caller) {
00692 IPA_PRED_ITER edge_iter(node);
00693 for (edge_iter.First(); !edge_iter.Is_Empty(); edge_iter.Next()) {
00694 IPA_EDGE *edge = edge_iter.Current_Edge();
00695 if (edge)
00696 edge->Set_Propagated_Const();
00697 }
00698 } else {
00699 CXX_DELETE (cprop_annot, Malloc_Mem_Pool);
00700 node->Set_Cprop_Annot (NULL);
00701 node->Clear_Propagated_Const();
00702 }
00703 }
00704
00705
00706 void
00707 IPA_CPROP_DF_FLOW::Delete_dead_call (IPA_NODE* node)
00708 {
00709 #ifdef TODO
00710 if (node->Should_Be_Skipped())
00711 return;
00712 #endif // TODO
00713
00714 if (!IPA_Enable_DCE)
00715 return;
00716
00717 IPA_SUCC_ITER edge_iter (node);
00718
00719 for (edge_iter.First (); !edge_iter.Is_Empty(); edge_iter.Next()) {
00720 IPA_EDGE *e = edge_iter.Current_Edge();
00721 if (e && e->Cprop_Annot() == (void *) -1)
00722 e->Set_Deletable ();
00723 }
00724
00725 if (IPA_Enable_DFE && node->Cprop_Annot () == (void *) -1) {
00726
00727 if (!node->Is_Undeletable())
00728 node->Set_Deletable ();
00729 }
00730
00731 }
00732
00733
00734
00735
00736 static void
00737 Connect_indirect_call (IPA_NODE* caller)
00738 {
00739
00740 if (caller->Should_Be_Skipped())
00741 return;
00742
00743 const IPA_ICALL_LIST& icall_list = caller->Icall_List ();
00744
00745 for (IPA_ICALL_LIST::const_iterator icall_iter = icall_list.begin ();
00746 icall_iter != icall_list.end (); ++icall_iter) {
00747
00748 SUMMARY_CALLSITE *call = (*icall_iter)->Callsite();
00749
00750 if (!call->Is_func_ptr ())
00751 continue;
00752
00753 SUMMARY_VALUE &value = (*icall_iter)->Value();
00754 if (!value.Is_addr_of () || !value.Is_global ())
00755 continue;
00756
00757 ST* func_st = &St_Table[value.Get_global_st_idx ()];
00758
00759 Is_True (ST_class (func_st) == CLASS_FUNC,
00760 ("expecting a function symbol"));
00761
00762 if (ST_is_weak_symbol (func_st))
00763 func_st = ST_strong (func_st);
00764
00765 NODE_INDEX callee_idx = AUX_PU_node (Aux_Pu_Table[ST_pu (func_st)]);
00766
00767 if (callee_idx != INVALID_NODE_INDEX) {
00768 (void) IPA_Call_Graph->Add_New_Edge (call,
00769 caller->Node_Index (),
00770 callee_idx);
00771 }
00772 else {
00773 IPA_ICALL_NODE* opq = CXX_NEW(IPA_ICALL_NODE(call), Malloc_Mem_Pool);
00774 caller->Ocall_List().push_back(opq);
00775 }
00776
00777 #ifdef TODO
00778 if (call->Has_callsite_freq ())
00779 Total_call_freq += call->Get_frequency_count ();
00780 #endif
00781 Clear_ST_is_not_used (func_st);
00782 }
00783 }
00784
00785
00786
00787
00788
00789
00790 void
00791 IPA_CPROP_DF_FLOW::PostProcessIO (void *n)
00792 {
00793 if (!n) return;
00794 IPA_NODE* node = (IPA_NODE*) n;
00795
00796 Delete_dead_call(node);
00797 PerformCloning(node);
00798
00799 if (! node->Icall_List ().empty ())
00800 Connect_indirect_call(node);
00801
00802 if (IPA_Enable_Common_Const) {
00803 Map_Global_Constants(node);
00804 }
00805
00806 if (Get_Trace(TP_PTRACE1, TP_PTRACE1_IPA_CPROP)) {
00807 Ipa_cprop_tlog (node);
00808 }
00809 }
00810
00811
00812 UINT32 GLOBAL_ANNOT::Size;
00813 ST_IDX* GLOBAL_ANNOT::Common_ST;
00814 OFFSET_SIZE_TO_ST_IDX_MAP* GLOBAL_ANNOT::Offset_Size_To_ST;
00815
00816
00817
00818
00819
00820 IPA_CPROP_DF_FLOW::IPA_CPROP_DF_FLOW (DF_DIRECTION ddf, MEM_POOL* m)
00821 : IPA_DATA_FLOW (ddf, m)
00822 {
00823
00824
00825 if (!IPA_Enable_Simple_Alias) {
00826 IPA_Enable_Common_Const = FALSE;
00827 }
00828
00829 if (IPA_Enable_Common_Const) {
00830 ST* st;
00831 INT i;
00832
00833
00834
00835 UINT32 count = 0;
00836 FOREACH_SYMBOL (GLOBAL_SYMTAB, st, i) {
00837 if (ST_class(st) == CLASS_VAR &&
00838 ST_sclass(st) == SCLASS_COMMON &&
00839 ST_base_idx(st) == ST_st_idx(st) &&
00840 !ST_addr_saved(st) &&
00841 !AUX_ST_flags(Aux_St_Table[ST_st_idx(st)], COMMON_USED_IN_IO)) {
00842 ++count;
00843 }
00844 }
00845
00846 GLOBAL_ANNOT::Size = count;
00847
00848 if (count > 0) {
00849
00850
00851 GLOBAL_ANNOT::Common_ST = CXX_NEW_ARRAY(ST_IDX, count, Malloc_Mem_Pool);
00852 count = 0;
00853 FOREACH_SYMBOL (GLOBAL_SYMTAB, st, i) {
00854 if (ST_class(st) == CLASS_VAR &&
00855 ST_sclass(st) == SCLASS_COMMON &&
00856 ST_base_idx(st) == ST_st_idx(st) &&
00857 !ST_addr_saved(st) &&
00858 !AUX_ST_flags(Aux_St_Table[ST_st_idx(st)], COMMON_USED_IN_IO)) {
00859
00860 GLOBAL_ANNOT::Common_ST[count++] = ST_st_idx(st);
00861 }
00862 }
00863
00864
00865
00866 GLOBAL_ANNOT::Offset_Size_To_ST =
00867 CXX_NEW_ARRAY(OFFSET_SIZE_TO_ST_IDX_MAP, count, Malloc_Mem_Pool);
00868
00869 FOREACH_SYMBOL (GLOBAL_SYMTAB, st, i) {
00870 if (ST_class(st) == CLASS_VAR &&
00871 ST_sclass(st) == SCLASS_COMMON &&
00872 ST_base(st) != st &&
00873 ST_base(ST_base(st)) == ST_base(st) &&
00874 !ST_addr_saved(ST_base(st)) &&
00875 !AUX_ST_flags(Aux_St_Table[ST_base_idx(st)], COMMON_USED_IN_IO) &&
00876 MTYPE_is_integral(TY_mtype(ST_type(st)))) {
00877
00878 INT32 common_index = GLOBAL_ANNOT::Index(ST_base_idx(st));
00879 OFFSET_SIZE_TO_ST_IDX_MAP& map =
00880 GLOBAL_ANNOT::Offset_Size_To_ST[common_index];
00881 map[OFFSET_SIZE(ST_ofst(st), TY_size(ST_type(st)))] = ST_st_idx(st);
00882 }
00883 }
00884 }
00885 else {
00886 IPA_Enable_Common_Const = FALSE;
00887 }
00888 }
00889 }
00890