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 #define __STDC_LIMIT_MACROS
00047 #include <stdint.h>
00048 #include <alloca.h>
00049
00050 #include "assert.h"
00051 #include "defs.h"
00052 #include "config_ipa.h"
00053 #include "lwn_util.h"
00054 #include "targ_sim.h"
00055 #include "wn_simp.h"
00056 #include "wn_tree_util.h"
00057
00058 #include "ipa_cg.h"
00059 #include "ipa_inline.h"
00060 #include "ipo_clone.h"
00061 #include "ipo_parent.h"
00062 #include "ipl_summarize.h"
00063 #include "ipo_tlog_utils.h"
00064 #include "ipa_option.h"
00065
00066 #if (!defined(_STANDALONE_INLINER) && !defined(_LIGHTWEIGHT_INLINER))
00067 #include "dwarf_DST_producer.h"
00068 #include "clone_DST_utils.h"
00069 #include "ipaa.h"
00070 #endif // _STANDALONE_INLINER
00071
00072 #include "ipo_inline.h"
00073
00074 static INT initial_initv_tab_size;
00075
00076 MEM_POOL Ipo_mem_pool;
00077 WN_MAP Parent_Map;
00078
00079
00080
00081
00082 class SCOPE_CONTEXT
00083 {
00084 private:
00085 SCOPE* _scope_tab;
00086
00087 public:
00088 SCOPE_CONTEXT (SCOPE *scope) {
00089 _scope_tab = Scope_tab;
00090 Scope_tab = scope;
00091 }
00092
00093 ~SCOPE_CONTEXT () {
00094 Scope_tab = _scope_tab;
00095 }
00096 };
00097
00098 #define BASETYPE TY_mtype
00099 #define ST_ADDR_SAVED ST_addr_saved
00100 #define ST_ADDR_PASSED ST_addr_passed
00101 #define SET_ST_ADDR_SAVED Set_ST_addr_saved
00102 #define SET_ST_ADDR_PASSED Set_ST_addr_passed
00103 #define RESET_ST_ADDR_SAVED Clear_ST_addr_saved
00104 #define RESET_ST_ADDR_PASSED Clear_ST_addr_passed
00105
00106
00107
00108
00109
00110 static BOOL
00111 Subscripts_All_0(const WN* actual, INT n)
00112 {
00113 INT numdim = WN_num_dim(actual);
00114 for (INT i = n; i < numdim; i++) {
00115 const WN* index = WN_array_index(actual, i);
00116 if (WN_operator(index) != OPR_INTCONST || WN_const_val(index) != 0) {
00117 return FALSE;
00118 }
00119 }
00120 return TRUE;
00121 }
00122
00123
00124
00125
00126
00127 static BOOL
00128 Equal_dims(ARB_HANDLE formal_arb, ARB_HANDLE actual_arb)
00129 {
00130
00131
00132
00133 if (ARB_const_lbnd (actual_arb) && ARB_const_ubnd (actual_arb) &&
00134 ARB_const_lbnd (formal_arb) && ARB_const_ubnd (formal_arb)) {
00135
00136 INT64 formal_size = abs (ARB_ubnd_val (formal_arb) -
00137 ARB_lbnd_val (formal_arb)) + 1;
00138
00139 INT64 actual_size = abs (ARB_ubnd_val (actual_arb) -
00140 ARB_lbnd_val (actual_arb)) + 1;
00141
00142 return (formal_size == actual_size);
00143 }
00144
00145 return FALSE;
00146 }
00147
00148
00149
00150
00151 static inline INT
00152 Dim_size (ARB_HANDLE arb)
00153 {
00154 Is_True(ARB_const_lbnd(arb) && ARB_const_ubnd(arb),
00155 ("Dim_size: Expected constant array bounds"));
00156 return abs(ARB_ubnd_val(arb)-ARB_lbnd_val(arb)) + 1;
00157 }
00158
00159
00160
00161
00162 static inline BOOL
00163 Dim_size_is_1(ARB_HANDLE arb)
00164 {
00165 return (ARB_const_lbnd(arb) && ARB_const_ubnd(arb) && Dim_size(arb) == 1);
00166 }
00167
00168
00169
00170
00171
00172
00173 static BOOL
00174 Dim_size_unknown(ARB_HANDLE arb)
00175 {
00176 return ((!ARB_const_ubnd(arb) && ARB_ubnd_var(arb) == ST_IDX_ZERO) ||
00177 Dim_size_is_1(arb));
00178 }
00179
00180
00181 static PARM_ITER
00182 Lookup_Parm (PARM_ATTR_VEC& vec, const ST* st)
00183 {
00184 for (PARM_ITER first (vec.begin ()); first != vec.end(); ++first) {
00185
00186 if ((*first).Formal_St () == st)
00187 return first;
00188 }
00189 return vec.end ();
00190 }
00191
00192
00193
00194 static BOOL
00195 Formal_Is_Array (const ST* st)
00196 {
00197 const TY& ty = Ty_Table[ST_type (st)];
00198
00199 return (ST_sclass (st) == SCLASS_FORMAL && TY_kind (ty) == KIND_POINTER &&
00200 TY_kind (TY_pointed (ty)) == KIND_ARRAY);
00201 }
00202
00203
00204
00205
00206
00207 static RESHAPE_METHOD
00208 Do_Linearize (WN* actual, ST* formal_st)
00209 {
00210 TY_IDX f_tyr = ST_type(formal_st);
00211 if (ST_sclass(formal_st) != SCLASS_FORMAL_REF) {
00212 f_tyr = TY_pointed(f_tyr);
00213 }
00214
00215 WN* base = (WN_operator(actual) == OPR_ARRAY ?
00216 WN_array_base(actual) : actual);
00217
00218 OPERATOR base_opr = WN_operator(base);
00219
00220 TY_IDX a_tyr;
00221
00222 if (base_opr == OPR_LDID) {
00223 a_tyr = ST_type(WN_st(base));
00224 if (TY_kind(a_tyr) != KIND_POINTER) {
00225 return RS_EQ_COMMON;
00226 }
00227 a_tyr = TY_pointed(a_tyr);
00228 }
00229 else if (base_opr == OPR_LDA) {
00230 a_tyr = ST_type(WN_st(base));
00231 }
00232 else {
00233 return RS_EQ_COMMON;
00234 }
00235
00236 if (TY_kind(a_tyr) != KIND_ARRAY ||
00237 TY_size(TY_etype(a_tyr)) != TY_size(TY_etype(f_tyr))) {
00238 return RS_EQ_COMMON;
00239 }
00240
00241 INT f_dims = TY_AR_ndims(f_tyr);
00242 INT a_dims = TY_AR_ndims(a_tyr);
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255 if (f_dims == a_dims) {
00256 if (base == actual || Subscripts_All_0(actual, 1)) {
00257 for (INT i = 1; i < a_dims; i++) {
00258 if (!(Equal_dims(TY_arb(f_tyr)[i], TY_arb(a_tyr)[i]))) {
00259 return RS_LINEARIZE;
00260 }
00261 }
00262 return RS_EQ;
00263 }
00264 }
00265
00266 else if (f_dims < a_dims) {
00267 INT diff = a_dims - f_dims;
00268
00269 if (base == actual ||
00270 Subscripts_All_0(actual, diff) ||
00271 (INLINE_Array_Bounds && Subscripts_All_0(actual, diff+1))) {
00272
00273 for (INT f_idx = 0, a_idx = diff; f_idx < f_dims; f_idx++, a_idx++) {
00274
00275 ARB_HANDLE f_arb = TY_arb(f_tyr)[f_idx];
00276 ARB_HANDLE a_arb = TY_arb(a_tyr)[a_idx];
00277
00278 if (!(f_idx == 0 && INLINE_Array_Bounds && Dim_size_unknown(f_arb)) &&
00279 !(Equal_dims(f_arb, a_arb))) {
00280 return RS_LINEARIZE;
00281 }
00282 }
00283 return RS_LT;
00284 }
00285 }
00286
00287 #ifdef _WEIRD_CASE_
00288 else {
00289 if (base == actual || Subscripts_All_0(actual, 0)) {
00290 for (INT a_idx = 0, f_idx = f_dims - a_dims;
00291 a_idx < a_dims;
00292 a_idx++, f_idx++) {
00293 if (!Equal_dims(TY_arb(f_tyr)[f_idx], TY_arb(a_tyr)[a_idx])) {
00294 return RS_LINEARIZE;
00295 }
00296 }
00297
00298 for (f_idx = 0; f_idx < f_dims - a_dims; f_idx++) {
00299 if (!Equal_dim_1(TY_arb(f_tyr)[f_idx])) {
00300 return RS_LINEARIZE;
00301 }
00302 }
00303 return RS_GT;
00304 }
00305 }
00306 #endif
00307
00308 return RS_LINEARIZE;
00309 }
00310
00311
00312
00313
00314
00315 static BOOL
00316 IPA_Do_Linearization (IPA_NODE* callee_node, WN* call, SCOPE* caller_scope)
00317 {
00318 WN* callee_wn = callee_node->Whirl_Tree();
00319 INT num_formals = WN_num_formals(callee_wn);
00320
00321 #ifdef KEY // bug 3898
00322
00323
00324 if (num_formals > WN_kid_count (call))
00325 num_formals = WN_kid_count (call);
00326 #endif // KEY
00327
00328 vector<ST*> formals;
00329 formals.reserve (num_formals);
00330
00331
00332 for (INT j = 0; j < num_formals; ++j) {
00333 formals.push_back (WN_st(WN_formal(callee_wn,j)));
00334 }
00335
00336 SCOPE_CONTEXT switch_scope(caller_scope);
00337
00338 for (INT i = 0; i < num_formals; ++i) {
00339 ST* formal_st = formals[i];
00340 if (ST_sclass (formal_st) != SCLASS_FORMAL ||
00341 ST_is_value_parm (formal_st))
00342 continue;
00343
00344 if (! Formal_Is_Array (formal_st))
00345 continue;
00346
00347 WN* actual = WN_kid(call, i);
00348 if (WN_operator(actual) == OPR_PARM)
00349 actual = WN_kid0(actual);
00350
00351 if (Do_Linearize(actual, formal_st) == RS_LINEARIZE)
00352 return TRUE;
00353 }
00354 return FALSE;
00355 }
00356
00357
00358 #if (!defined(_STANDALONE_INLINER) && !defined(_LIGHTWEIGHT_INLINER))
00359
00360 #ifdef KEY
00361 static BOOL
00362 Match_Loop_Indexes (WN* wn, vector<ST*> formals, INT num_formals)
00363 {
00364 OPCODE opc = WN_opcode(wn);
00365 if (opc == OPC_DO_LOOP) {
00366 WN* index = WN_index(wn);
00367
00368 for (INT i = 0; i < num_formals; ++i) {
00369 ST* formal_st = formals[i];
00370 if (ST_sclass (formal_st) != SCLASS_FORMAL_REF)
00371 continue;
00372 if (formal_st == WN_st(index))
00373 return TRUE;
00374 }
00375 } else if (opc == OPC_BLOCK) {
00376 for (WN* stmt = WN_first(wn); stmt; stmt = WN_next(stmt)) {
00377 if (WN_opcode(stmt) == OPC_DO_LOOP) {
00378 WN* index = WN_index(stmt);
00379
00380 for (INT i = 0; i < num_formals; ++i) {
00381 ST* formal_st = formals[i];
00382 if (ST_sclass (formal_st) != SCLASS_FORMAL_REF)
00383 continue;
00384 if (formal_st == WN_st(index))
00385 return TRUE;
00386 }
00387 }
00388 for (UINT kidno = 0; kidno < WN_kid_count(stmt); kidno++) {
00389 if (Match_Loop_Indexes (WN_kid(stmt, kidno), formals, num_formals))
00390 return TRUE;
00391 }
00392 }
00393 } else {
00394 for (UINT kidno = 0; kidno < WN_kid_count(wn); kidno++) {
00395 if (Match_Loop_Indexes(WN_kid(wn, kidno), formals, num_formals))
00396 return TRUE;
00397 }
00398 }
00399 return FALSE;
00400 }
00401
00402 static BOOL
00403 Formal_Is_Loop_Index (IPA_NODE* callee, const IPA_EDGE* edge)
00404 {
00405 WN * call = edge->Whirl_Node();
00406 WN* callee_wn = callee->Whirl_Tree(FALSE);
00407 INT num_formals = WN_num_formals(callee_wn);
00408 INT count_formals_to_test = 0;
00409
00410
00411 if (edge->Num_Actuals() < num_formals)
00412 num_formals = edge->Num_Actuals();
00413
00414 vector<ST*> formals;
00415 formals.reserve (num_formals);
00416
00417 for (INT j = 0; j < num_formals; ++j) {
00418 WN* actual = WN_kid(call, j);
00419 if (WN_operator(actual) == OPR_PARM &&
00420 WN_operator(WN_kid0(actual)) == OPR_ARRAY) {
00421 formals.push_back (WN_st(WN_formal(callee_wn,j)));
00422 count_formals_to_test ++;
00423 }
00424 }
00425
00426 if (Match_Loop_Indexes(callee_wn, formals, count_formals_to_test))
00427 return TRUE;
00428
00429 return FALSE;
00430 }
00431 #endif
00432
00433
00434 BOOL
00435 Can_Inline_Call (IPA_NODE* caller, IPA_NODE* callee, const IPA_EDGE* edge)
00436 {
00437 SCOPE_CONTEXT switch_scope(callee->Scope());
00438
00439
00440
00441 if (! (edge->Has_Must_Inline_Attrib () ||
00442 callee->Has_Must_Inline_Attrib () || INLINE_All ||
00443 IPA_Enable_Linearization)) {
00444
00445 if (IPA_Do_Linearization (callee, edge->Whirl_Node(), caller->Scope())) {
00446 Report_Reason ( callee, caller,
00447 "array reference will be linearized ", edge );
00448
00449 if (callee->Lexical_Level() > caller->Lexical_Level()) {
00450
00451
00452 caller->Set_Noinline_Attrib();
00453 }
00454
00455 return FALSE;
00456 }
00457 }
00458
00459 return TRUE;
00460
00461 }
00462
00463 #endif // !_STANDALONE_INLINER
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475 static
00476 ST* Find_Return_Registers(TYPE_ID type, PREG_NUM *rreg1, PREG_NUM *rreg2)
00477 {
00478 TYPE_ID mtype1;
00479 TYPE_ID mtype2;
00480
00481 if (WHIRL_Return_Info_On) {
00482
00483 RETURN_INFO return_info = Get_Return_Info (Be_Type_Tbl(type), Use_Simulated);
00484
00485 if (RETURN_INFO_count(return_info) <= 2) {
00486
00487 mtype1 = RETURN_INFO_mtype (return_info, 0);
00488 mtype2 = RETURN_INFO_mtype (return_info, 1);
00489 *rreg1 = RETURN_INFO_preg (return_info, 0);
00490 *rreg2 = RETURN_INFO_preg (return_info, 1);
00491 }
00492
00493 else
00494 Fail_FmtAssertion ("Find_Return_Registers: more than 2 return registers");
00495 }
00496
00497 else {
00498 Get_Return_Mtypes(Be_Type_Tbl(type), Use_Simulated, &mtype1, &mtype2);
00499 Get_Return_Pregs(mtype1, mtype2, rreg1, rreg2);
00500 }
00501
00502 if (Preg_Offset_Is_Int(*rreg1))
00503 return Int_Preg;
00504 else
00505 return Float_Preg;
00506 }
00507
00508
00509
00510
00511
00512 static WN*
00513 Create_array(WN* base)
00514 {
00515
00516 if (WN_operator (base) == OPR_ARRAY)
00517 return IPO_Copy_Tree (base);
00518
00519 INT ndims, i;
00520 OPCODE opc, opc1;
00521 WN* size_wn, *one, *upper, *lower;
00522 TY_IDX ty;
00523
00524 TYPE_ID rtype = WN_rtype(base);
00525 OPCODE array_op = OPCODE_make_op(OPR_ARRAY, rtype, MTYPE_V);
00526
00527 switch(WN_operator(base)) {
00528 case OPR_LDID:
00529 ty = TY_pointed(WN_ty(base));
00530 break;
00531
00532 case OPR_LDA:
00533 ty = ST_type(WN_st(base));
00534 break;
00535 }
00536
00537 assert(TY_kind(ty) == KIND_ARRAY);
00538 ndims = TY_AR_ndims(ty);
00539 WN* array_wn = WN_Create(array_op, ndims + ndims + 1);
00540 WN* b = IPO_Copy_Tree(base);
00541 WN_st_idx(array_wn) = WN_st_idx(base);
00542 WN_array_base(array_wn) = b;
00543
00544 WN_element_size(array_wn) = TY_size(TY_AR_etype(ty));
00545
00546 opc = OPC_I4INTCONST;
00547
00548
00549 for (i=0; i< ndims; ++i) {
00550
00551
00552 if (TY_AR_const_lbnd(ty, i) && TY_AR_const_ubnd(ty,i))
00553 {
00554 INT sum = Dim_size(TY_arb(ty)[i]);
00555 size_wn = WN_CreateIntconst(opc, sum);
00556 WN_array_dim(array_wn, i) = size_wn;
00557 WN_array_index(array_wn,i) = WN_CreateIntconst(opc,0);
00558 continue;
00559 }
00560
00561 else if
00562 ((TY_AR_lbnd_var(ty, i) == 0) ||
00563 (TY_AR_ubnd_var(ty, i) == 0))
00564 {
00565 WN_array_dim(array_wn, i) = WN_CreateIntconst(opc,0);
00566 WN_array_index(array_wn,i) = WN_CreateIntconst(opc,0);
00567 continue;
00568 }
00569
00570 else if (TY_AR_const_lbnd(ty, i))
00571 {
00572 upper = WN_CreateLdid (OPCODE_make_op(OPR_LDID,
00573 TY_mtype(ST_type(TY_AR_ubnd_var(ty,i))),
00574 TY_mtype(ST_type(TY_AR_ubnd_var(ty,i)))),
00575 0, TY_AR_ubnd_var(ty,i),
00576 ST_type(TY_AR_ubnd_var(ty,i)));
00577 lower = WN_CreateIntconst(opc, TY_AR_lbnd_val(ty, i));
00578
00579 }
00580
00581
00582 else if (TY_AR_const_ubnd(ty, i))
00583 {
00584 upper = WN_CreateIntconst(opc, TY_AR_ubnd_val(ty, i));
00585 lower = WN_CreateLdid (OPCODE_make_op(OPR_LDID,
00586 TY_mtype(ST_type(TY_AR_lbnd_var(ty,i))),
00587 TY_mtype(ST_type(TY_AR_lbnd_var(ty,i)))),
00588 0, TY_AR_lbnd_var(ty,i),
00589 ST_type(TY_AR_lbnd_var(ty,i)));
00590
00591 }
00592
00593 else
00594
00595 {
00596 lower = WN_CreateLdid (OPCODE_make_op(OPR_LDID,
00597 TY_mtype(ST_type(TY_AR_lbnd_var(ty,i))),
00598 TY_mtype(ST_type(TY_AR_lbnd_var(ty,i)))),
00599 0, TY_AR_lbnd_var(ty,i),
00600 ST_type(TY_AR_lbnd_var(ty,i)));
00601
00602 upper = WN_CreateLdid (OPCODE_make_op(OPR_LDID,
00603 TY_mtype(ST_type(TY_AR_ubnd_var(ty,i))),
00604 TY_mtype(ST_type(TY_AR_ubnd_var(ty,i)))),
00605 0, TY_AR_ubnd_var(ty,i),
00606 ST_type(TY_AR_ubnd_var(ty,i)));
00607
00608 }
00609
00610 opc1 = OPC_I4SUB;
00611 size_wn = LWN_CreateExp2( opc1, upper, lower);
00612 opc1 = OPC_I4INTCONST;
00613 one = WN_CreateIntconst(opc1, 1);
00614 opc1 = OPC_I4ADD;
00615 size_wn = LWN_CreateExp2(opc1, size_wn, one);
00616 WN_array_dim(array_wn,i) = size_wn;
00617 opc1 = OPC_I4INTCONST;
00618 WN_array_index(array_wn,i) = WN_CreateIntconst(opc1, 0);
00619 }
00620
00621
00622 LWN_Parentize(array_wn);
00623
00624 return array_wn;
00625 }
00626
00627
00628
00629
00630
00631
00632 static INT
00633 Get_orig_param_position (INT curpos, const VALUE_DYN_ARRAY *cprop_annot)
00634 {
00635 INT i = -1;
00636 INT idx_of_nonconst_param = -1;
00637
00638 if (cprop_annot == 0)
00639 return curpos;
00640 while (idx_of_nonconst_param != curpos) {
00641 if (!(*cprop_annot)[i+1].Is_remove_param()) {
00642 idx_of_nonconst_param++;
00643 }
00644 i++;
00645 }
00646 return i;
00647 }
00648
00649
00650
00651 static ST *
00652 Get_actual_st_if_passed (WN *actual)
00653 {
00654 TREE_ITER p (actual);
00655 while (p.Wn () != NULL) {
00656 WN* wn = p.Wn ();
00657
00658 switch (WN_operator (wn)) {
00659 case OPR_ILOAD:
00660 case OPR_MLOAD:
00661 p.Skip ();
00662 continue;
00663
00664 case OPR_LDA:
00665 {
00666 ST* st = WN_st (wn);
00667 if (ST_class (st) == CLASS_CONST)
00668 break;
00669 return st;
00670 }
00671 #ifdef KEY
00672 case OPR_BLOCK:
00673 {
00674 WN * parent = p.Get_parent_wn();
00675 if (parent && WN_operator(parent) == OPR_COMMA) {
00676 p.Skip ();
00677 continue;
00678 }
00679 }
00680 #endif
00681 }
00682 ++p;
00683 }
00684
00685 return NULL;
00686 }
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705 static void
00706 Set_Tables (IPA_NODE* node)
00707 {
00708 Scope_tab = node->Scope_Table ();
00709 Current_scope = node->Lexical_Level ();
00710 Current_pu = &Pu_Table[ST_pu (Scope_tab[Current_scope].st)];
00711 Parent_Map = node->Parent_Map ();
00712 Current_Map_Tab = node->Map_Table ();
00713 }
00714
00715
00716
00717
00718
00719
00720 BOOL
00721 IPO_INLINE::SubstituteFormal (ST* formal, WN* actual, INT position)
00722 {
00723 #ifdef _LIGHTWEIGHT_INLINER
00724 return FALSE;
00725
00726
00727 #else
00728 #ifndef _STANDALONE_INLINER
00729
00730 if (!IPA_Enable_Copy_Prop)
00731 return FALSE;
00732
00733 if (! (IPA_Enable_Simple_Alias && IPA_Enable_Addressing))
00734 return FALSE;
00735
00736 const IPAA_NODE_INFO *callee_info = Callee_node ()->Mod_Ref_Info ();
00737
00738 INT original_param_position = Get_orig_param_position (position,
00739 Callee_node ()->Cprop_Annot ());
00740
00741 if (callee_info->Is_formal_dmod_elmt (original_param_position)) {
00742 return FALSE;
00743 } else if (callee_info->Is_formal_dref_elmt (original_param_position))
00744 return FALSE;
00745
00746 if (ST_addr_saved (formal) || ST_addr_passed (formal))
00747 return FALSE;
00748
00749 ST *st = Get_actual_st_if_passed (actual);
00750
00751 if (st == NULL) {
00752 return FALSE;
00753 }
00754
00755
00756
00757 if (ST_class(st) == CLASS_CONST || ST_addr_saved (st)) {
00758 return FALSE;
00759 }
00760
00761
00762 return TRUE;
00763
00764 #else
00765
00766
00767
00768
00769
00770 if (!INLINE_Enable_Copy_Prop) {
00771 return FALSE;
00772 }
00773
00774
00775 BOOL same_file =
00776 (Caller_node ()->File_Index () == Callee_node ()->File_Index ()) ;
00777
00778 if (!same_file) {
00779 return FALSE;
00780 }
00781
00782 if (OPCODE_has_sym(WN_opcode(actual)) && WN_operator(actual) == OPR_LDA) {
00783 ST *s = WN_st(actual);
00784 TY_IDX t = WN_ty(actual);
00785 if ((ST_class(s) != CLASS_CONST) && (ST_ADDR_SAVED(s))) {
00786 return FALSE;
00787 }
00788
00789
00790 if ((TY_kind(t)== KIND_POINTER) && TY_pointed(t) &&
00791 TY_is_volatile(TY_pointed(t))) {
00792 return FALSE;
00793 }
00794
00795
00796
00797 if ((TY_kind(ST_type(s)) == KIND_SCALAR ||
00798 ((ST_class(s) == CLASS_VAR) && TY_kind(t) == KIND_POINTER)) &&
00799 (TY_kind(ST_type(formal)) == KIND_POINTER)) {
00800
00801 if ((ST_sclass(s) != SCLASS_AUTO) &&
00802 (ST_sclass(s) != SCLASS_FORMAL) &&
00803
00804 (! (ST_is_const_var(s) && (ST_sclass(s) == SCLASS_FSTATIC)))) {
00805
00806 return FALSE;
00807 }
00808
00809
00810 INT formal_element_size = TY_size(TY_pointed(ST_type(formal)));
00811 INT actual_element_size = TY_size(ST_type(s));
00812
00813
00814 if (formal_element_size != actual_element_size) {
00815 return FALSE;
00816 }
00817 } else {
00818
00819 return FALSE;
00820 }
00821 } else if (OPCODE_has_sym(WN_opcode(actual)) &&
00822 WN_operator(actual) == OPR_LDID) {
00823
00824
00825
00826
00827
00828
00829 return FALSE;
00830 } else {
00831
00832
00833 return FALSE;
00834 }
00835
00836 const SUMMARY_PROCEDURE *proc_node = Callee_Summary_Proc ();
00837
00838
00839 INT formal_index = proc_node->Get_formal_index();
00840
00841 SUMMARY_FORMAL *formal_node =
00842 Summary->Get_formal (formal_index +
00843 Get_orig_param_position (position,
00844 Callee_node ()->Cprop_Annot ()));
00845
00846 INT s_f_indx = formal_node->Get_symbol_index();
00847
00848 SUMMARY_SYMBOL *f_symbols = Summary->Get_symbol (0);
00849
00850 SUMMARY_CREF_SYMBOL *cref_symbols = Summary->Get_symbol_crefcount (0);
00851 INT cref_indx = Summary->Find_symbol_crefcount_index(s_f_indx);
00852
00853
00854
00855
00856
00857 if (OPCODE_has_sym(WN_opcode(actual)) &&
00858 (WN_operator(actual) == OPR_LDID) ||
00859 (WN_operator(actual) == OPR_LDA)) {
00860
00861 if (!(OPCODE_has_sym (WN_opcode(actual)) &&
00862 WN_operator(actual) == OPR_LDA))
00863
00864 {
00865 return FALSE;
00866 }
00867 }
00868
00869 BOOL cdref;
00870
00871
00872
00873 if (f_symbols[s_f_indx].Is_cdref_preg_only() &&
00874 WN_opcode (Call_Wn ()) == OPC_VCALL)
00875 {
00876 cdref = FALSE;
00877 if (Trace_CopyProp)
00878 fprintf(TFile, "ignore cref/dref (due to void call) for formal: %s",ST_name(formal));
00879 Inline_tlog("SubstituteFormal",0,"ignore cref/dref due to void call for formal: %s",ST_name(formal));
00880 }
00881 else if ( (cref_indx != -1) &&
00882 (cref_symbols[cref_indx].Get_cur_cref_count() == 0))
00883 {
00884 cdref = f_symbols[s_f_indx].Is_dref();
00885 if (Trace_CopyProp)
00886 fprintf(TFile, "ignore cref due to refcount being 0 for formal: %s \n",ST_name(formal));
00887 }
00888 else
00889 cdref = f_symbols[s_f_indx].Is_dref() || f_symbols[s_f_indx].Is_cref();
00890
00891
00892 if (f_symbols[s_f_indx].Is_dmod() ||
00893 f_symbols[s_f_indx].Is_aref() ||
00894 cdref ||
00895 (f_symbols[s_f_indx].Is_addr_saved())) {
00896
00897 return FALSE;
00898 } else {
00899 return TRUE;
00900 }
00901 #endif
00902 #endif
00903 }
00904
00905 #ifdef KEY // taken from wn_mp.cxx
00906 static const char * const dope_str_prefix = ".dope." ;
00907 static const INT dope_str_prefix_len = 6;
00908
00909 BOOL
00910 ST_Has_Dope_Vector(const ST *st) {
00911 if (ST_class(st) != CLASS_VAR)
00912 return FALSE;
00913
00914 if ( TY_is_f90_pointer(ST_type(st)) )
00915 return TRUE;
00916
00917 TY_IDX ty = ST_type(st);
00918 while (TY_kind(ty) == KIND_POINTER)
00919 ty = TY_pointed(ty);
00920
00921 if (TY_kind(ty) == KIND_STRUCT &&
00922 strncmp(TY_name(ty), dope_str_prefix, dope_str_prefix_len) == 0)
00923 return TRUE;
00924
00925 return FALSE;
00926 }
00927 #endif
00928
00929 static BOOL
00930 ST_might_be_modified (const ST* st)
00931 {
00932 if (ST_class (st) == CLASS_PREG || ST_class (st) == CLASS_CONST ||
00933 ST_is_const_var (st))
00934 return FALSE;
00935
00936 switch (ST_sclass (st)) {
00937 case SCLASS_AUTO:
00938 case SCLASS_FORMAL:
00939 case SCLASS_FORMAL_REF:
00940 if (!ST_addr_saved (st) && !ST_addr_passed (st) &&
00941 !ST_has_nested_ref (st))
00942 return FALSE;
00943 }
00944
00945 #ifdef KEY // bug 7871
00946 if (ST_Has_Dope_Vector (st)) return FALSE;
00947 #endif
00948
00949 return TRUE;
00950 }
00951
00952
00953
00954
00955
00956
00957
00958 static void
00959 Update_Caller_MP_Pragmas(ST* s, WN *wn)
00960 {
00961
00962
00963
00964
00965
00966 WN_VECTOR wnv(Malloc_Mem_Pool);
00967
00968 WN *tmp = wn;
00969 while (tmp) {
00970 if (WN_opcode(tmp) == OPC_REGION && REGION_is_mp(tmp)) {
00971 wnv.push_back (tmp);
00972 }
00973 tmp = LWN_Get_Parent(tmp);
00974 }
00975
00976 if (ST_sclass(s) == SCLASS_AUTO)
00977 #ifdef KEY
00978
00979 Add_Pragma_To_MP_Regions (&wnv, WN_PRAGMA_LOCAL,
00980 s, 0, Parent_Map, TRUE);
00981 #else
00982 Add_Pragma_To_MP_Regions (&wnv, WN_PRAGMA_LOCAL,
00983 s, 0, Parent_Map, FALSE);
00984 #endif // KEY
00985 else
00986 Add_Pragma_To_MP_Regions (&wnv, WN_PRAGMA_SHARED,
00987 s, 0, Parent_Map, FALSE);
00988
00989 }
00990
00991
00992
00993 static pair<WN*, ST*>
00994 Create_Copy_Expr_For_Ptr (WN* expr, WN* call, BOOL is_mp)
00995 {
00996 ST* copy_st = Gen_Temp_Symbol(MTYPE_To_TY(Pointer_type), "");
00997 WN* copy_stmt = WN_Stid (Pointer_type, 0, copy_st, ST_type (copy_st),
00998 IPO_Copy_Tree (expr));
00999 if (is_mp)
01000 Update_Caller_MP_Pragmas(copy_st, call);
01001
01002 return std::make_pair (copy_stmt, copy_st);
01003 }
01004
01005
01006
01007 static pair<WN*, ST*>
01008 Create_Copy_Expr (WN* expr, WN* call, BOOL is_mp)
01009 {
01010 TYPE_ID desc = WN_rtype (expr);
01011 ST* copy_st = Gen_Temp_Symbol(MTYPE_To_TY(desc), "");
01012 WN* copy_stmt = WN_Stid (desc, 0, copy_st, ST_type (copy_st),
01013 IPO_Copy_Tree (expr));
01014 if (is_mp)
01015 Update_Caller_MP_Pragmas(copy_st, call);
01016
01017 return std::make_pair (copy_stmt, copy_st);
01018 }
01019
01020
01021
01022
01023
01024 static void
01025 Process_Actual (WN* actual, WN* copy_in_block, IPO_INLINE& inliner)
01026 {
01027 UINT count = WN_kid_count (actual);
01028
01029 for (UINT i = 0; i < count; ++i) {
01030 WN* wn = WN_kid (actual, i);
01031 switch (WN_operator (wn)) {
01032 case OPR_INTCONST:
01033 case OPR_LDA:
01034 continue;
01035
01036 case OPR_ILOAD:
01037 if (WN_operator (WN_kid0 (wn)) != OPR_LDA)
01038 break;
01039 if (ST_might_be_modified (WN_st (WN_kid0 (wn))))
01040 break;
01041 else
01042 continue;
01043
01044 case OPR_LDID:
01045 if (ST_might_be_modified (WN_st (wn)))
01046 break;
01047 else
01048 continue;
01049
01050 case OPR_ARRAY:
01051 Process_Actual (wn, copy_in_block, inliner);
01052 continue;
01053
01054 default:
01055 break;
01056 }
01057
01058
01059
01060
01061 pair<WN*, ST*> copy_stmt = Create_Copy_Expr (wn, inliner.Call_Wn(),
01062 inliner.Caller_node()->Summary_Proc ()->Has_parallel_pragma () ||
01063 inliner.Caller_node()->Summary_Proc ()->Has_parallel_region_pragma());
01064
01065
01066 LWN_Insert_Block_Before (copy_in_block, NULL, copy_stmt.first);
01067
01068 WN_kid (actual, i) = WN_Ldid (WN_rtype (wn), 0,
01069 ST_st_idx (copy_stmt.second),
01070 ST_type (copy_stmt.second));
01071 }
01072 }
01073
01074
01075
01076
01077
01078
01079
01080 static void
01081 Copy_Subscript_Expressions (IPO_INLINE_AUX& aux, IPO_INLINE& inliner)
01082 {
01083
01084 PARM_ATTR_VEC& parm_attr = aux.parm_attr;
01085 for (PARM_ITER iter (parm_attr.begin ()); iter != parm_attr.end ();
01086 ++iter) {
01087
01088 WN* actual = (*iter).Actual_Wn ();
01089 if (WN_operator(actual) == OPR_ARRAY &&
01090 ((*iter).Pass_Method () == PM_UNKNOWN ||
01091 (*iter).Pass_Method () == PM_REPLACE)) {
01092
01093 Process_Actual (actual, aux.copy_in_block, inliner);
01094 }
01095 }
01096 }
01097
01098
01099
01100
01101
01102
01103 #ifdef _STANDALONE_INLINER
01104 static void
01105 Reset_Addr_Bits(ST* s, INT position, IPA_EDGE* edge, IPA_NODE* callee)
01106 {
01107 BOOL do_tracing;
01108
01109
01110
01111 do_tracing = Trace_CopyProp || Trace_IPA;
01112
01113
01114 SUMMARY_SYMBOL* symbols= Summary->Get_symbol (0);
01115
01116
01117 const SUMMARY_CALLSITE* callsites = edge->Summary_Callsite ();
01118
01119 INT aindx = callsites->Get_actual_index();
01120
01121 INT32 sindx =
01122 Summary->Get_actual (aindx +
01123 Get_orig_param_position (position,
01124 callee->Cprop_Annot ()))-> Get_symbol_index ();
01125
01126
01127 if (sindx == -1) {
01128 if (do_tracing)
01129 fprintf(TFile, "Actual index is -1; perhaps never set?: %s\n",
01130 ST_name(s));
01131 return;
01132 }
01133
01134
01135 SUMMARY_SYMBOL* snode = &symbols[sindx];
01136
01137 if (!snode->Is_local()) {
01138 if (do_tracing)
01139 fprintf(TFile,
01140 "Actual is not local. ST_addr bits NOT RESET for %s\n",
01141 ST_name(s));
01142 return;
01143 }
01144
01145
01146 if (snode->Is_addr_saved()) {
01147 if ((ST_class(s) == CLASS_VAR) || (ST_class(s) == CLASS_FUNC)) {
01148 SET_ST_ADDR_SAVED(s);
01149 if (do_tracing)
01150 fprintf(TFile, "ST_addr_saved for symbol %s is true \n",
01151 ST_name(s));
01152 } else if (do_tracing)
01153 fprintf(TFile, "ST_addr_saved for symbol %s NOT marked \n",
01154 ST_name(s));
01155
01156 } else {
01157 if (do_tracing)
01158 fprintf(TFile, "ST_addr_saved for symbol %s is false\n",
01159 ST_name(s));
01160 if (!snode->Is_addr_passed_inliner()) {
01161
01162 snode->Set_addr_passed_inliner();
01163
01164
01165 snode->Reset_cur_addr_passed_count();
01166 }
01167
01168 snode->Incr_cur_addr_passed_count();
01169
01170
01171
01172
01173 if (snode->Get_cur_addr_passed_count() == snode->Get_addr_count()) {
01174 RESET_ST_ADDR_SAVED(s);
01175 RESET_ST_ADDR_PASSED(s);
01176 if (do_tracing) {
01177 fprintf(TFile, "ST_addr_passed and ST_addr_saved reset for %s \n",
01178 ST_name(s));
01179 }
01180 }
01181 else if (do_tracing) {
01182
01183 fprintf(TFile, "Addr counts for %s DIFFER; Summary says %d but current count is %d\n",
01184 ST_name(s),
01185 snode->Get_addr_count(),
01186 snode->Get_cur_addr_passed_count());
01187 }
01188 }
01189 }
01190 #endif // _STANDALONE_INLINER
01191
01192
01193
01194
01195
01196
01197
01198
01199
01200
01201
01202
01203
01204
01205
01206
01207
01208
01209
01210
01211
01212
01213
01214
01215 #if (!defined(_STANDALONE_INLINER) && !defined(_LIGHTWEIGHT_INLINER))
01216 static void
01217 Update_formal_dref (WN *actual, IPA_NODE* caller)
01218 {
01219 if (!WN_has_sym(actual))
01220 return;
01221
01222 IPAA_NODE_INFO *caller_info = caller->Mod_Ref_Info ();
01223
01224 if (caller_info == NULL)
01225 return;
01226
01227 WN *func = caller->Whirl_Tree ();
01228 ST *st = WN_st (actual);
01229
01230 switch (ST_sclass (st)) {
01231 case SCLASS_FORMAL:
01232 case SCLASS_FORMAL_REF:
01233 for (INT i = 0; i < WN_num_formals (func); ++i) {
01234 if (WN_st (WN_formal (func, i)) != st)
01235 continue;
01236 INT orig_position =
01237 Get_orig_param_position (i, (VALUE_DYN_ARRAY *)
01238 (caller->Cprop_Annot()));
01239 caller_info->Add_formal_dref_elmt (orig_position);
01240 break;
01241 }
01242 break;
01243 }
01244 }
01245 #endif // _STANDALONE_INLINER
01246
01247
01248
01249
01250
01251
01252 static
01253 TYPE_ID Get_element_mtype(WN* actual)
01254 {
01255 WN* base;
01256 TY_IDX ty;
01257
01258 if (WN_operator(actual) == OPR_ARRAY) {
01259 base = WN_array_base(actual);
01260 return Get_element_mtype(base);
01261 }
01262 else
01263 base = actual;
01264
01265 switch(WN_operator(base)) {
01266
01267 case OPR_LDID:
01268 ty = TY_pointed(WN_ty(base));
01269 break;
01270
01271 case OPR_LDA:
01272 ty = ST_type(WN_st(base));
01273 break;
01274
01275 default:
01276 Fail_FmtAssertion("unknown base type\n");
01277 break;
01278 }
01279
01280 return
01281 BASETYPE(TY_AR_etype(ty));
01282 }
01283
01284
01285
01286
01287
01288 static
01289 TY_IDX Get_element_ty(WN* actual)
01290 {
01291 WN* base;
01292 TY_IDX ty;
01293 TY_IDX result_ty;
01294 if (WN_operator(actual) == OPR_ARRAY)
01295 base = WN_array_base(actual);
01296 else
01297 base = actual;
01298
01299 switch (WN_operator(base)) {
01300
01301 case OPR_LDID:
01302 ty = TY_pointed(WN_ty(base));
01303 break;
01304
01305 case OPR_LDA:
01306 ty = ST_type(WN_st(base));
01307 break;
01308
01309 default:
01310 for(INT i=0; i<WN_kid_count(base); ++i) {
01311 if (result_ty = Get_element_ty(WN_kid(base, i)))
01312 return result_ty;
01313 }
01314 Is_True(result_ty, ("Get_element_ty cannot find a good ty\n"));
01315 break;
01316 }
01317 result_ty = TY_AR_etype(ty);
01318 if (result_ty == 0) {
01319
01320 ty = WN_ty(base);
01321 if (TY_pointed(ty)) {
01322 ty = TY_pointed(ty);
01323 Is_True((TY_kind(ty) == KIND_ARRAY), ("Must be an array"));
01324 }
01325 result_ty = TY_AR_etype(ty);
01326 }
01327 return result_ty;
01328 }
01329
01330
01331
01332
01333
01334
01335
01336
01337
01338
01339
01340
01341
01342
01343
01344
01345
01346 PREG_NUM
01347 IPO_INLINE::Process_Alloca_Preamble()
01348 {
01349 Set_Tables (Caller_node ());
01350
01351 OPCODE stop = OPCODE_make_op(OPR_STID, MTYPE_V, Pointer_type);
01352 OPCODE ldop = OPCODE_make_op(OPR_LDID, Pointer_type, Pointer_type);
01353 TY_IDX pty = Make_Pointer_Type(Be_Type_Tbl(Pointer_type), TRUE);
01354
01355 PREG_NUM rreg1;
01356 PREG_NUM rreg2;
01357
01358
01359 char newstname[32] = "$save_sp_before_alloca";
01360 PREG_NUM saved_sp = Create_Preg_explicit(Pointer_type, (char*)newstname,
01361 Caller_Scope(), Caller_level());
01362
01363 OPCODE op = OPCODE_make_op(OPR_INTRINSIC_CALL, Pointer_type, MTYPE_V);
01364 WN* intrinsic_call = WN_Create(op, 0);
01365 WN* sp_tmp_def;
01366
01367 WN_intrinsic(intrinsic_call) = Pointer_Size == 8 ?
01368 INTRN_U8READSTACKPOINTER :
01369 INTRN_U4READSTACKPOINTER;
01370 ST* rst = Find_Return_Registers(Pointer_type, &rreg1, &rreg2);
01371 FmtAssert(rreg1 != 0 && rreg2 == 0, ("Bad pointer type ret regs"));
01372
01373 LWN_Insert_Block_Before(LWN_Get_Parent(Call_Wn ()), Call_Wn (),
01374 intrinsic_call);
01375
01376 WN* rreg_ldid = WN_CreateLdid(ldop, rreg1, ST_st_idx(rst), pty);
01377 sp_tmp_def = LWN_CreateStid(stop, saved_sp, MTYPE_To_PREG(Pointer_type),
01378 pty, rreg_ldid);
01379
01380 LWN_Insert_Block_Before(LWN_Get_Parent(Call_Wn ()),Call_Wn (),
01381 sp_tmp_def);
01382 return saved_sp;
01383 }
01384
01385
01386
01387 void IPO_INLINE::Process_Alloca_Postamble(PREG_NUM saved_sp)
01388 {
01389
01390 Set_Tables (Caller_node ());
01391
01392 TY_IDX pty = Make_Pointer_Type(Be_Type_Tbl(Pointer_type), TRUE);
01393 OPCODE ldop = OPCODE_make_op(OPR_LDID, Pointer_type, Pointer_type);
01394 OPCODE icallop = OPCODE_make_op(OPR_INTRINSIC_CALL, MTYPE_V, MTYPE_V);
01395 WN *intrinsic_call = WN_Create(icallop, 1);
01396 WN* wn_callarg;
01397 WN_intrinsic(intrinsic_call) = Pointer_Size == 8 ?
01398 INTRN_U8I8SETSTACKPOINTER :
01399 INTRN_U4I4SETSTACKPOINTER;
01400 wn_callarg = WN_CreateLdid(ldop, saved_sp,
01401 ST_st_idx(MTYPE_To_PREG(Pointer_type)),
01402 Be_Type_Tbl(Pointer_type) );
01403
01404
01405 WN* tmp=WN_CreateParm(Pointer_type,wn_callarg,pty,WN_PARM_BY_VALUE);
01406 LWN_Set_Parent(wn_callarg, tmp);
01407 wn_callarg = tmp;
01408
01409 WN_kid0(intrinsic_call) = wn_callarg;
01410 LWN_Set_Parent(wn_callarg, intrinsic_call);
01411 LWN_Insert_Block_After(LWN_Get_Parent(Call_Wn ()), Call_Wn (), intrinsic_call);
01412
01413 }
01414
01415
01416
01417
01418
01419 extern void
01420 Init_inline()
01421 {
01422
01423 Init_Operator_To_Opcode_Table();
01424 }
01425
01426
01427
01428
01429
01430 WN_MAP_TAB *caller_map_tab;
01431 WN_MAP_TAB *callee_map_tab;
01432
01433
01434
01435
01436
01437
01438 IPO_INLINE::IPO_INLINE (IPA_NODE *caller_node,
01439 IPA_NODE *callee_node,
01440 IPA_EDGE *edge) :
01441 _caller_node(caller_node), _callee_node(callee_node), _call_edge(edge)
01442 {
01443
01444 #if 0
01445 {
01446
01447
01448 IPA_NODE_CONTEXT caller_context (caller_node);
01449 IPA_NODE_CONTEXT callee_context (caller_node);
01450 }
01451 #endif
01452
01453 IP_FILE_HDR& file_hdr_caller = Caller_node()->File_Header ();
01454 IP_FILE_HDR& file_hdr_callee = Callee_node()->File_Header ();
01455
01456
01457 caller_map_tab =
01458 PU_Info_maptab(file_hdr_caller.proc_info[Caller_node()->Proc_Info_Index()].info);
01459
01460 callee_map_tab =
01461 PU_Info_maptab(file_hdr_callee.proc_info[Callee_node()->Proc_Info_Index()].info);
01462
01463 Parent_Map = caller_node->Parent_Map();
01464
01465
01466 Current_Map_Tab = caller_map_tab;
01467
01468 Set_symtab(NULL);
01469
01470 #ifndef _LIGHTWEIGHT_INLINER
01471 WN_mem_pool_ptr = Caller_node()->Mem_Pool();
01472 #else // _LIGHTWEIGHT_INLINER
01473 if (INLINE_Use_Malloc_Mempool)
01474 WN_mem_pool_ptr = Malloc_Mem_Pool;
01475 else
01476 WN_mem_pool_ptr = Caller_node()->Mem_Pool();
01477 #endif // _LIGHTWEIGHT_INLINER
01478
01479
01480 _flags = 0;
01481
01482 #if (!defined(_STANDALONE_INLINER) && !defined(_LIGHTWEIGHT_INLINER))
01483 if (IPA_Enable_DST) {
01484 Set_callee_cross_file_id(DST_get_cross_file_id (Caller_dst(),
01485 Callee_dst(),
01486 Caller_file_dst(),
01487 Callee_file_dst()));
01488 }
01489 #endif // _STANDALONE_INLINER
01490
01491 }
01492
01493
01494
01495
01496
01497
01498
01499
01500
01501
01502
01503 static void
01504 Propagate_Flags (IPA_NODE* caller_node, IPA_NODE* callee_node)
01505 {
01506 PU_IDX caller_pu_idx = ST_pu (caller_node->Func_ST());
01507 PU_IDX callee_pu_idx = ST_pu (callee_node->Func_ST());
01508
01509
01510 Pu_Table[caller_pu_idx].flags |= PU_HAS_INLINES;
01511
01512
01513
01514
01515
01516
01517 Pu_Table[caller_pu_idx].flags |=
01518 (Pu_Table[callee_pu_idx].flags & (PU_HAS_EXC_SCOPES |
01519 PU_NEEDS_FILL_ALIGN_LOWERING |
01520 PU_HAS_VERY_HIGH_WHIRL |
01521 PU_MP_NEEDS_LNO |
01522 PU_HAS_ALLOCA |
01523 PU_HAS_MP |
01524 PU_HAS_NAMELIST |
01525 PU_HAS_REGION ));
01526
01527 }
01528
01529
01530
01531
01532
01533
01534
01535
01536
01537 static void
01538 Recognize_Caller_MP (IPA_NODE* caller, IPA_NODE* callee)
01539 {
01540
01541
01542 SUMMARY_PROCEDURE* caller_proc = caller->Summary_Proc ();
01543 SUMMARY_PROCEDURE* callee_proc = callee->Summary_Proc ();
01544
01545 if (callee_proc->Has_parallel_pragma()) {
01546 caller_proc->Set_has_parallel_pragma();
01547 }
01548
01549 if (callee_proc->Has_parallel_region_pragma()) {
01550 caller_proc->Set_has_parallel_region_pragma();
01551 }
01552 }
01553
01554
01555
01556 static void
01557 Insert_Block_Around (WN* parent, WN* wn, WN* before, WN* after)
01558 {
01559 static char msg[] = "Invalid argument to Insert_Block_Around";
01560
01561 Is_True (wn && parent && WN_operator (parent) == OPR_BLOCK, (msg));
01562
01563 if (before) {
01564 if (WN_operator (before) == OPR_BLOCK) {
01565 if (WN_first (before) != NULL) {
01566
01567 WN* first = WN_first (before);
01568 WN* last = WN_last (before);
01569 WN_prev (first) = WN_prev (wn);
01570 WN_next (last) = wn;
01571 WN_prev (wn) = last;
01572 if (WN_prev (first))
01573 WN_next (WN_prev (first)) = first;
01574 else
01575 WN_first (parent) = first;
01576 }
01577 } else {
01578 Is_True (OPERATOR_has_next_prev (WN_operator (before)), (msg));
01579 WN_prev (before) = WN_prev (wn);
01580 WN_next (before) = wn;
01581 WN_prev (wn) = before;
01582 if (WN_prev (before))
01583 WN_next (WN_prev (before)) = before;
01584 else
01585 WN_first (parent) = before;
01586 }
01587 }
01588
01589 if (after) {
01590 if (WN_operator (after) == OPR_BLOCK) {
01591 if (WN_first (after) != NULL) {
01592 WN* first = WN_first (after);
01593 WN* last = WN_last (after);
01594 WN_next (last) = WN_next (wn);
01595 WN_prev (first) = wn;
01596 WN_next (wn) = first;
01597 if (WN_next (last))
01598 WN_prev (WN_next (last)) = last;
01599 else
01600 WN_last (parent) = last;
01601 }
01602 } else {
01603 Is_True (OPERATOR_has_next_prev (WN_operator (after)), (msg));
01604 WN_next (after) = WN_next (wn);
01605 WN_prev (after) = wn;
01606 WN_next (wn) = after;
01607 if (WN_next (after))
01608 WN_prev (WN_next (after)) = after;
01609 else
01610 WN_last (parent) = after;
01611 }
01612 }
01613 }
01614
01615
01616
01617
01618
01619
01620
01621
01622 static void
01623 Insert_Labels (WN *Call, LABEL_IDX return_label, LABEL_IDX entry_label,
01624 WN* inlined_block)
01625 {
01626
01627
01628 WN* parent_wn = WN_Get_Parent(Call, Parent_Map, Current_Map_Tab);
01629
01630 Is_True((parent_wn != NULL), ("Invalid Block in Insert Label \n"));
01631 Is_True(((WN_operator(parent_wn) == OPR_BLOCK)),
01632 ("Illegal Parent for the call statement"));
01633
01634
01635
01636 WN* ret_wn;
01637 if (return_label) {
01638 ret_wn = WN_CreateLabel (return_label, 0, NULL);
01639
01640
01641 Is_True (WN_operator (inlined_block) == OPR_BLOCK,
01642 ("invalid inlined body"));
01643 WN* wn_goto = WN_last (inlined_block);
01644 if ((wn_goto != NULL) && (WN_operator (wn_goto) == OPR_GOTO)) {
01645 if (WN_label_number (wn_goto) == return_label) {
01646 WN_last (inlined_block) = WN_prev (wn_goto);
01647 if (WN_prev (wn_goto))
01648 WN_next (WN_prev (wn_goto)) = NULL;
01649 else
01650 WN_first (inlined_block) = NULL;
01651 }
01652 }
01653 } else
01654 ret_wn = NULL;
01655
01656 WN* entry_wn = entry_label ? WN_CreateLabel (entry_label, 0, NULL) : NULL;
01657
01658 Insert_Block_Around (parent_wn, Call, entry_wn, ret_wn);
01659
01660 }
01661
01662
01663
01664
01665
01666
01667
01668
01669
01670 static void
01671 Save_And_Restore_Stack (WN* call)
01672 {
01673
01674 WN* parent_wn = WN_Get_Parent(call, Parent_Map, Current_Map_Tab);
01675
01676 Is_True((parent_wn != NULL), ("Invalid Block in Insert Label \n"));
01677 Is_True(((WN_operator(parent_wn) == OPR_BLOCK)),
01678 ("Illegal Parent for the call statement"));
01679
01680 PREG_NUM sp = Create_Preg (Pointer_Mtype, "sp");
01681 WN* save = WN_StidIntoPreg (Pointer_Mtype, sp,
01682 MTYPE_To_PREG (Pointer_Mtype),
01683 WN_CreateAlloca (WN_Intconst (MTYPE_U4, 0)));
01684
01685 WN* restore = WN_CreateDealloca (1);
01686 WN_kid0 (restore) = WN_LdidPreg (Pointer_Mtype, sp);
01687
01688 Insert_Block_Around (parent_wn, call, save, restore);
01689
01690 }
01691
01692 void
01693 IPO_INLINE::Pre_Process_Caller (LABEL_IDX& return_label)
01694 {
01695
01696 Set_Tables (Caller_node ());
01697
01698
01699
01700
01701
01702 Recognize_Caller_MP (Caller_node (), Callee_node ());
01703
01704 if (Callee_Summary_Proc()->Has_early_returns())
01705 New_LABEL (Caller_level (), return_label);
01706 else
01707 return_label = 0;
01708
01709 }
01710
01711
01712
01713 static inline void
01714 Replace_Return_By_Goto (TREE_ITER& iter, LABEL_IDX ret_label)
01715 {
01716
01717 iter.Replace (WN_CreateGoto( (ST_IDX) 0, ret_label));
01718 }
01719
01720
01721
01722
01723
01724 WN *
01725 IPO_INLINE::Clone_Callee(BOOL same_file)
01726 {
01727
01728
01729 IPO_CLONE copy(caller_map_tab, callee_map_tab,
01730 Parent_Map,
01731 Callee_Scope(), Caller_Scope(),
01732 Callee_level(), Caller_level(),
01733 Callee_node()->Cloned_Symtab(),
01734 &Ipo_mem_pool,
01735 same_file, 0);
01736
01737
01738 if (!Callee_node()->Cloned_Symtab()) {
01739 if (Callee_node()->Has_Pstatics ()) {
01740 copy.Promote_Statics();
01741 Callee_node()->Clear_Has_Pstatics();
01742 }
01743
01744 copy.Get_sym()->Update_Symtab(FALSE);
01745
01746 Set_symtab(copy.Get_sym());
01747
01748 Callee_node()->Set_Cloned_Symtab(Symtab());
01749 }
01750 else {
01751 copy.Get_sym()->Update_Symtab(TRUE);
01752 Set_symtab(Callee_node()->Cloned_Symtab());
01753 }
01754
01755 WN *result = copy.Clone_Tree(WN_func_body(Callee_Wn ()));
01756
01757 #if (!defined(_STANDALONE_INLINER) && !defined(_LIGHTWEIGHT_INLINER))
01758
01759 if (Caller_node ()->Has_frequency ()) {
01760 FB_FREQ call_freq = Call_edge()->Get_frequency();
01761 if (call_freq.Known ()) {
01762 FB_FREQ callee_freq = Callee_node ()->Has_frequency () ?
01763 Callee_node()->Get_frequency() : FB_FREQ_UNKNOWN;
01764 FB_FREQ scale (FB_FREQ_ZERO);
01765 if (! callee_freq.Known ()) {
01766 DevWarn ("Inconsistent freq. count between callsite in %s and"
01767 " callee %s", Caller_node()->Name (),
01768 Callee_node()->Name ());
01769 } else {
01770 scale = call_freq / callee_freq;
01771 SUMMARY_FEEDBACK* fb = Callee_node ()->Get_feedback ();
01772 fb->Set_frequency_count (callee_freq - call_freq);
01773 }
01774
01775 #ifdef _DEBUG_TEST
01776 printf("scale for %s in %s is %f", Callee_node()->Name(), Caller_node()->Name(), scale);
01777 printf(", callee_freq = %f", callee_freq.Value());
01778 printf(", call_freq = %f\n", call_freq.Value());
01779 #endif // _DEBUG_TEST
01780
01781 FB_IPA_Inline (Callee_node()->Feedback_Info(),
01782 Caller_node()->Feedback_Info(),
01783 Callee_Wn (), result, scale);
01784
01785 }
01786 }
01787 #endif // _STANDALONE_INLINER
01788
01789 return (result);
01790
01791 }
01792
01793
01794 void
01795 IPO_INLINE::Process_OPR_REGION(WN* wn, IPA_NODE* caller_node)
01796 {
01797
01798
01799 PU& caller_pu = Pu_Table[ST_pu(caller_node->Func_ST())];
01800
01801 if (PU_has_region(caller_pu)) {
01802
01803 UINT32 region_id = caller_node->Max_Region_Id();
01804
01805 if (region_id == 0) {
01806 region_id = Compute_max_region_id (caller_node->Whirl_Tree ());
01807 }
01808
01809 ++region_id;
01810 caller_node-> Set_Max_Region_Id(region_id);
01811 WN_set_region_id(wn, region_id);
01812 } else
01813 caller_node-> Set_Max_Region_Id(WN_region_id(wn));
01814
01815
01816 if (WN_region_is_EH(wn)) {
01817 INITO_IDX init_idx = WN_ereg_supp (wn);
01818
01819 if (init_idx) {
01820
01821 pair<ST*, WN_OFFSET> sym = Create_Copy_In_Symbol (INITO_st(init_idx));
01822 ST* copy_st = sym.first;
01823 Clear_ST_is_temp_var (copy_st);
01824 Set_ST_is_not_used (INITO_st(init_idx));
01825 Set_ST_storage_class (*copy_st, ST_storage_class(*INITO_st(init_idx)));
01826 Set_INITO_st_idx(init_idx, ST_st_idx(copy_st));
01827
01828 INITV_IDX val_idx = INITO_val(init_idx);
01829
01830 if (val_idx < initial_initv_tab_size) {
01831 Set_INITO_val(init_idx,
01832 Symtab()->Clone_INITVs_For_EH(INITO_val(init_idx), init_idx));
01833 }
01834 #ifdef KEY
01835
01836
01837
01838 if (WN_block_empty (WN_region_pragmas (wn)) &&
01839 Call_edge()->EH_Whirl_Node()) {
01840 INITV_IDX initv = INITV_blk (INITO_val (init_idx));
01841
01842 INITO_IDX enclosing = WN_ereg_supp (Call_edge()->EH_Whirl_Node());
01843 INITV_IDX e_initv = INITV_blk (INITO_val (enclosing));
01844 if (INITV_kind(initv) == INITVKIND_ZERO) {
01845
01846 if (INITV_kind(e_initv) != INITVKIND_ZERO) {
01847 INITV_IDX insert = New_INITV();
01848 INITV_Init_Block (INITO_val(init_idx), insert);
01849 while (e_initv) {
01850 memcpy (&Initv_Table[insert], &Initv_Table[e_initv], sizeof(INITV));
01851 e_initv = INITV_next (e_initv);
01852 if (e_initv) {
01853 INITV_IDX prev = insert;
01854 insert = New_INITV();
01855 Set_INITV_next (prev, insert);
01856 }
01857 }
01858 }
01859 } else {
01860
01861
01862
01863 INITV_IDX last_initv = INITV_IDX_ZERO;
01864 while (initv)
01865 {
01866 if (INITV_kind (initv) == INITVKIND_VAL)
01867 {
01868 int sym = TCON_uval (INITV_tc_val (initv));
01869 if (sym < 0)
01870 {
01871 int new_ofst = -(mINT32)(-sym +
01872 caller_node->EH_spec_size());
01873 INITV_IDX bkup = INITV_next (initv);
01874 INITV_Set_VAL (Initv_Table[initv],
01875 Enter_tcon (Host_To_Targ (MTYPE_I4,
01876 new_ofst)), 1);
01877 Set_INITV_next (initv, bkup);
01878 }
01879 }
01880 last_initv = initv;
01881 initv = INITV_next(initv);
01882 }
01883 initv = last_initv;
01884
01885
01886 e_initv = INITV_next (e_initv);
01887 while (e_initv) {
01888 INITV_IDX insert = New_INITV();
01889 memcpy (&Initv_Table[insert], &Initv_Table[e_initv], sizeof(INITV));
01890 Set_INITV_next (initv, insert);
01891 initv = insert;
01892 e_initv = INITV_next (e_initv);
01893 }
01894 }
01895 } else if (WN_block_empty (WN_region_pragmas (wn))) {
01896
01897
01898 INITV_IDX initv = INITV_blk (INITO_val (init_idx));
01899 if (INITV_kind (initv) != INITVKIND_ZERO) {
01900 while (initv) {
01901 if (INITV_kind (initv) == INITVKIND_VAL) {
01902 int sym = TCON_uval (INITV_tc_val (initv));
01903 if (sym < 0) {
01904 int new_ofst = -(mINT32)(-sym +
01905 caller_node->EH_spec_size());
01906 INITV_IDX bkup = INITV_next (initv);
01907 INITV_Set_VAL (Initv_Table[initv],
01908 Enter_tcon (Host_To_Targ (MTYPE_I4,
01909 new_ofst)), 1);
01910 Set_INITV_next (initv, bkup);
01911 }
01912 }
01913 initv = INITV_next(initv);
01914 }
01915 }
01916 }
01917 #endif
01918 }
01919
01920
01921
01922
01923
01924
01925 UINT inito_size = Get_INITO_Size(init_idx);
01926 ST* temp_st = INITO_st (init_idx);
01927 TY_IDX tyi;
01928 TY& zty = New_TY (tyi);
01929 TY_Init (zty, inito_size, KIND_STRUCT, MTYPE_M,temp_st->u1.name_idx);
01930 Set_TY_align (tyi, 4);
01931 temp_st->u2.type = tyi;
01932 }
01933
01934 Set_PU_has_region(caller_pu);
01935 }
01936
01937 static vector<TY_IDX, mempool_allocator<TY_IDX> > processed_types (Malloc_Mem_Pool);
01938
01939 static BOOL
01940 ty_processed(TY_IDX ty)
01941 {
01942 for (int i = 0; i < processed_types.size(); ++i) {
01943 if (TY_IDX_index(processed_types[i]) == TY_IDX_index(ty))
01944 return TRUE;
01945 }
01946 return FALSE;
01947 }
01948
01949 static void
01950 fix_var_dim_array(TY_IDX ty, IPO_SYMTAB* symtab)
01951 {
01952 if (TY_kind(ty) == KIND_POINTER)
01953 ty = TY_pointed(ty);
01954
01955 if (TY_kind(ty) == KIND_ARRAY) {
01956
01957 if (ty_processed(ty))
01958
01959 return;
01960
01961 ARB_ITER arb_iter = Make_arb_iter (ARB_HANDLE (TY_arb(ty)));
01962 UINT dim = ARB_dimension (arb_iter);
01963 processed_types.push_back(ty);
01964 for (UINT i = 0; i < dim; ++i) {
01965 ARB_HANDLE arb (arb_iter);
01966 if (!ARB_const_lbnd(arb)) {
01967 ST_IDX idx = ARB_lbnd_var(arb);
01968 if (ST_IDX_index(idx) != 0)
01969 Set_ARB_lbnd_var(arb, ST_st_idx(symtab->Get_ST(ST_ptr(idx))));
01970 }
01971 if (!ARB_const_ubnd(arb)) {
01972 ST_IDX idx = ARB_ubnd_var(arb);
01973 if (ST_IDX_index(idx) != 0)
01974 Set_ARB_ubnd_var(arb, ST_st_idx(symtab->Get_ST(ST_ptr(idx))));
01975 }
01976 if (!ARB_const_stride(arb)) {
01977 ST_IDX idx = ARB_stride_var(arb);
01978 if (ST_IDX_index(idx) != 0)
01979 Set_ARB_stride_var(arb, ST_st_idx(symtab->Get_ST(ST_ptr(idx))));
01980 }
01981 ++arb_iter;
01982 }
01983 fix_var_dim_array(TY_etype(ty), symtab);
01984 }
01985 }
01986
01987
01988
01989
01990
01991
01992 void
01993 IPO_INLINE::Process_Op_Code (TREE_ITER& iter, IPO_INLINE_AUX& aux)
01994 {
01995 WN* wn = iter.Wn ();
01996 #if defined(KEY) && !defined(_STANDALONE_INLINER) && !defined(_LIGHTWEIGHT_INLINER)
01997
01998
01999
02000 if (OPERATOR_has_next_prev(WN_operator(wn)))
02001 WN_Set_Linenum (wn, WN_Get_Linenum (Call_Wn()));
02002 #endif // KEY && !_STANDALONE_INLINER && !_LIGHTWEIGHT_INLINER
02003 OPERATOR oper = WN_operator (wn);
02004 switch(oper) {
02005 case OPR_RETURN_VAL:
02006
02007
02008
02009
02010
02011 if (WN_operator (WN_kid0 (wn)) == OPR_LDA) {
02012 ST* st = WN_st(WN_kid0 (wn));
02013 if (st != NULL)
02014 Set_ST_addr_saved(st);
02015 }
02016 else
02017 if (WN_operator (WN_kid0 (wn)) == OPR_COMMA) {
02018 WN *wn1 = WN_kid0 (wn);
02019
02020 do {
02021 wn1 = WN_kid1 (wn1);
02022 } while (WN_operator (wn1) == OPR_COMMA);
02023 if (WN_operator (wn1) == OPR_LDA) {
02024 ST* st = WN_st(wn1);
02025 if (st != NULL)
02026 Set_ST_addr_saved(st);
02027 }
02028 }
02029 if (WN_rtype (WN_kid0 (wn)) == MTYPE_M) {
02030 ST* tmp_st = aux.rp.find_st ();
02031 #ifdef KEY
02032 TY_IDX stid_ty = ST_type(tmp_st);
02033 #else
02034 TY_IDX stid_ty = WN_ty(WN_kid0(wn));
02035 #endif // KEY
02036
02037 #if (defined(_STANDALONE_INLINER) || defined(_LIGHTWEIGHT_INLINER))
02038 if (stid_ty == 0) {
02039
02040
02041 stid_ty = WN_ty(WN_kid1(WN_kid0(wn)));
02042 }
02043 #endif // _STANDALONE_INLINER
02044 iter.Insert (WN_Stid (MTYPE_M, 0, tmp_st, stid_ty,
02045 WN_kid0 (wn)));
02046 } else
02047 iter.Insert (WN_StidIntoPreg (TY_mtype (ST_type (aux.rp.find_st())),
02048 aux.rp.find ((PREG_IDX) -1),
02049 aux.rp.find_st (),
02050 WN_kid0 (wn)));
02051
02052 ++iter;
02053
02054
02055
02056 WN_set_operator (wn, OPR_RETURN);
02057 #ifdef KEY
02058
02059 WN_set_rtype (wn, MTYPE_V);
02060 WN_set_desc (wn, MTYPE_V);
02061 #endif
02062 return;
02063
02064 case OPR_RETURN:
02065
02066
02067 if (Callee_Summary_Proc()->Has_early_returns())
02068 Replace_Return_By_Goto (iter, aux.return_label);
02069 else {
02070 iter.Delete ();
02071 return;
02072 }
02073 break;
02074
02075
02076 case OPR_EXC_SCOPE_BEGIN:
02077 Fail_FmtAssertion ("Invalid opcode from old style Exception Processing\n");
02078 break;
02079
02080 case OPR_REGION:
02081 Process_OPR_REGION (wn, Caller_node ());
02082 break;
02083
02084 case OPR_PRAGMA:
02085 case OPR_XPRAGMA:
02086
02087 if (oper == OPR_PRAGMA && WN_pragma(wn) == WN_PRAGMA_PREAMBLE_END) {
02088 iter.Delete ();
02089 return;
02090 } else {
02091 const ST* st;
02092 switch (WN_pragma(wn)) {
02093 case WN_PRAGMA_DISTRIBUTE:
02094 case WN_PRAGMA_DISTRIBUTE_RESHAPE:
02095 case WN_PRAGMA_DYNAMIC:
02096 st = WN_st (wn);
02097 if (st && (ST_sclass(st) == SCLASS_FSTATIC ||
02098 ST_sclass(st) == SCLASS_EXTERN ||
02099 ST_sclass(st) == SCLASS_UGLOBAL ||
02100 ST_sclass(st) == SCLASS_DGLOBAL ||
02101 ST_sclass(st) == SCLASS_COMMON ||
02102 (ST_base(st) &&
02103 ST_sclass(ST_base(st)) == SCLASS_COMMON))) {
02104 iter.Delete ();
02105 return;
02106 }
02107 default:
02108 break;
02109 }
02110 }
02111 break;
02112
02113 #if 0
02114 case OPR_PARM:
02115 if (IPA_Enable_Inline_Var_Dim_Array && Callee_Summary_Proc()->Has_var_dim_array())
02116 fix_var_dim_array(WN_ty(wn), Symtab());
02117 break;
02118 #endif
02119 #ifdef KEY
02120 case OPR_CALL:
02121 {
02122 WN * kid0;
02123 if (WN_kid_count(wn) == 1 && (kid0 = WN_kid0 (WN_kid0 (wn))))
02124 {
02125 if (WN_operator (kid0) == OPR_LDID &&
02126 ST_one_per_pu (&St_Table[WN_st_idx (kid0)]))
02127 {
02128 ST_IDX i = WN_st_idx (wn);
02129 char * func_name = ST_name (St_Table[i]);
02130 Is_True (func_name &&
02131 (!strcmp (func_name, "_Unwind_Resume") ||
02132 !strcmp (func_name, "__cxa_call_unexpected") ||
02133 !strcmp (func_name, "__cxa_begin_catch") ||
02134 !strcmp (func_name, "__cxa_get_exception_ptr")),
02135 ("Function %s has one-per-pu paramter", func_name));
02136
02137 INITV_IDX exc_ptr = INITO_val ((INITO_IDX) PU_misc_info (Get_Current_PU ()));
02138 WN_st_idx (kid0) = TCON_uval (INITV_tc_val (exc_ptr));
02139 }
02140 }
02141 }
02142 break;
02143 case OPR_EQ:
02144 if (WN_operator (WN_kid0 (wn)) == OPR_LDID &&
02145 ST_one_per_pu (&St_Table[WN_st_idx (WN_kid0 (wn))]))
02146 {
02147
02148
02149
02150
02151
02152
02153
02154
02155
02156
02157
02158
02159 INITV_IDX first = INITO_val ((INITO_IDX) PU_misc_info (Get_Current_PU ()));
02160 WN_st_idx (WN_kid0 (wn)) = TCON_uval (INITV_tc_val (INITV_next (first)));
02161
02162 int current_filter = WN_const_val (WN_kid1 (wn));
02163
02164 if (current_filter < 0)
02165 {
02166 WN_const_val (WN_kid1 (wn)) = - (mINT32)(-current_filter + Caller_node()->EH_spec_size());
02167 break;
02168 }
02169 Set_Tables (Callee_node());
02170
02171 INITO_IDX ino = PU_misc_info (Pu_Table [ST_pu (Callee_node()->Func_ST())]);
02172 INITV_IDX tinfo = INITV_next (INITV_next (INITO_val (ino)));
02173 INITV_IDX ttable = INITO_val (TCON_uval (INITV_tc_val (tinfo)));
02174 int filter;
02175
02176 while (ttable)
02177 {
02178 filter = TCON_uval (INITV_tc_val (INITV_next (INITV_blk (ttable))));
02179 if (filter == current_filter)
02180 break;
02181 ttable = INITV_next (ttable);
02182 }
02183 FmtAssert (filter == current_filter, ("No matching ST for exception filter in callee typeinfo-table"));
02184 ST_IDX current_st = 0;
02185 {
02186 INITV_IDX i = INITV_blk (ttable);
02187 FmtAssert (INITV_kind (i) != INITVKIND_ZERO, ("Unexpected 0 st_idx for cmp operand"));
02188 current_st = TCON_uval (INITV_tc_val (i));
02189 }
02190 #ifdef Is_True_On
02191 {
02192 ST_SCLASS s = ST_sclass (St_Table[current_st]);
02193 FmtAssert (s == SCLASS_DGLOBAL || s == SCLASS_EXTERN, ("Typeinfo symbol should be global"));
02194 }
02195 #endif
02196 Set_Tables (Caller_node());
02197
02198 ttable = INITO_val (TCON_uval (INITV_tc_val (INITV_next (INITV_next (first)))));
02199
02200 ST_IDX search;
02201 while (ttable)
02202 {
02203 INITV_IDX i = INITV_blk (ttable);
02204 if (INITV_kind (i) == INITVKIND_ZERO)
02205 search = 0;
02206 else
02207 search = TCON_uval (INITV_tc_val (i));
02208 if (search == current_st)
02209 break;
02210 ttable = INITV_next (ttable);
02211 }
02212 FmtAssert (search == current_st, ("No matching ST for exception filter in merged caller typeinfo-table"));
02213
02214 WN_const_val (WN_kid1 (wn)) = TCON_uval (INITV_tc_val (INITV_next (INITV_blk (ttable))));
02215 }
02216 break;
02217 #endif
02218
02219 default:
02220 break;
02221 }
02222
02223 if (OPERATOR_has_sym (oper))
02224 Process_ST (iter, aux);
02225 else
02226 ++iter;
02227 }
02228
02229
02230
02231
02232 static void
02233 Process_Pregs(WN* w, const RETURN_PREG& rp)
02234 {
02235 INT offst;
02236
02237
02238
02239 if (WN_operator(w) == OPR_PRAGMA)
02240 offst = WN_pragma_arg1(w);
02241 else
02242 offst = WN_offset(w);
02243
02244
02245 if (WN_operator (w) == OPR_STID) {
02246 if (offst == -1) {
02247 WN_st_idx (w) = ST_st_idx (rp.find_st ());
02248 if (WN_desc (w) == MTYPE_M)
02249 WN_offset (w) = 0;
02250 else
02251 WN_offset (w) = rp.find (offst);
02252 } else if (Preg_Is_Dedicated(offst))
02253 WN_offset (w) = rp.find (offst);
02254 }
02255 }
02256
02257
02258
02259
02260 static BOOL
02261 has_array_reference (WN* wn)
02262 {
02263 TREE_ITER iter (wn);
02264 while (iter.Wn () != NULL) {
02265 WN* wn = iter.Wn ();
02266 OPERATOR opr = WN_operator (wn);
02267 if (OPERATOR_has_sym (opr)) {
02268 ST* st = WN_st (wn);
02269 if (st != NULL && ST_sclass (st) == SCLASS_FORMAL &&
02270 TY_kind (ST_type (st)) == KIND_POINTER &&
02271 TY_kind (TY_pointed (ST_type (st))) == KIND_ARRAY)
02272 return TRUE;
02273 }
02274 ++iter;
02275 }
02276 return FALSE;
02277 }
02278
02279
02280
02281
02282
02283
02284
02285
02286 static BOOL
02287 Unaliased_Actuals_Useful (WN* wn)
02288 {
02289 TREE_ITER iter (wn);
02290 while (iter.Wn () != NULL) {
02291 OPERATOR opr = WN_operator (iter.Wn ());
02292 switch (opr) {
02293 case OPR_DO_LOOP:
02294 case OPR_DO_WHILE:
02295 case OPR_WHILE_DO:
02296 if (has_array_reference (iter.Wn ()))
02297 return TRUE;
02298 iter.Skip ();
02299 break;
02300
02301 default:
02302 if (OPERATOR_is_stmt (opr))
02303 iter.Skip ();
02304 else
02305 ++iter;
02306 break;
02307 }
02308 }
02309 return FALSE;
02310 }
02311
02312
02313
02314
02315
02316 static ST *
02317 Get_Array_ST (WN *wn)
02318 {
02319 TREE_ITER iter (wn);
02320 while (iter.Wn () != NULL) {
02321 WN* w = iter.Wn ();
02322 ST* st;
02323 switch (WN_operator (w)) {
02324 case OPR_LDA:
02325 st = WN_st (w);
02326 if (TY_kind (ST_type (st)) == KIND_ARRAY)
02327 return st;
02328 ++iter;
02329 break;
02330 case OPR_LDID:
02331 st = WN_st (w);
02332 {
02333 const TY& ty = Ty_Table[ST_type (st)];
02334 if (TY_kind (ty) == KIND_POINTER &&
02335 TY_kind (TY_pointed (ty)) == KIND_ARRAY)
02336 return st;
02337 }
02338 ++iter;
02339 break;
02340 case OPR_ILOAD:
02341 iter.Skip();
02342 break;
02343 default:
02344 ++iter;
02345 }
02346 }
02347 return NULL;
02348 }
02349
02350
02351 static inline BOOL
02352 Is_Scalar_Formal_Ref (const ST* st)
02353 {
02354 if (ST_sclass (st) != SCLASS_FORMAL_REF)
02355 return FALSE;
02356
02357 TY& ty = Ty_Table[ST_type (st)];
02358
02359 if (TY_kind (ty) == KIND_POINTER || TY_kind (ty) == KIND_ARRAY)
02360 return FALSE;
02361 return TRUE;
02362 }
02363
02364
02365
02366
02367
02368
02369
02370
02371
02372
02373
02374 static void
02375 Disambiguate_Aliased_Actuals (PARM_ATTR_VEC& parm_attr, PU& pu)
02376 {
02377 UINT i;
02378 const UINT num_parm = parm_attr.size ();
02379 ST** actuals = (ST**) alloca (num_parm * sizeof(ST*));
02380
02381
02382 for (i = 0; i < num_parm; ++i) {
02383 actuals[i] = Get_Array_ST (parm_attr[i].Actual_Wn ());
02384 }
02385
02386 BOOL done = TRUE;
02387 BOOL* aliased = (BOOL*) alloca (num_parm * sizeof(BOOL));
02388 BOOL* scalar = (BOOL*) alloca (num_parm * sizeof(BOOL));
02389
02390 BZERO (aliased, sizeof(BOOL)*num_parm);
02391 BZERO (scalar, sizeof(BOOL)*num_parm);
02392
02393
02394 for (i = 0; i < num_parm; ++i) {
02395 ST* st = actuals[i];
02396 if (st == NULL) {
02397 aliased[i] = scalar[i] = FALSE;
02398 continue;
02399 } else if (aliased[i])
02400 continue;
02401
02402 for (INT j = i + 1; j < num_parm; ++j) {
02403 if (st == actuals[j]) {
02404 aliased[j] = aliased[i] = TRUE;
02405 done = FALSE;
02406 scalar[j] = Is_Scalar_Formal_Ref (parm_attr[j].Formal_St ());
02407 }
02408 }
02409 if (aliased[i])
02410 scalar[i] = Is_Scalar_Formal_Ref (parm_attr[i].Formal_St ());
02411 }
02412
02413 if (done)
02414 return;
02415
02416
02417
02418
02419
02420
02421
02422 done = FALSE;
02423 for ( i = 0; i < num_parm; ++i) {
02424 if (! aliased[i] || parm_attr[i].Actual_Aliased () != NULL)
02425 continue;
02426 if (scalar[i]) {
02427 parm_attr[i].Set_actual_aliased (actuals[i]);
02428 parm_attr[i].Set_pass_method (PM_COPY_IN_OUT);
02429 parm_attr[i].Set_fixup_method (FM_REPLACE_ST);
02430 continue;
02431 }
02432
02433 for (UINT j = i + 1; j < num_parm; ++j) {
02434 if (aliased[j] && !scalar[j] && actuals[i] == actuals[j]) {
02435
02436 parm_attr[i].Set_actual_aliased (actuals[i]);
02437 parm_attr[i].Set_pass_method (PM_NEED_BARRIER);
02438 parm_attr[i].Set_fixup_method (FM_REPLACE_ST);
02439
02440 parm_attr[j].Set_actual_aliased (actuals[j]);
02441 parm_attr[j].Set_pass_method (PM_NEED_BARRIER);
02442 parm_attr[j].Set_fixup_method (FM_REPLACE_ST);
02443
02444 Set_PU_smart_addr_analysis (pu);
02445 }
02446 }
02447 }
02448 }
02449
02450
02451 namespace {
02452
02453 typedef pair<ST*, BOOL> BARRIER_ST;
02454
02455 struct barrier_st_cmp {
02456 BOOL operator() (BARRIER_ST st1, BARRIER_ST st2) const {
02457 if (st1.first == st2.first)
02458 return st1.second < st2.second;
02459 return st1.first < st2.first;
02460 }
02461 };
02462
02463 }
02464
02465
02466
02467
02468
02469
02470
02471 static void
02472 Generate_Barriers (WN* parent, WN* call, IPO_INLINE_AUX& aux)
02473 {
02474 PARM_ATTR_VEC& parm_attr = aux.parm_attr;
02475
02476 vector<BARRIER_ST, mempool_allocator<BARRIER_ST> >
02477 actual_list (&Ipo_mem_pool);
02478 actual_list.reserve (parm_attr.size ());
02479
02480 UINT num_barrier_formal = 0;
02481 PARM_ITER p (parm_attr.begin ());
02482 for (; p != parm_attr.end (); ++p) {
02483 ST* st = p->Actual_Aliased ();
02484 if (st != NULL) {
02485 BOOL use_lda = p->Restrict_Pointer ();
02486 if (! use_lda) {
02487 if (TY_kind (ST_type (st)) == KIND_ARRAY)
02488 use_lda = TRUE;
02489 else {
02490
02491 Is_True (TY_kind (ST_type (st)) == KIND_POINTER &&
02492 TY_kind (TY_pointed (ST_type (st))) == KIND_ARRAY,
02493 ("Invalid symbol for barriers"));
02494 }
02495 }
02496 actual_list.push_back (BARRIER_ST (st, use_lda));
02497 }
02498 if (p->Pass_Method () == PM_NEED_BARRIER)
02499 ++num_barrier_formal;
02500 }
02501
02502 if (actual_list.size () == 0)
02503 return;
02504
02505
02506 sort (actual_list.begin (), actual_list.end (), barrier_st_cmp ());
02507 UINT size = unique (actual_list.begin (), actual_list.end ()) -
02508 actual_list.begin ();
02509
02510
02511 WN* before = WN_CreateBarrier (TRUE , size);
02512 WN* after = WN_CreateBarrier (FALSE , size);
02513
02514 for (UINT i = 0; i < size; ++i) {
02515 ST* st = actual_list[i].first;
02516 WN* lvalue = actual_list[i].second ?
02517 WN_Lda (Pointer_Mtype, 0, st) :
02518 WN_Ldid (Pointer_Mtype, 0, ST_st_idx (st), ST_type (st));
02519
02520 WN_kid (before, i) = lvalue;
02521 WN_kid (after, i) = IPO_Copy_Tree (lvalue);
02522 }
02523
02524 Insert_Block_Around (parent, call, before, after);
02525
02526
02527
02528 before = WN_CreateBarrier (FALSE , num_barrier_formal);
02529 after = WN_CreateBarrier (TRUE , num_barrier_formal);
02530
02531 UINT j = 0;
02532 for ( p = parm_attr.begin (); p != parm_attr.end (); ++p) {
02533 if (p->Pass_Method () != PM_NEED_BARRIER)
02534 continue;
02535
02536 Is_True (TY_kind (ST_type (p->Formal_St ())) == KIND_POINTER,
02537 ("Invalid formal symbol for barriers"));
02538 Is_True (p->Replace_St () != 0, ("Missing barrier symbols"));
02539 WN* lvalue = WN_Ldid (Pointer_Mtype, 0, p->Replace_St (),
02540 ST_type (p->Formal_St ()));
02541 WN_kid (before, j) = lvalue;
02542 WN_kid (after, j) = IPO_Copy_Tree (lvalue);
02543 ++j;
02544 }
02545
02546 Insert_Block_Around (parent, call, before, after);
02547
02548 }
02549
02550
02551
02552
02553
02554
02555 static void
02556 Array_reshape_eq (WN* actual, TREE_ITER& iter)
02557 {
02558 WN* wn = iter.Wn ();
02559
02560 Is_True (WN_operator (wn) == OPR_ARRAY,
02561 ("invalid opcode in Reshape_Array"));
02562
02563 if (WN_operator (actual) != OPR_ARRAY ||
02564 WN_num_dim (wn) != WN_num_dim (actual)) {
02565 WN_array_base (wn) = WN_Type_Conversion (IPO_Copy_Tree (actual),
02566 WN_rtype (wn));
02567 iter.Skip ();
02568 return;
02569 }
02570
02571 WN* array_node = IPO_Copy_Tree (actual);
02572
02573 INT dim = WN_num_dim (array_node);
02574
02575 for (UINT i = 0; i < dim; ++i) {
02576 WN* index_actual = WN_array_index (array_node, i);
02577 WN* index_formal = WN_array_index (wn, i);
02578 WN_array_index (array_node, i) =
02579 WN_CreateExp2 (OPR_ADD, WN_rtype (index_formal), MTYPE_V,
02580 index_actual, index_formal);
02581 }
02582
02583 iter.Replace (array_node);
02584 iter.Skip ();
02585 }
02586
02587
02588
02589
02590
02591 static void
02592 Array_reshape_gt (WN* actual, TREE_ITER& iter)
02593 {
02594 WN* wn = iter.Wn ();
02595
02596 Is_True (WN_operator (wn) == OPR_ARRAY,
02597 ("invalid opcode in Reshape_Array"));
02598
02599 WN* array_node = Create_array (actual);
02600
02601 INT actual_dim = WN_num_dim (array_node);
02602 INT delta = WN_num_dim (wn) - actual_dim ;
02603
02604 if (delta <=0) {
02605
02606 WN_array_base (wn) = WN_Type_Conversion (array_node, WN_rtype (wn));
02607 iter.Skip ();
02608 return;
02609 }
02610
02611 for (UINT i = 0; i < actual_dim; ++i) {
02612 WN* index_formal = WN_array_index (wn, i + delta);
02613 WN* index_actual = WN_array_index (array_node, i);
02614 WN_array_index (array_node, i) =
02615 WN_CreateExp2 (OPR_ADD, WN_rtype (index_formal), MTYPE_V,
02616 index_actual, index_formal);
02617 }
02618
02619 iter.Replace (array_node);
02620 iter.Skip ();
02621 }
02622
02623
02624
02625
02626
02627 static void
02628 Array_reshape_lt (WN* actual, TREE_ITER& iter)
02629 {
02630 WN* wn = iter.Wn ();
02631
02632 Is_True (WN_operator (wn) == OPR_ARRAY,
02633 ("invalid opcode in Reshape_Array"));
02634
02635 WN* array_node = Create_array (actual);
02636
02637 INT formal_dim = WN_num_dim (wn);
02638 INT delta = WN_num_dim (array_node) - formal_dim;
02639
02640 if (delta <= 0) {
02641
02642 WN_array_base (wn) = WN_Type_Conversion (array_node, WN_rtype (wn));
02643 iter.Skip ();
02644 return;
02645 }
02646
02647 for (UINT i = 0; i < formal_dim; ++i) {
02648 WN* index_formal = WN_array_index (wn, i);
02649 WN* index_actual = WN_array_index (array_node, i + delta);
02650 WN_array_index (array_node, i + delta) =
02651 WN_CreateExp2 (OPR_ADD, WN_rtype (index_formal), MTYPE_V,
02652 index_actual, index_formal);
02653 }
02654
02655 iter.Replace (array_node);
02656 iter.Skip ();
02657 }
02658
02659
02660
02661 void
02662 IPO_INLINE::Reshape_Array (TREE_ITER& iter, PARAMETER_ATTRIBUTES& parm,
02663 IPO_INLINE_AUX& aux)
02664 {
02665 if (ST* actual_st = parm.Addr_Passed_Actual ()) {
02666 if (! ST_addr_saved (actual_st)) {
02667
02668
02669 TREE_ITER i = iter;
02670 while (WN* wn = i.Wn ()) {
02671 OPERATOR opr = WN_operator (wn);
02672 if (opr == OPR_STID) {
02673 Set_ST_addr_saved (actual_st);
02674 parm.Set_addr_passed_actual (NULL);
02675 break;
02676 }
02677 if (OPERATOR_is_stmt (opr) ||
02678 opr == OPR_ILOAD || opr == OPR_MLOAD)
02679 break;
02680 if (i.Get_parent_wn () == NULL)
02681 break;
02682 i.Pop ();
02683 }
02684 }
02685 }
02686
02687 WN* parent = iter.Get_parent_wn ();
02688 if (WN_operator (parent) != OPR_ARRAY) {
02689
02690
02691 WN* new_wn = WN_Type_Conversion (IPO_Copy_Tree (parm.Actual_Wn ()),
02692 WN_rtype (iter.Wn()));
02693 iter.Replace (new_wn);
02694 iter.Skip ();
02695 return;
02696 }
02697
02698
02699 Is_True (WN_array_base (parent) == iter.Wn (), ("Invalid array node"));
02700
02701
02702
02703 {
02704 TREE_ITER p (parent);
02705 while (p.Wn () != NULL && p.Wn () != WN_kid1(parent))
02706 ++p;
02707 while (p.Wn () != NULL)
02708 Process_Op_Code (p, aux);
02709 }
02710
02711 iter.Pop ();
02712
02713
02714 switch (parm.Reshape_Method ()) {
02715 case RS_EQ:
02716 Array_reshape_eq (parm.Actual_Wn (), iter);
02717 break;
02718 case RS_GT:
02719 Array_reshape_gt (parm.Actual_Wn (), iter);
02720 break;
02721 case RS_LT:
02722 Array_reshape_lt (parm.Actual_Wn (), iter);
02723 break;
02724 default:
02725 Fail_FmtAssertion ("Incorrect array reshape analysis");
02726 break;
02727 }
02728 }
02729
02730
02731 #ifdef Is_True_On
02732
02733
02734 static inline WN*
02735 Create_Assert (ST* formal, WN* const_wn, TYPE_ID desc)
02736 {
02737 WN* load = WN_Ldid (desc, 0, formal, ST_type (formal));
02738 return WN_CreateAssert (0, WN_EQ (Mtype_comparison (desc), load,
02739 WN_COPY_Tree (const_wn)));
02740
02741 }
02742 #endif // Is_True_On
02743
02744 void
02745 IPO_INLINE::Process_Formal_ST (TREE_ITER& iter, ST* cp, IPO_INLINE_AUX& aux)
02746 {
02747 #ifdef KEY
02748 WN *wn = iter.Wn ();
02749 PARM_ITER p = Lookup_Parm (aux.parm_attr, cp);
02750 if (p == aux.parm_attr.end())
02751 {
02752
02753
02754 ST_IDX idx = 0;
02755 for (replace_st_vec::iterator i=aux.replace_st.begin();
02756 i!=aux.replace_st.end(); ++i)
02757 if ((*i).formal == cp)
02758 {
02759 idx = (*i).replace;
02760 break;
02761 }
02762 Is_True (idx, ("No ST to replace formal"));
02763 WN_st_idx (wn) = idx;
02764 iter++;
02765 return;
02766 }
02767 PARAMETER_ATTRIBUTES& parm = *p;
02768 #else
02769 PARAMETER_ATTRIBUTES& parm = *(Lookup_Parm (aux.parm_attr, cp));
02770 WN *wn = iter.Wn ();
02771 #endif
02772
02773 switch (parm.Fixup_Method ()) {
02774 WN* new_wn;
02775 WN* actual;
02776
02777 case FM_REPLACE_ST:
02778 Is_True (parm.Replace_St () != 0,
02779 ("Missing symbol for formal parameter replacement"));
02780 WN_st_idx (wn) = parm.Replace_St ();
02781 WN_offset (wn) += parm.Formal_Preg ();
02782 if (WN_offset (wn) == 0 && WN_operator (wn) == OPR_LDID) {
02783
02784 ST* st = WN_st (wn);
02785 if (ST_class (st) == CLASS_CONST) {
02786 if (MTYPE_is_integral (TY_mtype (ST_type (st)))) {
02787 TYPE_ID mtype = TY_mtype (ST_type (st));
02788 TCON& tcon = Tcon_Table[ST_tcon (st)];
02789 INT64 value = Targ_To_Host (tcon);
02790 WN* const_wn = WN_Intconst (Mtype_comparison (mtype), value);
02791 iter.Replace (WN_Int_Type_Conversion(const_wn, WN_rtype(wn)));
02792 } else if (MTYPE_is_float (TY_mtype (ST_type (st)))) {
02793 TCON& tcon = Tcon_Table[ST_tcon (st)];
02794 iter.Replace (WN_CreateConst (OPR_CONST, TCON_ty (tcon),
02795 MTYPE_V, ST_st_idx (st)));
02796 }
02797 }
02798 }
02799 break;
02800
02801 case FM_REPLACE_ACTUAL:
02802 if (WN_offset (wn) == 0 && WN_operator (wn) == OPR_LDID) {
02803 new_wn = WN_Type_Conversion (IPO_Copy_Tree (parm.Actual_Wn ()),
02804 WN_rtype (wn));
02805 iter.Replace (new_wn);
02806 iter.Skip ();
02807 }
02808 else {
02809 iter.Delete ();
02810 #ifdef Is_True_On
02811 Create_Assert(WN_st(wn), parm.Actual_Wn (), TY_mtype (ST_type (WN_st(wn))));
02812 #endif // Is_True_On
02813 }
02814 return;
02815
02816 case FM_REPLACE_ARRAY:
02817 Is_True (WN_operator (wn) == OPR_LDID,
02818 ("Incorrect parameter passing analysis"));
02819 Reshape_Array (iter, parm, aux);
02820 return;
02821
02822
02823 case FM_LOWER_FORMAL_REF:
02824
02825
02826
02827
02828
02829 actual = IPO_Copy_Tree (parm.Actual_Wn ());
02830
02831 switch (WN_operator (wn)) {
02832 case OPR_LDID:
02833 new_wn = WN_CreateIload (OPR_ILOAD, WN_rtype (wn),
02834 WN_desc (wn), WN_load_offset (wn),
02835 WN_ty (wn),
02836 Make_Pointer_Type (WN_ty (wn)),
02837 actual);
02838 break;
02839
02840 case OPR_LDA:
02841 new_wn = actual;
02842 if (WN_offset (wn) != 0) {
02843 WN* offset = WN_Intconst (MTYPE_U4, WN_offset (wn));
02844 new_wn = WN_CreateExp2 (OPR_ADD, WN_rtype (wn), MTYPE_V,
02845 new_wn, offset);
02846 }
02847 break;
02848
02849 case OPR_STID:
02850 {
02851
02852 TREE_ITER i (wn);
02853 ++i;
02854 while (i.Wn () != NULL)
02855 Process_Op_Code (i, aux);
02856 }
02857 new_wn = WN_Istore (WN_desc (wn), WN_store_offset (wn),
02858 Make_Pointer_Type (WN_ty (wn)), actual,
02859 WN_kid0 (wn));
02860 break;
02861
02862 default:
02863 Fail_FmtAssertion ("Unexpected references of formal parameter");
02864 }
02865
02866 iter.Replace (new_wn);
02867 iter.Skip ();
02868 return;
02869
02870 default:
02871 Fail_FmtAssertion ("uninitialized parameter fixup method");
02872 }
02873
02874 ++iter;
02875 }
02876
02877
02878
02879
02880
02881
02882
02883
02884 void
02885 IPO_INLINE::Process_ST (TREE_ITER& iter, IPO_INLINE_AUX& aux)
02886 {
02887 ST* cp = WN_st (iter.Wn ());
02888 if (cp == NULL) {
02889 ++iter;
02890 return;
02891 }
02892
02893 #if 0
02894 if (IPA_Enable_Inline_Var_Dim_Array && Callee_Summary_Proc()->Has_var_dim_array())
02895 fix_var_dim_array(ST_type(cp), Symtab());
02896 #endif
02897
02898
02899 SUMMARY_PROCEDURE* caller_proc = Caller_node()->Summary_Proc ();
02900
02901 BOOL Is_DoAcross = caller_proc->Has_parallel_pragma ();
02902 BOOL Is_MP_Region = caller_proc->Has_parallel_region_pragma();
02903
02904 switch(ST_sclass(cp)) {
02905 case SCLASS_PSTATIC:
02906 Set_ST_sclass(cp, SCLASS_FSTATIC);
02907 case SCLASS_FSTATIC:
02908
02909
02910 if (ST_class (cp) != CLASS_CONST &&
02911 Callee_node ()->File_Index () != Caller_node ()->File_Index ()) {
02912
02913 static INT Temp_Index = 0;
02914 STR_IDX new_name = Save_Str2i(ST_name(cp),"..", Temp_Index++);
02915 Set_ST_name_idx (*cp, new_name);
02916 if (ST_is_initialized(cp) && !ST_init_value_zero(cp))
02917 Set_ST_sclass(cp, SCLASS_DGLOBAL);
02918 else
02919 Set_ST_sclass(cp, SCLASS_UGLOBAL);
02920
02921 if (ST_ADDR_SAVED(cp) || ST_ADDR_PASSED(cp)) {
02922 Set_ST_export(cp, EXPORT_HIDDEN);
02923 } else
02924 Set_ST_export(cp, EXPORT_INTERNAL);
02925
02926 if (ST_base_idx (cp) != ST_st_idx (cp)) {
02927 Set_ST_sclass(ST_ptr(ST_base_idx(cp)), ST_sclass(cp));
02928 Set_ST_export(ST_ptr(ST_base_idx(cp)), ST_export(cp));
02929 }
02930 }
02931 #if (defined(KEY) && (defined(_STANDALONE_INLINER) || defined(_LIGHTWEIGHT_INLINER)))
02932 if ((Is_DoAcross) || (Is_MP_Region)) {
02933 Update_Caller_MP_Pragmas(cp, Call_Wn());
02934 }
02935 #endif // KEY && _STANDALONE_INLINER
02936
02937 break;
02938
02939 case SCLASS_EXTERN:
02940 case SCLASS_UGLOBAL:
02941 case SCLASS_DGLOBAL:
02942 case SCLASS_COMMON:
02943 #if (defined(_STANDALONE_INLINER) || defined(_LIGHTWEIGHT_INLINER))
02944 if ((Is_DoAcross) || (Is_MP_Region)) {
02945 Update_Caller_MP_Pragmas(cp, Call_Wn());
02946 }
02947 #endif // _STANDALONE_INLINER
02948 break;
02949
02950 case SCLASS_AUTO:
02951
02952
02953
02954 if (!ST_is_export_local(cp))
02955 Fail_FmtAssertion("unsupported ST_export %d and class %d \n",
02956 ST_sclass(cp), ST_export(cp));
02957
02958 FmtAssert(cp != NULL, ("LOCAL must have a cloned version\n"));
02959 Clear_ST_is_return_var(cp);
02960
02961 if ((Is_DoAcross) || (Is_MP_Region)) {
02962 if (aux.Local_ST_Not_Processed(cp)) {
02963 Update_Caller_MP_Pragmas(cp, Call_Wn());
02964 }
02965 }
02966 break;
02967
02968 case SCLASS_TEXT:
02969 #if (!defined(_STANDALONE_INLINER) && !defined(_LIGHTWEIGHT_INLINER))
02970 FmtAssert(cp != NULL, ("LOCAL must have a cloned version\n"));
02971 #endif
02972 break;
02973
02974 case SCLASS_FORMAL:
02975 case SCLASS_FORMAL_REF:
02976 if (ST_is_not_used (cp)) {
02977
02978
02979
02980
02981 Process_Formal_ST (iter, cp, aux);
02982 return;
02983 }
02984 break;
02985
02986 case SCLASS_REG:
02987 Process_Pregs (iter.Wn (), aux.rp);
02988 break;
02989
02990 default:
02991 if (ST_class(cp) != CLASS_NAME) {
02992 Fail_FmtAssertion("SCLASS Type %s: unsupported \n",
02993 Sclass_Name(ST_sclass(cp)));
02994 Print_ST ( TFile,cp,0);
02995 }
02996 break;
02997 }
02998
02999 ++iter;
03000 }
03001
03002
03003
03004
03005
03006
03007 static WN *
03008 Simplify_Tree(WN *block)
03009 {
03010
03011 WN_SimpParentMap = Parent_Map;
03012 WN* tmp_callee = WN_Simplify_Tree(block);
03013 WN_SimpParentMap = (WN_MAP)0;
03014 return tmp_callee;
03015 }
03016
03017
03018 pair<ST*, WN_OFFSET>
03019 IPO_INLINE::Create_Copy_In_Symbol (ST* formal_st)
03020 {
03021 ST* copy_st = NULL;
03022 WN_OFFSET wn_offset = 0;
03023
03024 copy_st = Symtab()->IPO_Copy_ST (formal_st, Caller_level());
03025 Set_ST_base_idx (copy_st, ST_st_idx(copy_st));
03026 Set_ST_ofst (copy_st, 0);
03027 Set_ST_sclass (copy_st, SCLASS_AUTO);
03028 Clear_ST_is_value_parm (copy_st);
03029 Clear_ST_is_not_used (copy_st);
03030 Clear_ST_is_optional_argument (copy_st);
03031 Set_ST_is_temp_var (copy_st);
03032 #ifdef KEY // bug 6674
03033 Clear_TY_is_restrict (copy_st->u2.type);
03034 #endif
03035
03036
03037 SUMMARY_PROCEDURE* caller_proc = Caller_node()->Summary_Proc ();
03038
03039 BOOL Is_DoAcross = caller_proc->Has_parallel_pragma ();
03040 BOOL Is_MP_Region = caller_proc->Has_parallel_region_pragma();
03041
03042 if ((Is_DoAcross) || (Is_MP_Region)) {
03043 Update_Caller_MP_Pragmas(copy_st, Call_Wn());
03044 }
03045
03046 return std::make_pair (copy_st, wn_offset);
03047 }
03048
03049
03050 static inline WN*
03051 Copy_Scalar (ST* dest, WN_OFFSET offset, TYPE_ID desc, WN* src)
03052 {
03053 return WN_Stid (desc, offset, dest, ST_type (dest),
03054 WN_Type_Conversion (src, desc));
03055 }
03056
03057
03058 static WN*
03059 Copy_Struct (ST* dest, WN* src, UINT64 size)
03060 {
03061 if (WHIRL_Mldid_Mstid_On)
03062 #ifdef KEY // bug 7760: src may not be M type due to fix to bug 7741.
03063 return WN_Stid (WN_rtype(src), 0, dest, ST_type (dest), src);
03064 #else
03065 return WN_Stid (MTYPE_M, 0, dest, ST_type (dest), src);
03066 #endif
03067 else
03068 return WN_CreateMstore (0, Make_Pointer_Type (ST_type (dest)),
03069 src, WN_Lda (Pointer_Mtype, 0, dest),
03070 WN_Intconst (MTYPE_U4, size));
03071 }
03072
03073
03074 void
03075 IPO_INLINE::Process_Copy_In (PARM_ITER parm, WN* copy_in_block)
03076 {
03077 Is_True (Scope_tab == Caller_Scope (), ("expecting caller scope"));
03078 Is_True (parm->Pass_Method () == PM_COPY_IN,
03079 ("Incorrect parameter passing method"));
03080
03081 if (parm->Fixup_Method () == FM_REPLACE_ST) {
03082
03083 WN* actual = IPO_Copy_Tree (parm->Actual_Wn ());
03084 ST* formal_st = parm->Formal_St ();
03085 const TY& formal_ty = Ty_Table[ST_type (formal_st)];
03086 TYPE_ID mtype = TY_mtype (formal_ty);
03087
03088 ST* copy_st;
03089 WN_OFFSET wn_offset;
03090
03091 pair<ST*, WN_OFFSET> sym = Create_Copy_In_Symbol (formal_st);
03092 copy_st = sym.first;
03093 wn_offset = sym.second;
03094
03095 WN* copy_wn;
03096
03097 if (mtype != MTYPE_M) {
03098
03099 if (ST* st = Get_actual_st_if_passed (actual)) {
03100 Set_ST_addr_saved (st);
03101 }
03102 #if (!defined(_STANDALONE_INLINER) && !defined(_LIGHTWEIGHT_INLINER))
03103
03104
03105 Update_formal_dref (actual, Caller_node ());
03106 #endif
03107 copy_wn = Copy_Scalar (copy_st, wn_offset, mtype, actual);
03108 } else {
03109
03110 copy_wn = Copy_Struct (copy_st, actual, TY_size (formal_ty));
03111 }
03112
03113 LWN_Insert_Block_Before (copy_in_block, NULL, copy_wn);
03114
03115
03116 parm->Set_formal_preg (wn_offset);
03117 parm->Set_replace_st (ST_st_idx (copy_st));
03118
03119 } else {
03120
03121 WN* actual = parm->Actual_Wn ();
03122 ST* formal_st = parm->Formal_St ();
03123 pair<WN*, ST*> copy_stmt;
03124
03125 if (! ST_is_value_parm (formal_st) &&
03126 (WN_operator(actual) == OPR_INTCONST && ST_is_optional_argument
03127 (formal_st))) {
03128 copy_stmt = Create_Copy_Expr_For_Ptr (actual, Call_Wn(),
03129 Caller_node()->Summary_Proc ()->Has_parallel_pragma () ||
03130 Caller_node()->Summary_Proc ()->Has_parallel_region_pragma());
03131
03132 LWN_Insert_Block_Before (copy_in_block, NULL, copy_stmt.first);
03133
03134 parm->Set_actual (WN_Ldid (Pointer_type, 0,
03135 ST_st_idx (copy_stmt.second),
03136 ST_type (copy_stmt.second)));
03137 }
03138 else {
03139 copy_stmt = Create_Copy_Expr (actual, Call_Wn(),
03140 Caller_node()->Summary_Proc ()->Has_parallel_pragma () ||
03141 Caller_node()->Summary_Proc ()->Has_parallel_region_pragma());
03142
03143
03144 LWN_Insert_Block_Before (copy_in_block, NULL, copy_stmt.first);
03145
03146 parm->Set_actual (WN_Ldid (WN_rtype (actual), 0,
03147 ST_st_idx (copy_stmt.second),
03148 ST_type (copy_stmt.second)));
03149 }
03150
03151 }
03152
03153 }
03154
03155
03156
03157 static void
03158 Process_Direct_Replacement (PARM_ITER parm)
03159 {
03160 Is_True (parm->Pass_Method () == PM_REPLACE,
03161 ("Incorrect parameter passing method"));
03162
03163 if (parm->Fixup_Method () == FM_REPLACE_ST) {
03164 WN* wn = parm->Actual_Wn ();
03165 Is_True (OPERATOR_has_sym (WN_operator (wn)),
03166 ("expecting a WHIRL node with ST"));
03167 parm->Set_replace_st (WN_st_idx (wn));
03168 parm->Set_formal_preg (WN_offset (wn));
03169 ST* formal_st = parm->Formal_St ();
03170 if (ST_addr_saved(formal_st))
03171 Set_ST_addr_saved (WN_st(wn));
03172 }
03173
03174 }
03175
03176
03177
03178
03179
03180
03181
03182
03183
03184
03185
03186 void
03187 IPO_INLINE::Process_Copy_In_Copy_Out (PARM_ITER p, IPO_INLINE_AUX& aux)
03188 {
03189 Is_True (Scope_tab == Caller_Scope (), ("expecting caller scope"));
03190 Is_True (p->Pass_Method () == PM_COPY_IN_OUT,
03191 ("Incorrect parameter passing method"));
03192
03193
03194 WN* actual = IPO_Copy_Tree (p->Actual_Wn ());
03195 ST* formal_st = p->Formal_St ();
03196 const TY& formal_ty = Ty_Table[ST_type (formal_st)];
03197 TYPE_ID mtype = TY_mtype (formal_ty);
03198
03199 Is_True (mtype != MTYPE_M, ("copy in/copy out parameter is MTYPE_M"));
03200 Is_True (p->Fixup_Method () != FM_LOWER_FORMAL_REF,
03201 ("Invalid fixup method for copy in/copy out parameters"));
03202
03203 pair<ST*, WN_OFFSET> sym = Create_Copy_In_Symbol (formal_st);
03204 ST* copy_st = sym.first;
03205 WN_OFFSET wn_offset = sym.second;
03206
03207 WN* wn_iload = WN_CreateIload (OPR_ILOAD, mtype, mtype, 0,
03208 ST_type (formal_st),
03209 Make_Pointer_Type (ST_type (formal_st)),
03210 actual);
03211
03212 WN* copy_in = WN_Stid (mtype, wn_offset, copy_st, ST_type (copy_st),
03213 WN_Type_Conversion (wn_iload, mtype));
03214
03215 LWN_Insert_Block_Before (aux.copy_in_block, NULL, copy_in);
03216
03217
03218
03219
03220 actual = IPO_Copy_Tree (p->Actual_Wn ());
03221
03222 WN* load_wn = WN_Ldid (mtype, wn_offset, ST_st_idx (copy_st),
03223 ST_type (copy_st));
03224 WN* copy_wn = WN_Istore (mtype, 0, Make_Pointer_Type (ST_type (copy_st)),
03225 actual, load_wn);
03226
03227 if (aux.copy_out_block == NULL)
03228 aux.copy_out_block = WN_CreateBlock ();
03229
03230 LWN_Insert_Block_After (aux.copy_out_block, NULL, copy_wn);
03231
03232 p->Set_formal_preg (wn_offset);
03233 p->Set_replace_st (ST_st_idx (copy_st));
03234
03235
03236 }
03237
03238
03239
03240
03241
03242 void
03243 IPO_INLINE::Process_Barriers (PARM_ITER parm, WN* copy_in_block)
03244 {
03245 Is_True (Scope_tab == Caller_Scope (), ("expecting caller scope"));
03246 Is_True (parm->Pass_Method () == PM_NEED_BARRIER,
03247 ("Incorrect parameter passing method"));
03248
03249 ST* formal_st = parm->Formal_St ();
03250 TY& formal_ty = Ty_Table[ST_type (formal_st)];
03251
03252 Is_True (TY_kind (formal_ty) == KIND_POINTER,
03253 ("incorrect type for array argument"));
03254
03255 ST* copy_st = Symtab()->IPO_Copy_ST (formal_st, Caller_level());
03256 Set_ST_base_idx (copy_st, ST_st_idx(copy_st));
03257 Set_ST_ofst (copy_st, 0);
03258 Set_ST_sclass (copy_st, SCLASS_AUTO);
03259 Clear_ST_is_value_parm (copy_st);
03260 Clear_ST_is_not_used (copy_st);
03261 Set_ST_is_temp_var (copy_st);
03262 if (! parm->Restrict_Pointer ())
03263 Set_ST_pt_to_unique_mem (copy_st);
03264
03265
03266 SUMMARY_PROCEDURE* caller_proc = Caller_node()->Summary_Proc ();
03267
03268 BOOL Is_DoAcross = caller_proc->Has_parallel_pragma ();
03269 BOOL Is_MP_Region = caller_proc->Has_parallel_region_pragma();
03270
03271 if ((Is_DoAcross) || (Is_MP_Region)) {
03272 Update_Caller_MP_Pragmas(copy_st, Call_Wn());
03273 }
03274
03275 WN* copy_wn = Copy_Scalar (copy_st, 0, TY_mtype (formal_ty),
03276 IPO_Copy_Tree (parm->Actual_Wn ()));
03277
03278 LWN_Insert_Block_Before (copy_in_block, NULL, copy_wn);
03279
03280 parm->Set_replace_st (ST_st_idx (copy_st));
03281 Set_PU_smart_addr_analysis (*Current_pu);
03282 }
03283
03284
03285
03286 static inline BOOL
03287 constant_array_base (WN* base)
03288 {
03289 OPERATOR opr = WN_operator (base);
03290 if (opr == OPR_LDA)
03291 return TRUE;
03292
03293 if (opr == OPR_LDID) {
03294 const ST* st = WN_st (base);
03295 return (ST_sclass (st) == SCLASS_FORMAL && !ST_is_value_parm (st));
03296 }
03297
03298 return FALSE;
03299 }
03300
03301
03302
03303
03304 static void
03305 Copy_Non_Constant_Parm (WN* parm, WN* copy_in_block, PARAMETER_ATTRIBUTES& p, IPO_INLINE& inliner)
03306 {
03307 switch (WN_operator (parm)) {
03308 case OPR_INTCONST:
03309 case OPR_LDA:
03310 return;
03311
03312 case OPR_ILOAD:
03313 if (WN_operator (WN_kid0 (parm)) != OPR_LDA)
03314 break;
03315 if (ST_might_be_modified (WN_st (WN_kid0 (parm))))
03316 break;
03317 else
03318 return;
03319
03320 case OPR_LDID:
03321 if (ST_might_be_modified (WN_st (parm)))
03322 break;
03323 else
03324 return;
03325
03326 default:
03327 break;
03328 }
03329
03330
03331
03332
03333 pair<WN*, ST*> copy_stmt = Create_Copy_Expr (parm, inliner.Call_Wn(),
03334 inliner.Caller_node()->Summary_Proc ()->Has_parallel_pragma () ||
03335 inliner.Caller_node()->Summary_Proc ()->Has_parallel_region_pragma());
03336
03337
03338 LWN_Insert_Block_Before (copy_in_block, NULL, copy_stmt.first);
03339
03340 p.Set_actual (WN_Ldid (WN_rtype (parm), 0, ST_st_idx (copy_stmt.second),
03341 ST_type (copy_stmt.second)));
03342
03343 }
03344
03345
03346 static void
03347 Compute_Pass_Method (PARM_ITER p, IPO_INLINE_AUX& aux, IPO_INLINE& inliner)
03348 {
03349 PARM_ATTR_VEC& parm_attr = aux.parm_attr;
03350 PARAMETER_ATTRIBUTES& parm = *p;
03351 WN* wn = parm.Actual_Wn ();
03352 OPERATOR opr = WN_operator (wn);
03353 ST* formal_st = parm.Formal_St ();
03354
03355 if (!ST_is_value_parm (formal_st) && Formal_Is_Array (formal_st)) {
03356 RESHAPE_METHOD r = Do_Linearize(wn, formal_st);
03357 parm.Set_pass_method (PM_REPLACE);
03358 parm.Set_fixup_method (FM_REPLACE_ARRAY);
03359 parm.Set_reshape_method (r);
03360 if (ST* actual_st = Get_actual_st_if_passed (wn)) {
03361 if (ST_addr_passed (actual_st) && !ST_addr_saved (actual_st))
03362 parm.Set_addr_passed_actual (actual_st);
03363 }
03364 switch (r) {
03365 case RS_EQ:
03366 case RS_LT:
03367 case RS_GT:
03368
03369 return;
03370
03371 case RS_LINEARIZE:
03372 case RS_EQ_COMMON:
03373 default:
03374
03375
03376 break;
03377 }
03378 }
03379
03380 if (! ST_is_value_parm (formal_st)) {
03381 if (opr == OPR_INTCONST && ST_is_optional_argument (formal_st)) {
03382
03383
03384
03385 parm.Set_pass_method (PM_COPY_IN);
03386 if (ST_sclass (formal_st) == SCLASS_FORMAL_REF)
03387 parm.Set_fixup_method (FM_LOWER_FORMAL_REF);
03388 else
03389 parm.Set_fixup_method (FM_REPLACE_ST);
03390 } else if (ST_sclass (formal_st) == SCLASS_FORMAL_REF) {
03391 parm.Set_pass_method (PM_REPLACE);
03392 if (opr == OPR_LDA)
03393 parm.Set_fixup_method (FM_REPLACE_ST);
03394 else {
03395 parm.Set_fixup_method (FM_LOWER_FORMAL_REF);
03396 if (opr != OPR_ARRAY)
03397
03398 Copy_Non_Constant_Parm (wn, aux.copy_in_block, parm, inliner);
03399 }
03400 } else {
03401
03402
03403 parm.Set_pass_method (PM_REPLACE);
03404 parm.Set_fixup_method (FM_REPLACE_ACTUAL);
03405 }
03406 } else {
03407
03408 if (INLINE_Enable_Restrict_Pointers) {
03409 if (TY_is_restrict (ST_type (formal_st)) &&
03410 TY_kind (ST_type (formal_st)) == KIND_POINTER) {
03411 parm.Set_actual_aliased (Get_actual_st_if_passed (wn));
03412 parm.Set_pass_method (PM_NEED_BARRIER);
03413 parm.Set_fixup_method (FM_REPLACE_ST);
03414 parm.Set_restrict_pointer ();
03415 return;
03416 }
03417 }
03418
03419
03420
03421 if (! OPERATOR_is_leaf (opr) && opr != OPR_ARRAY) {
03422 parm.Set_pass_method (PM_COPY_IN);
03423 parm.Set_fixup_method (FM_REPLACE_ST);
03424 } else if (inliner.SubstituteFormal (formal_st, wn,
03425 p - parm_attr.begin ())) {
03426
03427
03428
03429 parm.Set_pass_method (PM_REPLACE);
03430 parm.Set_fixup_method (FM_REPLACE_ACTUAL);
03431 } else {
03432 parm.Set_pass_method (PM_COPY_IN);
03433 parm.Set_fixup_method (FM_REPLACE_ST);
03434 }
03435 }
03436 }
03437
03438
03439 static ST*
03440 get_formal(SCOPE* callee_scope, WN *formal)
03441 {
03442 SCOPE_CONTEXT switch_scope(callee_scope);
03443 ST* formal_st = WN_st(formal);
03444 return (formal_st);
03445 }
03446
03447
03448
03449
03450
03451 void
03452 IPO_INLINE::Process_Formals (IPO_INLINE_AUX& aux)
03453 {
03454 PARM_ATTR_VEC& parm_attr = aux.parm_attr;
03455 Is_True (parm_attr.size () == 0,
03456 ("uninitialized parameter attributes list"));
03457
03458 WN* callee = Callee_Wn ();
03459 WN* call = Call_Wn ();
03460 BOOL has_array = FALSE;
03461
03462
03463
03464 #ifdef KEY
03465 INT num_params = Call_edge()->Num_Actuals() < WN_num_formals(callee) ?
03466 Call_edge()->Num_Actuals() : WN_num_formals(callee);
03467
03468 for (INT j=0; j < num_params; ++j)
03469 #else
03470 for (INT j=0; j < WN_num_formals(callee); ++j)
03471 #endif
03472 {
03473 ST* ste = get_formal(Callee_Scope(), WN_formal(callee,j));
03474 ste = Symtab()->Get_ST(ste);
03475 Is_True (ST_sclass (ste) == SCLASS_FORMAL ||
03476 ST_sclass (ste) == SCLASS_FORMAL_REF,
03477 ("ProcessFormals:sclass %s not supported \n",
03478 Sclass_Name(ST_sclass(ste))));
03479
03480 WN* actual = WN_kid(call, j);
03481 if (WN_operator(actual) == OPR_PARM)
03482 actual = WN_kid0(actual);
03483 if (WN_operator(actual) == OPR_ARRAY)
03484 has_array = TRUE;
03485 parm_attr.push_back (PARAMETER_ATTRIBUTES (actual, ste));
03486 }
03487
03488 #ifdef KEY
03489
03490
03491 for (; num_params < WN_num_formals(callee); ++num_params)
03492 {
03493 ST* ste = get_formal(Callee_Scope(), WN_formal(callee, num_params));
03494 ste = Symtab()->Get_ST(ste);
03495 pair<ST*, WN_OFFSET> sym = Create_Copy_In_Symbol (ste);
03496 Is_True (!sym.second, ("Non-zero offset not handled yet"));
03497
03498 formal_to_replace_st param (ste, ST_st_idx (sym.first));
03499 aux.replace_st.push_back (param);
03500 }
03501 #endif
03502
03503 aux.copy_in_block = WN_CreateBlock();
03504
03505
03506 if (has_array) {
03507 if (IPA_Enable_BarrierFarg) {
03508 PU& pu = Pu_Table[ST_pu (Callee_node ()->Func_ST ())];
03509
03510
03511 if ((PU_f77_lang (pu) || PU_f90_lang (pu)) &&
03512 !PU_args_aliased (pu) &&
03513 Unaliased_Actuals_Useful (aux.inlined_body))
03514 Disambiguate_Aliased_Actuals (parm_attr, pu);
03515 }
03516
03517
03518 Copy_Subscript_Expressions (aux, *this);
03519
03520 }
03521
03522
03523
03524 for (PARM_ITER p (parm_attr.begin()); p != parm_attr.end(); ++p) {
03525
03526 if ((*p).Pass_Method () == PM_UNKNOWN)
03527 Compute_Pass_Method (p, aux, *this);
03528
03529 switch ((*p).Pass_Method ()) {
03530
03531 case PM_COPY_IN:
03532 Process_Copy_In (p, aux.copy_in_block);
03533 break;
03534
03535 case PM_REPLACE:
03536 Process_Direct_Replacement (p);
03537 break;
03538
03539 case PM_COPY_IN_OUT:
03540 Process_Copy_In_Copy_Out (p, aux);
03541 break;
03542
03543 case PM_NEED_BARRIER:
03544 Process_Barriers (p, aux.copy_in_block);
03545 break;
03546
03547 default:
03548 Fail_FmtAssertion ("Undetermined parameter passing method");
03549 break;
03550 }
03551 }
03552
03553 }
03554
03555
03556
03557
03558
03559 void
03560 IPO_INLINE::Walk_and_Update_Callee (IPO_INLINE_AUX& aux)
03561 {
03562
03563 Process_Formals (aux);
03564
03565
03566
03567
03568
03569 TREE_ITER iter (aux.inlined_body);
03570
03571 while (iter.Wn () != NULL) {
03572 Process_Op_Code (iter, aux);
03573 }
03574
03575 WN_Parentize (aux.inlined_body, Caller_node()->Parent_Map (),
03576 Caller_Map_Table ());
03577
03578 aux.inlined_body = Simplify_Tree(aux.inlined_body);
03579 }
03580
03581 #ifdef KEY
03582 void
03583 IPO_INLINE::Merge_EH_Spec_Tables (void)
03584 {
03585 INITV_IDX start, blk;
03586 if (!PU_cxx_lang (Callee_node()->Get_PU()))
03587 return;
03588
03589
03590 INITO_IDX tmp = PU_misc_info (Callee_node()->Get_PU());
03591 if (tmp)
03592 start = INITO_val (tmp);
03593 else return;
03594
03595 const INITO_IDX callee_spec = TCON_uval (INITV_tc_val (INITV_next (INITV_next (INITV_next (start)))));
03596 if (!callee_spec)
03597 return;
03598
03599 blk = INITV_blk (INITO_val (callee_spec));
03600 mUINT32 callee_spec_size=0;
03601 vector<ST_IDX> callee_spec_types;
03602 while (blk)
03603 {
03604 callee_spec_size++;
03605 if (INITV_kind (blk) == INITVKIND_ZERO)
03606 callee_spec_types.push_back (0);
03607 else
03608 callee_spec_types.push_back (TCON_uval (INITV_tc_val (blk)));
03609 blk = INITV_next (blk);
03610 }
03611 if (!Callee_node()->EH_spec_size())
03612 Callee_node()->Set_EH_spec_size (callee_spec_size);
03613 #ifdef Is_True_On
03614 else FmtAssert (Callee_node()->EH_spec_size() == callee_spec_size, ("EH specification size mismatch"));
03615 FmtAssert (!callee_spec_types.empty(), ("EH Specification merge error"));
03616 #endif
03617
03618
03619 Set_Tables (Caller_node());
03620 start = INITO_val (PU_misc_info (Pu_Table [ST_pu (Caller_node()->Func_ST())]));
03621 const INITO_IDX caller_spec = TCON_uval (INITV_tc_val (INITV_next (INITV_next (INITV_next (start)))));
03622 if (caller_spec)
03623 blk = INITV_blk (INITO_val (caller_spec));
03624 else
03625 blk = 0;
03626 mUINT32 caller_spec_size=0;
03627 INITV_IDX last_ti = INITV_IDX_ZERO;
03628 while (blk)
03629 {
03630 caller_spec_size++;
03631 last_ti = blk;
03632 blk = INITV_next (blk);
03633 }
03634 if (!Caller_node()->EH_spec_size())
03635 Caller_node()->Set_EH_spec_size (caller_spec_size);
03636 #ifdef Is_True_On
03637 else FmtAssert (Caller_node()->EH_spec_size() == caller_spec_size, ("EH specification size mismatch"));
03638 #endif
03639
03640 INITV_IDX first_insert = INITV_IDX_ZERO, prev_insert = INITV_IDX_ZERO;
03641 for (vector<ST_IDX>::iterator i = callee_spec_types.begin();
03642 i != callee_spec_types.end();
03643 i++)
03644 {
03645 INITV_IDX insert = New_INITV();
03646 if (*i == 0)
03647 INITV_Set_ZERO (Initv_Table[insert], MTYPE_U4, 1);
03648 else
03649 INITV_Set_VAL (Initv_Table[insert],
03650 Enter_tcon (Host_To_Targ (MTYPE_U4, *i)), 1);
03651 if (prev_insert)
03652 Set_INITV_next (prev_insert, insert);
03653 else
03654 first_insert = insert;
03655 prev_insert = insert;
03656 }
03657 if (!caller_spec_size)
03658 {
03659 IPO_SYMTAB* cloned = Callee_node()->Cloned_Symtab();
03660
03661 INITO_IDX cloned_spec = cloned->Get_INITO_IDX (callee_spec);
03662 ST * new_st = Copy_ST (INITO_st (cloned_spec), CURRENT_SYMTAB);
03663 INITV_IDX begin = New_INITV();
03664 INITV_Init_Block (begin, first_insert);
03665 INITO_IDX new_spec = New_INITO (ST_st_idx (new_st), begin);
03666
03667
03668 INITV_IDX pos = INITV_next (INITV_next (INITV_next (start)));
03669 INITV_IDX bkup = INITV_next (pos);
03670 FmtAssert (!bkup, ("Exception specification info not last entry"));
03671 INITV_Set_VAL (Initv_Table[pos],
03672 Enter_tcon (Host_To_Targ (MTYPE_U4, new_spec)), 1);
03673 Set_INITV_next (pos, bkup);
03674 }
03675 else
03676 Set_INITV_next (last_ti, first_insert);
03677 Set_Tables (Callee_node());
03678 }
03679
03680 void
03681 IPO_INLINE::Merge_EH_Typeinfo_Tables (void)
03682 {
03683 vector<ST_IDX> callee_typeinfos, caller_typeinfos;
03684 INITV_IDX start, blk, last_blk=0;
03685 if (!PU_cxx_lang (Callee_node()->Get_PU()))
03686 return;
03687
03688 INITO_IDX tmp = PU_misc_info (Callee_node()->Get_PU());
03689 if (tmp)
03690 start = INITO_val (tmp);
03691 else
03692 return;
03693 const INITO_IDX callee_ttable = TCON_uval (INITV_tc_val (INITV_next (INITV_next (start))));
03694 if (!callee_ttable)
03695 return;
03696 blk = INITO_val (callee_ttable);
03697 while (blk)
03698 {
03699 INITV_IDX ti = INITV_blk (blk);
03700 if (INITV_kind (ti) == INITVKIND_ZERO)
03701 callee_typeinfos.push_back (0);
03702 else
03703 callee_typeinfos.push_back (TCON_uval (INITV_tc_val (ti)));
03704 blk = INITV_next (blk);
03705 }
03706
03707
03708 Set_Tables (Caller_node());
03709 start = INITO_val (PU_misc_info (Pu_Table [ST_pu (Caller_node()->Func_ST())]));
03710 INITO_IDX caller_ttable = TCON_uval (INITV_tc_val (INITV_next (INITV_next (start))));
03711 if (caller_ttable) blk = INITO_val (caller_ttable);
03712 else blk = 0;
03713 while (blk)
03714 {
03715 INITV_IDX ti = INITV_blk (blk);
03716 if (INITV_kind (ti) == INITVKIND_ZERO)
03717 caller_typeinfos.push_back (0);
03718 else
03719 caller_typeinfos.push_back (TCON_uval (INITV_tc_val (ti)));
03720 last_blk = blk;
03721 blk = INITV_next (blk);
03722 }
03723 sort (caller_typeinfos.begin(), caller_typeinfos.end());
03724 int last_caller_filter = caller_typeinfos.size();
03725 if (!last_caller_filter)
03726 {
03727 FmtAssert (!last_blk && !caller_ttable, ("EH Tables processing error in inliner"));
03728 IPO_SYMTAB* cloned = Callee_node()->Cloned_Symtab();
03729
03730 INITO_IDX cloned_ttable = cloned->Get_INITO_IDX (callee_ttable);
03731 ST * new_st = Copy_ST (INITO_st (cloned_ttable), CURRENT_SYMTAB);
03732 INITV_IDX to_iter = New_INITV();
03733 INITO_IDX new_ttable = New_INITO (ST_st_idx (new_st), to_iter);
03734 INITV_IDX from_iter = INITO_val (cloned_ttable);
03735 while (from_iter)
03736 {
03737 memcpy (&Initv_Table[to_iter], &Initv_Table[from_iter], sizeof(INITV));
03738
03739 INITV_IDX from = INITV_blk (from_iter);
03740 INITV_IDX to_ti = New_INITV();
03741 INITV_Init_Block (to_iter, to_ti);
03742
03743 memcpy (&Initv_Table[to_ti], &Initv_Table[from], sizeof(INITV));
03744 from = INITV_next (from);
03745 INITV_IDX to_filter = New_INITV();
03746 memcpy (&Initv_Table[to_filter], &Initv_Table[from], sizeof(INITV));
03747 Set_INITV_next (to_ti, to_filter);
03748 from_iter = INITV_next (from_iter);
03749 if (from_iter)
03750 {
03751 INITV_IDX tmp = New_INITV();
03752 Set_INITV_next (to_iter, tmp);
03753 to_iter = tmp;
03754 }
03755 }
03756
03757 INITV_IDX insert = INITV_next (INITV_next (start));
03758 INITV_IDX bkup = INITV_next (insert);
03759 INITV_Set_VAL (Initv_Table[insert],
03760 Enter_tcon (Host_To_Targ (MTYPE_U4, new_ttable)), 1);
03761 Set_INITV_next (insert, bkup);
03762 }
03763 else
03764 {
03765 FmtAssert (last_blk, ("EH Tables processing error in inliner"));
03766 int filter = last_caller_filter+1;
03767 vector<ST_IDX>::iterator i = callee_typeinfos.begin();
03768 for (; i!=callee_typeinfos.end(); ++i)
03769 {
03770 if (!binary_search (caller_typeinfos.begin(),
03771 caller_typeinfos.end(), (*i)))
03772 {
03773 INITV_IDX st = New_INITV();
03774 if (*i == 0)
03775 INITV_Set_ZERO (Initv_Table[st], MTYPE_U4, 1);
03776 else
03777 INITV_Set_VAL (Initv_Table[st],
03778 Enter_tcon (Host_To_Targ (MTYPE_U4, *i)), 1);
03779 INITV_IDX f = New_INITV();
03780 INITV_Set_VAL (Initv_Table[f],
03781 Enter_tcon (Host_To_Targ (MTYPE_U4, filter)), 1);
03782 Set_INITV_next (st, f);
03783
03784 INITV_IDX next_blk = New_INITV();
03785 INITV_Init_Block (next_blk, st);
03786 Set_INITV_next (last_blk, next_blk);
03787 last_blk = next_blk;
03788 filter++;
03789 }
03790 }
03791 }
03792
03793 Set_Tables (Callee_node());
03794 }
03795 void
03796 IPO_INLINE::Merge_EH_Tables (void)
03797 {
03798 Merge_EH_Typeinfo_Tables ();
03799 Merge_EH_Spec_Tables ();
03800 }
03801 #endif
03802
03803
03804 void
03805 IPO_INLINE::Process_Callee (IPO_INLINE_AUX& aux, BOOL same_file)
03806 {
03807 BOOL use_lowered_return_preg =
03808 Callee_Summary_Proc()->Use_lowered_return_preg ();
03809
03810 Is_True (use_lowered_return_preg ==
03811 Caller_Summary_Proc()->Use_lowered_return_preg (),
03812 ("Incompatible WHIRL between caller and callee"));
03813
03814 #ifndef KEY
03815
03816
03817
03818
03819
03820 Compute_Return_Preg_Offset (Callee_Wn (), aux.rp, use_lowered_return_preg,
03821 Caller_Scope(), Caller_level());
03822
03823 if (aux.rp.size () > 0 && WN_opcode (Call_Wn ()) != OPC_VCALL)
03824 Fix_Return_Pregs(Call_Wn (), aux.rp);
03825 #endif // !KEY
03826
03827 Set_Tables (Callee_node ());
03828
03829
03830
03831 aux.inlined_body = Clone_Callee (same_file);
03832
03833
03834
03835 WN_Parentize (aux.inlined_body, Caller_node()->Parent_Map(),
03836 Caller_Map_Table());
03837
03838 #ifdef KEY
03839 Merge_EH_Tables();
03840 #endif
03841 Set_Tables (Caller_node ());
03842 #ifdef KEY
03843
03844 Compute_Return_Preg_Offset (Callee_Wn (), aux.rp, use_lowered_return_preg,
03845 Caller_Scope(), Caller_level());
03846
03847 if (aux.rp.size () > 0 && WN_opcode (Call_Wn ()) != OPC_VCALL)
03848 Fix_Return_Pregs(Call_Wn (), aux.rp);
03849 #endif // !KEY
03850 Walk_and_Update_Callee (aux);
03851
03852
03853
03854
03855
03856
03857
03858
03859 }
03860
03861
03862
03863
03864
03865
03866
03867
03868
03869
03870
03871
03872
03873
03874
03875
03876
03877
03878
03879
03880
03881 void
03882 IPO_INLINE::Post_Process_Caller (IPO_INLINE_AUX& aux)
03883
03884 {
03885 Set_Tables (Caller_node ());
03886
03887 #ifdef KEY
03888 Caller_node()->Set_EH_spec_size (Caller_node()->EH_spec_size() +
03889 Callee_node()->EH_spec_size());
03890 #endif
03891 WN* call = Call_Wn ();
03892 WN* parent_wn = WN_Get_Parent(call, Parent_Map, Current_Map_Tab);
03893
03894 Is_True (((WN_operator(parent_wn) == OPR_BLOCK)),
03895 ("Illegal Parent for the call statement"));
03896
03897 const PU& pu = Pu_Table[ST_pu (Callee_node ()->Func_ST ())];
03898
03899 {
03900 INT64 lang = PU_src_lang (pu);
03901 ST* cp = Callee_node ()->Func_ST ();
03902
03903
03904 WN* pragma_node_begin =
03905 WN_CreatePragma (WN_PRAGMA_INLINE_BODY_START, cp, lang, 0);
03906
03907
03908
03909 WN_Set_Linenum (pragma_node_begin, WN_Get_Linenum (call));
03910
03911 WN* pragma_node_end =
03912 WN_CreatePragma (WN_PRAGMA_INLINE_BODY_END, cp, lang, 0);
03913
03914 Insert_Block_Around (parent_wn, call, pragma_node_begin,
03915 pragma_node_end);
03916 }
03917
03918
03919 if (INLINE_Optimize_Alloca) {
03920 PREG_NUM saved_sp;
03921 if (Alloca_Dealloca_On) {
03922 if (PU_has_user_alloca (pu)) {
03923 Save_And_Restore_Stack (call);
03924 }
03925 } else if (PU_has_alloca (pu)) {
03926 saved_sp = Process_Alloca_Preamble();
03927 Process_Alloca_Postamble (saved_sp);
03928 }
03929 }
03930
03931
03932 if (IPA_Enable_BarrierFarg || INLINE_Enable_Restrict_Pointers) {
03933 Generate_Barriers (parent_wn, call, aux);
03934 }
03935
03936
03937
03938
03939 Insert_Block_Around (parent_wn, call, aux.copy_in_block,
03940 aux.copy_out_block);
03941
03942 if (Callee_Summary_Proc()->Has_early_returns()) {
03943 if (IPA_Enable_DST)
03944 New_LABEL (Caller_level (), aux.entry_label);
03945 else
03946 aux.entry_label = 0;
03947
03948 Insert_Labels (call, aux.return_label, aux.entry_label,
03949 aux.inlined_body);
03950 }
03951
03952
03953
03954 if (WN_first (aux.inlined_body) != NULL) {
03955 WN_next (WN_prev (call)) = WN_first (aux.inlined_body);
03956 WN_prev (WN_first (aux.inlined_body)) = WN_prev (call);
03957
03958 WN_next (WN_last (aux.inlined_body)) = WN_next (call);
03959 WN_prev (WN_next (call)) = WN_last (aux.inlined_body);
03960 } else {
03961 WN_next (WN_prev (call)) = WN_next (call);
03962 WN_prev (WN_next (call)) = WN_prev (call);
03963 }
03964
03965 WN_Set_Linenum (WN_next (call), WN_Get_Linenum (call));
03966
03967 }
03968
03969
03970
03971
03972
03973
03974 void
03975 IPO_INLINE::Process()
03976 {
03977
03978 Temporary_Error_Phase ephase ("Inline processing");
03979
03980 initial_initv_tab_size = Initv_Table.Size();
03981
03982 BOOL same_file =
03983 (Caller_node ()->File_Index () == Callee_node ()->File_Index ()) ;
03984
03985
03986 IPO_INLINE_AUX aux_info (Callee_node ()->Num_Formals (), &Ipo_mem_pool);
03987
03988
03989
03990 Pre_Process_Caller (aux_info.return_label);
03991
03992
03993
03994
03995 Process_Callee (aux_info, same_file);
03996
03997 Post_Process_Caller (aux_info);
03998
03999
04000 Propagate_Flags (Caller_node (), Callee_node ());
04001
04002 #ifdef _LIGHTWEIGHT_INLINER
04003 if (INLINE_Use_Malloc_Mempool) {
04004 WN* wn = WN_func_body(Callee_Wn ());
04005 UINTPS inlined_body = (UINTPS)aux_info.inlined_body;
04006 if (OPCODE_has_next_prev(WN_opcode(wn)))
04007 inlined_body = inlined_body - ((UINTPS)&(WN_real_fields((STMT_WN *)wn)) - UINTPS(wn));
04008 Caller_node()->Add_to_inlined_list ((char *)inlined_body);
04009 }
04010 #endif
04011
04012 if (Cur_PU_Feedback) {
04013 #ifdef KEY
04014 const FB_VERIFY_STATUS status = Cur_PU_Feedback->Verify("IPA/inline");
04015 if( status == FB_VERIFY_UNBALANCED ){
04016 ;
04017
04018 } else if( status == FB_VERIFY_INVALID ){
04019 DevWarn( "Feedback Verify fails after inlining %s to %s",
04020 Callee_node()->Name(), Caller_node()->Name() );
04021 }
04022 #else
04023 BOOL not_pass = Cur_PU_Feedback->Verify("IPA/inline");
04024 if ( not_pass ) {
04025 DevWarn("Feedback Verify fails after inlining %s to %s",
04026 Callee_node()->Name (), Caller_node()->Name ());
04027 }
04028 #endif // KEY
04029 }
04030
04031 #if (!defined(_STANDALONE_INLINER) && !defined(_LIGHTWEIGHT_INLINER))
04032 if (IPA_Enable_DST) {
04033
04034
04035
04036 Current_DST = Callee_file_dst();
04037
04038 Set_FILE_INFO_has_inlines(Caller_file_info());
04039
04040 DST_subprogram_concrete_to_abstract(Callee_dst());
04041
04042
04043
04044
04045
04046 DST_enter_inlined_subroutine(Caller_dst(), Callee_dst(),
04047 aux_info.entry_label, aux_info.return_label,
04048 Caller_file_dst(),
04049 Callee_file_dst(),
04050 Symtab(), Caller_node ()->Mem_Pool (),
04051 Callee_node ()->Mem_Pool (),
04052 same_file ? 0 : Callee_cross_file_id());
04053 }
04054 #endif // _STANDALONE_INLINER
04055
04056 }
04057