00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073 #ifdef _KEEP_RCS_ID
00074 static char *rcs_id = "$Source: /proj/osprey/CVS/open64/osprey1.0/be/whirl2c/PUinfo.cxx,v $ $Revision: 1.1.1.1 $";
00075 #endif
00076
00077 #include <string.h>
00078
00079 #ifdef BUILD_WHIRL2C
00080 # include "whirl2c_common.h"
00081 #else
00082 # include "whirl2f_common.h"
00083 #endif
00084 #include "w2cf_parentize.h"
00085 #include "mempool.h"
00086 #include "const.h"
00087 #include "wn_util.h"
00088 #include "PUinfo.h"
00089 #include "targ_sim.h"
00090
00091 #define IS_RETURN_PREG(wn) \
00092 (ST_class(WN_st(wn)) == CLASS_PREG \
00093 && (Is_Return_Preg(WN_load_offset(wn)) \
00094 || WN_st(wn) == Return_Val_Preg ) )
00095
00096
00097
00098
00099 const WN *PUinfo_current_func = NULL;
00100 const RETURN_PREG *PUinfo_return_preg = NULL;
00101 TOKEN_BUFFER PUinfo_local_decls = NULL;
00102 TOKEN_BUFFER PUinfo_pragmas = NULL;
00103 UINT PUinfo_local_decls_indent = 0;
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127 typedef enum Preg_Usage_Kind
00128 {
00129 PREG_AS_UNKNOWN,
00130 PREG_AS_INT8,
00131 PREG_AS_UINT8,
00132 PREG_AS_INT16,
00133 PREG_AS_UINT16,
00134 PREG_AS_INT32,
00135 PREG_AS_UINT32,
00136 PREG_AS_INT64,
00137 PREG_AS_UINT64,
00138 PREG_AS_IEEE32,
00139 PREG_AS_IEEE64,
00140 PREG_AS_IEEE80,
00141 PREG_AS_QUAD,
00142 PREG_AS_C4,
00143 PREG_AS_C8,
00144 PREG_AS_C10,
00145 PREG_AS_CQ
00146 } PREG_USAGE_KIND;
00147
00148 #define FIRST_PREG_USAGE_KIND PREG_AS_INT8
00149 #define SMALLEST_iPREG_USAGE_KIND FIRST_PREG_USAGE_KIND
00150 #define LARGEST_iPREG_USAGE_KIND PREG_AS_UINT64
00151 #define LAST_PREG_USAGE_KIND PREG_AS_CQ
00152
00153 static const MTYPE Ukind_to_Mtype[LAST_PREG_USAGE_KIND+1] =
00154 {
00155 MTYPE_UNKNOWN,
00156 MTYPE_I1,
00157 MTYPE_U1,
00158 MTYPE_I2,
00159 MTYPE_U2,
00160 MTYPE_I4,
00161 MTYPE_U4,
00162 MTYPE_I8,
00163 MTYPE_U8,
00164 MTYPE_F4,
00165 MTYPE_F8,
00166 MTYPE_F10,
00167 MTYPE_FQ,
00168 MTYPE_C4,
00169 MTYPE_C8,
00170 MTYPE_C10,
00171 MTYPE_CQ
00172 };
00173
00174 typedef struct Preg_Info PREG_INFO;
00175 struct Preg_Info
00176 {
00177 BOOL use[LAST_PREG_USAGE_KIND+1];
00178 BOOL decl[LAST_PREG_USAGE_KIND+1];
00179 INT16 preg_num;
00180 PREG_INFO *next;
00181 };
00182 #define PREG_INFO_use(info, ukind) (info)->use[ukind]
00183 #define PREG_INFO_decl(info, ukind) (info)->decl[ukind]
00184 #define PREG_INFO_preg_num(info) (info)->preg_num
00185 #define PREG_INFO_next(info) (info)->next
00186
00187 #define PREG_INFO_HASH_TABLE_SIZE 73
00188 #define PREG_INFO_HASH_IDX(offset) \
00189 (UINT32)(offset % PREG_INFO_HASH_TABLE_SIZE)
00190
00191 static PREG_INFO *Preg_Info_Hash_Tbl[PREG_INFO_HASH_TABLE_SIZE];
00192 static PREG_INFO *Free_Preg_Info = NULL;
00193
00194
00195 static BOOL
00196 WN_in_ioitem(const WN *wn)
00197 {
00198
00199
00200 BOOL found_io = FALSE, found_region = FALSE;
00201
00202 wn = W2CF_Get_Parent(wn);
00203 while (wn != NULL && !found_io && !found_region)
00204 {
00205 if (WN_opc_operator(wn) == OPR_IO_ITEM)
00206 found_io = TRUE;
00207 else if (WN_opc_operator(wn) == OPR_REGION)
00208 found_region = TRUE;
00209 wn = W2CF_Get_Parent(wn);
00210 }
00211 return (found_io);
00212 }
00213
00214
00215 static PREG_USAGE_KIND
00216 Mtype_to_Ukind(MTYPE mtype)
00217 {
00218
00219
00220
00221
00222
00223
00224 PREG_USAGE_KIND ukind;
00225
00226 switch (mtype)
00227 {
00228 case MTYPE_B:
00229 ukind = PREG_AS_INT8;
00230 break;
00231 case MTYPE_I1:
00232 ukind = PREG_AS_INT8;
00233 break;
00234 case MTYPE_U1:
00235 ukind = PREG_AS_UINT8;
00236 break;
00237 case MTYPE_I2:
00238 ukind = PREG_AS_INT16;
00239 break;
00240 case MTYPE_U2:
00241 ukind = PREG_AS_UINT16;
00242 break;
00243 case MTYPE_I4:
00244 ukind = PREG_AS_INT32;
00245 break;
00246 case MTYPE_U4:
00247 ukind = PREG_AS_UINT32;
00248 break;
00249 case MTYPE_I8:
00250 ukind = PREG_AS_INT64;
00251 break;
00252 case MTYPE_U8:
00253 ukind = PREG_AS_UINT64;
00254 break;
00255 case MTYPE_F4:
00256 ukind = PREG_AS_IEEE32;
00257 break;
00258 case MTYPE_F8:
00259 ukind = PREG_AS_IEEE64;
00260 break;
00261 case MTYPE_F10:
00262 ukind = PREG_AS_IEEE80;
00263 break;
00264 case MTYPE_FQ:
00265 ukind = PREG_AS_QUAD;
00266 break;
00267 case MTYPE_C4:
00268 ukind = PREG_AS_C4;
00269 break;
00270 case MTYPE_C8:
00271 ukind = PREG_AS_C8;
00272 break;
00273 case MTYPE_C10:
00274 ukind = PREG_AS_C10;
00275 break;
00276 case MTYPE_CQ:
00277 ukind = PREG_AS_CQ;
00278 break;
00279 #ifdef TARG_X8664
00280 case MTYPE_V16C4:
00281 case MTYPE_V16C8:
00282 case MTYPE_V16I1:
00283 case MTYPE_V16I2:
00284 case MTYPE_V16I4:
00285 case MTYPE_V16I8:
00286 case MTYPE_V16F4:
00287 case MTYPE_V16F8:
00288
00289 case MTYPE_V8I1:
00290 case MTYPE_V8I2:
00291 case MTYPE_V8I4:
00292 case MTYPE_V8F4:
00293
00294 case MTYPE_M8I1:
00295 case MTYPE_M8I2:
00296 case MTYPE_M8I4:
00297 case MTYPE_M8F4:
00298 ukind = PREG_AS_IEEE64;
00299 break;
00300 #endif
00301 default:
00302 Is_True(FALSE, ("Illegal MTYPE for Mtype_to_Ukind mapping"));
00303 break;
00304 }
00305 return ukind;
00306 }
00307
00308
00309 static PREG_INFO *
00310 Get_Preg_Info(INT16 preg_num)
00311 {
00312 PREG_INFO *preg_info = NULL;
00313
00314 if (preg_num < 0)
00315 return NULL;
00316
00317
00318 for (preg_info = Preg_Info_Hash_Tbl[PREG_INFO_HASH_IDX(preg_num)];
00319 preg_info != NULL && PREG_INFO_preg_num(preg_info) != preg_num;
00320 preg_info = PREG_INFO_next(preg_info));
00321 return preg_info;
00322 }
00323
00324
00325 static void
00326 Accumulate_Preg_Info(TY_IDX preg_ty, INT16 preg_num)
00327 {
00328
00329
00330
00331 PREG_INFO *preg_info;
00332 INT usage_kind;
00333
00334 if (preg_num <= -1)
00335 return;
00336
00337 Is_True(TY_Is_Scalar(preg_ty),
00338 ("Expected KIND_SCALAR symbol in Accumulate_Preg_Info()"));
00339
00340
00341
00342
00343 preg_info = Get_Preg_Info(preg_num);
00344 if (preg_info == NULL)
00345 {
00346
00347 if (Free_Preg_Info == NULL)
00348 preg_info = TYPE_ALLOC_N(PREG_INFO, 1);
00349 else
00350 {
00351 preg_info = Free_Preg_Info;
00352 Free_Preg_Info = PREG_INFO_next(Free_Preg_Info);
00353 }
00354
00355
00356 for (usage_kind = (INT)FIRST_PREG_USAGE_KIND;
00357 usage_kind <= (INT)LAST_PREG_USAGE_KIND;
00358 usage_kind++)
00359 {
00360 PREG_INFO_decl(preg_info, usage_kind) = FALSE;
00361 PREG_INFO_use(preg_info, usage_kind) = FALSE;
00362 }
00363 PREG_INFO_preg_num(preg_info) = preg_num;
00364 PREG_INFO_next(preg_info) =
00365 Preg_Info_Hash_Tbl[PREG_INFO_HASH_IDX(preg_num)];
00366 Preg_Info_Hash_Tbl[PREG_INFO_HASH_IDX(preg_num)] = preg_info;
00367 }
00368
00369
00370 usage_kind = (INT)Mtype_to_Ukind(TY_mtype(preg_ty));
00371 PREG_INFO_use(preg_info, usage_kind) = TRUE;
00372 }
00373
00374
00375 static void
00376 Enter_Pregs_Into_Symtab(void)
00377 {
00378
00379
00380
00381
00382
00383
00384
00385 TY_IDX preg_ty;
00386 PREG_INFO *preg_info;
00387 INT hash_idx;
00388 INT usage_kind;
00389
00390 for (hash_idx = 0; hash_idx < PREG_INFO_HASH_TABLE_SIZE; hash_idx++)
00391 for (preg_info = Preg_Info_Hash_Tbl[hash_idx];
00392 preg_info != NULL;
00393 preg_info = PREG_INFO_next(preg_info))
00394 {
00395
00396
00397
00398 for (usage_kind = (INT)LARGEST_iPREG_USAGE_KIND;
00399 (usage_kind >= (INT)SMALLEST_iPREG_USAGE_KIND &&
00400 !PREG_INFO_use(preg_info, usage_kind));
00401 usage_kind--);
00402
00403 if (usage_kind >= (INT)SMALLEST_iPREG_USAGE_KIND)
00404 {
00405 preg_ty = Stab_Mtype_To_Ty(Ukind_to_Mtype[usage_kind]);
00406 W2CF_Symtab_Nameof_Preg(preg_ty, PREG_INFO_preg_num(preg_info));
00407 }
00408
00409
00410 for (usage_kind = (INT)LARGEST_iPREG_USAGE_KIND + 1;
00411 usage_kind <= (INT)LAST_PREG_USAGE_KIND;
00412 usage_kind++)
00413 {
00414 if (PREG_INFO_use(preg_info, usage_kind))
00415 {
00416 preg_ty = Stab_Mtype_To_Ty(Ukind_to_Mtype[usage_kind]);
00417 W2CF_Symtab_Nameof_Preg(preg_ty, PREG_INFO_preg_num(preg_info));
00418 }
00419 }
00420 }
00421 }
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432 static void
00433 Enter_Local_Syms_Into_Symtab(const ST *func_st)
00434 {
00435 ST_IDX st_idx;
00436 const ST *st;
00437
00438 (void)W2CF_Symtab_Nameof_St(func_st);
00439 FOREACH_SYMBOL(CURRENT_SYMTAB, st, st_idx)
00440 {
00441 if ((ST_sym_class(st) == CLASS_VAR || ST_sym_class(st) == CLASS_FUNC) &&
00442 !Stab_Is_Based_At_Common_Or_Equivalence(st))
00443 {
00444 #ifdef BUILD_WHIRL2F
00445 if (TY_Is_Pointer(ST_type(st)))
00446 (void)W2CF_Symtab_Nameof_St_Pointee(st);
00447 #endif
00448 (void)W2CF_Symtab_Nameof_St(st);
00449 }
00450 }
00451 }
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535 #define PUINFO_WN_ITER_wn(iter) \
00536 (iter != NULL? WN_ITER_wn(iter) : NULL)
00537 #define PUINFO_WN_WALK_TreeNext(iter) \
00538 (iter != NULL? WN_WALK_TreeNext(iter) : NULL)
00539 #define PUINFO_WN_WALK_StmtNext(iter) \
00540 (iter != NULL? WN_WALK_StmtNext(iter) : NULL)
00541
00542 static CALLSITE *CallSite_First = NULL;
00543 static CALLSITE *CallSite_Last = NULL;
00544 static CALLSITE *CallSite_Free = NULL;
00545
00546 static RETURNSITE *ReturnSite_First = NULL;
00547 static RETURNSITE *ReturnSite_Last = NULL;
00548 static RETURNSITE *ReturnSite_Free = NULL;
00549
00550
00551 static void
00552 Var_Loaded_From(const WN *wn,
00553 const ST **st,
00554 STAB_OFFSET *offset)
00555 {
00556 Is_True(wn != NULL, ("wn==NULL in Var_Loaded_From()"));
00557 if (WN_opc_operator(wn) == OPR_LDID)
00558 {
00559 *st = WN_st(wn);
00560 *offset = WN_load_offset(wn);
00561 }
00562 else if (WN_opc_operator(wn) == OPR_ILOAD &&
00563 WN_opc_operator(WN_kid0(wn)) == OPR_LDA)
00564 {
00565 *st = WN_st(WN_kid0(wn));
00566 *offset = WN_load_offset(wn) + WN_lda_offset(WN_kid0(wn));
00567 }
00568 else
00569 {
00570 *st = NULL;
00571 *offset = -1;
00572 }
00573 }
00574
00575
00576 static void
00577 Var_Stored_In(const WN *wn,
00578 const ST **st,
00579 STAB_OFFSET *offset)
00580 {
00581 Is_True(wn != NULL, ("wn==NULL in Var_Stored_In()"));
00582 if (WN_opc_operator(wn) == OPR_STID)
00583 {
00584 *st = WN_st(wn);
00585 *offset = WN_store_offset(wn);
00586 }
00587 else if (WN_opc_operator(wn) == OPR_ISTORE &&
00588 WN_opc_operator(WN_kid1(wn)) == OPR_LDA)
00589 {
00590 *st = WN_st(WN_kid1(wn));
00591 *offset = WN_store_offset(wn) + WN_lda_offset(WN_kid1(wn));
00592 }
00593 else
00594 {
00595 *st = NULL;
00596 *offset = -1;
00597 }
00598 }
00599
00600
00601 static const WN *
00602 Does_Stmt_Store_From_Preg(const WN *wn, STAB_OFFSET preg_num)
00603 {
00604 if ((WN_opc_operator(wn) == OPR_STID ||
00605 WN_opc_operator(wn) == OPR_ISTORE) &&
00606 WN_opc_operator(WN_kid0(wn)) == OPR_LDID &&
00607 ST_sym_class(WN_st(WN_kid0(wn))) == CLASS_PREG &&
00608 WN_load_offset(WN_kid0(wn)) == preg_num)
00609 return wn;
00610 else
00611 return NULL;
00612 }
00613
00614
00615 static const WN *
00616 Does_Stmt_Store_Into_Preg(const WN *wn, STAB_OFFSET preg_num)
00617 {
00618 if (WN_opc_operator(wn) == OPR_STID &&
00619 ST_sym_class(WN_st(wn)) == CLASS_PREG &&
00620 WN_store_offset(wn) == preg_num)
00621 return wn;
00622 else
00623 return NULL;
00624 }
00625
00626
00627 static CALLSITE *
00628 New_CallSite(const WN *call_wn,
00629 TY_IDX return_ty,
00630 const WN *store1_wn,
00631 const WN *store2_wn,
00632 const ST *return_var,
00633 STAB_OFFSET var_offset)
00634 {
00635 CALLSITE *callsite;
00636
00637 if (CallSite_Free != NULL)
00638 {
00639 callsite = CallSite_Free;
00640 CallSite_Free = CALLSITE_next(CallSite_Free);
00641 }
00642 else
00643 {
00644 callsite = TYPE_ALLOC_N(CALLSITE, 1);
00645 }
00646 if (CallSite_Last == NULL)
00647 {
00648 CallSite_Last = callsite;
00649 CallSite_First = callsite;
00650 }
00651 else
00652 {
00653 CALLSITE_next(CallSite_Last) = callsite;
00654 CallSite_Last = callsite;
00655 }
00656 CALLSITE_call(callsite) = call_wn;
00657 CALLSITE_return_ty(callsite) = return_ty;
00658 CALLSITE_store1(callsite) = store1_wn;
00659 CALLSITE_store2(callsite) = store2_wn;
00660 CALLSITE_return_var(callsite) = return_var;
00661 CALLSITE_var_offset(callsite) = var_offset;
00662 CALLSITE_in_regs(callsite) = FALSE;
00663 CALLSITE_next(callsite) = NULL;
00664
00665 return callsite;
00666 }
00667
00668
00669 static RETURNSITE *
00670 New_ReturnSite(const WN *return_wn,
00671 const WN *store1_wn,
00672 const WN *store2_wn,
00673 const ST *return_var,
00674 STAB_OFFSET var_offset)
00675 {
00676 RETURNSITE *return_info;
00677
00678 if (ReturnSite_Free != NULL)
00679 {
00680 return_info = ReturnSite_Free;
00681 ReturnSite_Free = RETURNSITE_next(ReturnSite_Free);
00682 }
00683 else
00684 {
00685 return_info = TYPE_ALLOC_N(RETURNSITE, 1);
00686 }
00687 if (ReturnSite_Last == NULL)
00688 {
00689 ReturnSite_Last = return_info;
00690 ReturnSite_First = return_info;
00691 }
00692 else
00693 {
00694 RETURNSITE_next(ReturnSite_Last) = return_info;
00695 ReturnSite_Last = return_info;
00696 }
00697 RETURNSITE_return(return_info) = return_wn;
00698 RETURNSITE_store1(return_info) = store1_wn;
00699 RETURNSITE_store2(return_info) = store2_wn;
00700 RETURNSITE_return_var(return_info) = return_var;
00701 RETURNSITE_var_offset(return_info) = var_offset;
00702 RETURNSITE_next(return_info) = NULL;
00703
00704 return return_info;
00705 }
00706
00707
00708 static WN_ITER *
00709 Append_CallSite(WN_ITER *stmt_iter, const WN *next_stmt)
00710 {
00711
00712
00713
00714
00715 TY_IDX return_ty;
00716
00717 RETURN_PREG return_preg;
00718 const RETURN_PREG * const return_preg_ptr = &return_preg;
00719
00720 const ST *save_var1 = NULL;
00721 const ST *save_var2;
00722 STAB_OFFSET save_offset1 = 0;
00723 STAB_OFFSET save_offset2;
00724 const WN *store1 = NULL;
00725 const WN *store2 = NULL;
00726
00727 const WN * const call_wn = next_stmt;
00728
00729
00730 if (WN_opc_operator(call_wn) == OPR_CALL ||
00731 WN_opc_operator(call_wn) == OPR_PICCALL)
00732 {
00733 Is_True(WN_entry_name(call_wn) != 0,
00734 ("Missing WN_entry_name() for %s",
00735 OPCODE_name(WN_opcode(call_wn))));
00736 return_ty =
00737 Func_Return_Type(ST_pu_type(&St_Table[WN_entry_name(call_wn)]));
00738 }
00739 else if (WN_opc_operator(call_wn) == OPR_ICALL)
00740 {
00741
00742
00743
00744
00745
00746 return_ty = Func_Return_Type(WN_ty(call_wn));
00747 }
00748 else
00749 {
00750 Is_True(WN_opc_operator(call_wn) == OPR_INTRINSIC_CALL,
00751 ("Expected OPR_INTRINSIC_CALL node in Append_CallSite()"));
00752
00753 return_ty = WN_intrinsic_return_ty(WN_opcode(call_wn),
00754 (INTRINSIC)WN_intrinsic(call_wn),
00755 call_wn);
00756 }
00757
00758
00759
00760
00761 return_preg = PUinfo_Get_ReturnPreg(return_ty);
00762
00763
00764 next_stmt = PUINFO_WN_ITER_wn(stmt_iter);
00765
00766
00767 if (RETURN_PREG_num_pregs(return_preg_ptr) > 0 && next_stmt != NULL)
00768 {
00769
00770 store1 =
00771 Does_Stmt_Store_From_Preg(next_stmt,
00772 RETURN_PREG_offset(return_preg_ptr, 0));
00773
00774
00775
00776
00777 if (store1 != NULL)
00778 {
00779
00780 Var_Stored_In(next_stmt, &save_var1, &save_offset1);
00781
00782
00783
00784
00785
00786
00787 stmt_iter = PUINFO_WN_WALK_StmtNext(stmt_iter);
00788 next_stmt = PUINFO_WN_ITER_wn(stmt_iter);
00789
00790
00791
00792
00793 if (RETURN_PREG_num_pregs(return_preg_ptr) > 1 &&
00794 next_stmt != NULL &&
00795 save_var1 != NULL &&
00796 ST_sym_class(save_var1) != CLASS_PREG)
00797 {
00798 store2 =
00799 Does_Stmt_Store_From_Preg(next_stmt,
00800 RETURN_PREG_offset(return_preg_ptr,
00801 1 ));
00802
00803 if (store2 != NULL)
00804 {
00805 Var_Stored_In(next_stmt, &save_var2, &save_offset2);
00806 if (save_var1 == save_var2 && save_offset1 < save_offset2)
00807 stmt_iter = PUINFO_WN_WALK_StmtNext(stmt_iter);
00808 else
00809 {
00810 store1 = store2 = NULL;
00811 save_var1 = NULL;
00812 }
00813 }
00814 else
00815 {
00816 save_var1 = NULL;
00817 store1 = NULL;
00818 }
00819 }
00820 else if (RETURN_PREG_num_pregs(return_preg_ptr) > 1)
00821 {
00822
00823
00824
00825 save_var1 = NULL;
00826 store1 = NULL;
00827 }
00828 }
00829 }
00830
00831 (void)New_CallSite(call_wn, return_ty, store1, store2,
00832 save_var1, save_offset1);
00833
00834 return stmt_iter;
00835 }
00836
00837
00838 static WN_ITER *
00839 Append_ReturnSite(WN_ITER *stmt_iter, const WN *first_stmt)
00840 {
00841
00842
00843
00844 const WN *stmt = first_stmt;
00845 const ST *load_var1 = NULL;
00846 const ST *load_var2;
00847 STAB_OFFSET load_offset1 = 0;
00848 STAB_OFFSET load_offset2;
00849
00850 const WN *store1 = NULL;
00851 const WN *store2 = NULL;
00852
00853
00854
00855
00856 if (RETURN_PREG_num_pregs(PUinfo_return_preg) > 0 &&
00857 WN_opc_operator(stmt) == OPR_STID)
00858 {
00859
00860 store1 =
00861 Does_Stmt_Store_Into_Preg(stmt,
00862 RETURN_PREG_offset(PUinfo_return_preg, 0));
00863
00864
00865
00866
00867 if (store1 != NULL)
00868 {
00869
00870
00871
00872 Var_Loaded_From(WN_kid0(stmt), &load_var1, &load_offset1);
00873
00874
00875 stmt = PUINFO_WN_ITER_wn(stmt_iter);
00876
00877
00878
00879
00880 if (RETURN_PREG_num_pregs(PUinfo_return_preg) > 1 &&
00881 stmt != NULL &&
00882 WN_opc_operator(stmt) == OPR_STID &&
00883 load_var1 != NULL &&
00884 ST_sym_class(load_var1) != CLASS_PREG)
00885 {
00886 store2 =
00887 Does_Stmt_Store_Into_Preg(stmt,
00888 RETURN_PREG_offset(PUinfo_return_preg,
00889 1 ));
00890 if (store2 != NULL)
00891 {
00892 Var_Loaded_From(WN_kid0(stmt), &load_var2, &load_offset2);
00893 if (load_var1 == load_var2 && load_offset1 < load_offset2)
00894 {
00895 stmt_iter = PUINFO_WN_WALK_StmtNext(stmt_iter);
00896 stmt = PUINFO_WN_ITER_wn(stmt_iter);
00897 }
00898 else
00899 {
00900 store1 = store2 = NULL;
00901 load_var1 = NULL;
00902 stmt = first_stmt;
00903 }
00904 }
00905 else
00906 {
00907 store1 = NULL;
00908 load_var1 = NULL;
00909 stmt = first_stmt;
00910 }
00911 }
00912 else if (RETURN_PREG_num_pregs(PUinfo_return_preg) > 1)
00913 {
00914
00915
00916
00917 store1 = NULL;
00918 load_var1 = NULL;
00919 stmt = first_stmt;
00920 }
00921 }
00922 }
00923
00924
00925 if (stmt != NULL && WN_opc_operator(stmt) == OPR_RETURN)
00926 {
00927 (void)New_ReturnSite(stmt, store1, store2, load_var1, load_offset1);
00928
00929 if (stmt != first_stmt)
00930 stmt_iter = PUINFO_WN_WALK_StmtNext(stmt_iter);
00931 }
00932
00933 return stmt_iter;
00934 }
00935
00936
00937
00938
00939
00940 static void
00941 Accumulate_Stmt_PUinfo(WN *wn)
00942 {
00943
00944
00945
00946
00947 WN_ITER *stmt_iter = WN_WALK_StmtIter(wn);
00948 const WN *parent;
00949 const WN *gparent;
00950
00951
00952 while (stmt_iter != NULL)
00953 {
00954 const WN *stmt = PUINFO_WN_ITER_wn(stmt_iter);
00955
00956 if (stmt != NULL)
00957 {
00958 switch(WN_opc_operator(stmt))
00959 {
00960 case OPR_CALL:
00961 case OPR_ICALL:
00962 case OPR_PICCALL:
00963 case OPR_INTRINSIC_CALL:
00964
00965
00966
00967
00968
00969 parent = W2CF_Get_Parent(stmt);
00970 gparent = W2CF_Get_Parent(parent);
00971 if (!WN_in_ioitem(stmt) &&
00972 (WN_opc_operator(gparent) != OPR_REGION ||
00973 WN_region_pragmas(gparent) != parent))
00974 {
00975
00976
00977
00978
00979 stmt_iter =
00980 Append_CallSite(PUINFO_WN_WALK_StmtNext(stmt_iter), stmt);
00981 }
00982 else
00983 stmt_iter = PUINFO_WN_WALK_StmtNext(stmt_iter);
00984 break;
00985
00986 case OPR_STID:
00987
00988
00989
00990
00991 stmt_iter =
00992 Append_ReturnSite(PUINFO_WN_WALK_StmtNext(stmt_iter), stmt);
00993 break;
00994
00995 case OPR_RETURN:
00996
00997
00998
00999 stmt_iter =
01000 Append_ReturnSite(PUINFO_WN_WALK_StmtNext(stmt_iter), stmt);
01001 break;
01002
01003 default:
01004 stmt_iter = PUINFO_WN_WALK_StmtNext(stmt_iter);
01005 break;
01006 }
01007 }
01008 }
01009 }
01010
01011
01012 static void
01013 Accumulate_Expr_PUinfo(WN *root)
01014 {
01015
01016
01017
01018
01019
01020 WN_ITER *wn_iter;
01021 const WN *wn;
01022 const WN *parent;
01023 const WN *gparent;
01024 const WN *next_return_ldid = NULL;
01025 CALLSITE *last_callsite = NULL;
01026
01027
01028 for (wn_iter = WN_WALK_TreeIter(root);
01029 wn_iter != NULL;
01030 wn_iter = PUINFO_WN_WALK_TreeNext(wn_iter))
01031 {
01032
01033
01034
01035
01036
01037 wn = PUINFO_WN_ITER_wn(wn_iter);
01038 if (wn != NULL)
01039 switch(WN_opc_operator(wn))
01040 {
01041 case OPR_STID:
01042 if (ST_sym_class(WN_st(wn)) == CLASS_PREG)
01043 Accumulate_Preg_Info(ST_type(WN_st(wn)), WN_store_offset(wn));
01044
01045
01046
01047
01048
01049
01050
01051 case OPR_ISTORE:
01052 if (last_callsite != NULL &&
01053 (CALLSITE_store1(last_callsite) == wn ||
01054 CALLSITE_store2(last_callsite) == wn))
01055 {
01056
01057 Is_True(WN_operator(WN_kid0(wn)) == OPR_LDID &&
01058 IS_RETURN_PREG(WN_kid0(wn)),
01059 ("Unexpected CALLSITE in Accumulate_Expr_PUinfo()"));
01060
01061 next_return_ldid = WN_kid0(wn);
01062 }
01063 break;
01064
01065 case OPR_LDID:
01066 if (ST_sym_class(WN_st(wn)) == CLASS_PREG)
01067 {
01068 Accumulate_Preg_Info(ST_type(WN_st(wn)), WN_load_offset(wn));
01069
01070
01071
01072
01073
01074
01075 if (next_return_ldid == wn)
01076 next_return_ldid = NULL;
01077 else if (last_callsite != NULL && IS_RETURN_PREG(wn))
01078 CALLSITE_in_regs(last_callsite) = TRUE;
01079 }
01080 break;
01081
01082 case OPR_LDA:
01083
01084 Is_True(ST_sym_class(WN_st(wn)) != CLASS_PREG,
01085 ("Attempt to LDA a PREG in Accumulate_Expr_PUinfo()"));
01086 break;
01087
01088 case OPR_CALL:
01089 case OPR_ICALL:
01090 case OPR_PICCALL:
01091 case OPR_INTRINSIC_CALL:
01092
01093
01094 parent = W2CF_Get_Parent(wn);
01095 gparent = W2CF_Get_Parent(parent);
01096 if (!WN_in_ioitem(wn) &&
01097 (WN_opc_operator(gparent) != OPR_REGION ||
01098 WN_region_pragmas(gparent) != parent))
01099 {
01100
01101
01102
01103
01104
01105 if (last_callsite == NULL)
01106 last_callsite = PUinfo_Get_CallSites();
01107 else
01108 last_callsite = CALLSITE_next(last_callsite);
01109
01110 Is_True(CALLSITE_call(last_callsite) == wn,
01111 ("Unexpected callsite order in Accumulate_Expr_PUinfo()"));
01112 }
01113 break;
01114
01115 case OPR_RETURN:
01116
01117
01118
01119
01120
01121 if (RETURN_PREG_num_pregs(PUinfo_return_preg) > 0)
01122 {
01123 TY_IDX preg_ty;
01124 STAB_OFFSET preg_offset;
01125
01126 preg_offset = RETURN_PREG_offset(PUinfo_return_preg, 0);
01127 preg_ty =
01128 Stab_Mtype_To_Ty(RETURN_PREG_mtype(PUinfo_return_preg, 0));
01129 Accumulate_Preg_Info(preg_ty, preg_offset);
01130 if (RETURN_PREG_num_pregs(PUinfo_return_preg) > 1)
01131 {
01132 preg_offset = RETURN_PREG_offset(PUinfo_return_preg, 1);
01133 preg_ty =
01134 Stab_Mtype_To_Ty(RETURN_PREG_mtype(PUinfo_return_preg, 1));
01135 Accumulate_Preg_Info(preg_ty, preg_offset);
01136 }
01137 }
01138 break;
01139
01140 default:
01141 break;
01142 }
01143 }
01144 }
01145
01146
01147
01148
01149
01150 void
01151 PUinfo_initialize(void)
01152 {
01153 Is_True(PUinfo_local_decls == NULL &&
01154 PUinfo_current_func == NULL &&
01155 PUinfo_return_preg == NULL,
01156 ("Unexpected state in PUinfo_init()"));
01157
01158 }
01159
01160
01161 void
01162 PUinfo_finalize(void)
01163 {
01164
01165 CALLSITE *callsite;
01166 RETURNSITE *returnsite;
01167
01168
01169 while (CallSite_Free != NULL)
01170 {
01171 callsite = CallSite_Free;
01172 CallSite_Free = CALLSITE_next(callsite);
01173 FREE(callsite);
01174 }
01175
01176
01177 while (ReturnSite_Free != NULL)
01178 {
01179 returnsite = ReturnSite_Free;
01180 ReturnSite_Free = CALLSITE_next(returnsite);
01181 FREE(returnsite);
01182 }
01183 }
01184
01185
01186 void
01187 PUinfo_init_pu(const WN *pu, WN *body_part_of_interest)
01188 {
01189
01190
01191
01192
01193
01194
01195 static RETURN_PREG preg_info;
01196
01197 Is_True(WN_operator(pu) == OPR_FUNC_ENTRY,
01198 ("Expected an OPR_FUNC_ENTRY node in PUinfo_init()"));
01199
01200
01201 Is_True(PUinfo_local_decls == NULL &&
01202 PUinfo_pragmas == NULL &&
01203 PUinfo_current_func == NULL &&
01204 PUinfo_return_preg == NULL,
01205 ("Unexpected state in PUinfo_init_pu()"));
01206
01207 PUinfo_current_func = pu;
01208 preg_info = PUinfo_Get_ReturnPreg(PUINFO_RETURN_TY);
01209 PUinfo_return_preg = &preg_info;
01210 PUinfo_local_decls = New_Token_Buffer();
01211 PUinfo_pragmas = New_Token_Buffer();
01212
01213
01214
01215
01216
01217 if (!OPCODE_is_expression(WN_opcode(body_part_of_interest)))
01218 Accumulate_Stmt_PUinfo(body_part_of_interest);
01219
01220
01221
01222
01223
01224
01225 Accumulate_Expr_PUinfo(body_part_of_interest);
01226
01227
01228
01229
01230
01231
01232
01233 W2CF_Symtab_Push();
01234 Enter_Local_Syms_Into_Symtab(&St_Table[WN_entry_name(pu)]);
01235 Enter_Pregs_Into_Symtab();
01236
01237 }
01238
01239
01240 void
01241 PUinfo_exit_pu(void)
01242 {
01243
01244
01245
01246 UINT32 hash_idx;
01247 CALLSITE *callsite;
01248 RETURNSITE *returnsite;
01249
01250
01251 W2CF_Symtab_Pop();
01252
01253
01254 for (hash_idx = 0; hash_idx < PREG_INFO_HASH_TABLE_SIZE; hash_idx++)
01255 {
01256 PREG_INFO *preg_info = Preg_Info_Hash_Tbl[hash_idx];
01257 if (preg_info != NULL)
01258 {
01259 while (PREG_INFO_next(preg_info) != NULL)
01260 preg_info = PREG_INFO_next(preg_info);
01261 PREG_INFO_next(preg_info) = Free_Preg_Info;
01262 Free_Preg_Info = Preg_Info_Hash_Tbl[hash_idx];
01263 Preg_Info_Hash_Tbl[hash_idx] = NULL;
01264 }
01265 }
01266
01267
01268 for (callsite = CallSite_First;
01269 callsite != NULL;
01270 callsite = CALLSITE_next(callsite))
01271 {
01272 CALLSITE_next(callsite) = CallSite_Free;
01273 CallSite_Free = callsite;
01274 }
01275 CallSite_First = NULL;
01276 CallSite_Last = NULL;
01277
01278
01279 for (returnsite = ReturnSite_First;
01280 returnsite != NULL;
01281 returnsite = RETURNSITE_next(returnsite))
01282 {
01283 RETURNSITE_next(returnsite) = ReturnSite_Free;
01284 ReturnSite_Free = returnsite;
01285 }
01286 ReturnSite_First = NULL;
01287 ReturnSite_Last = NULL;
01288
01289
01290 PUinfo_current_func = NULL;
01291 PUinfo_return_preg = NULL;
01292 if (PUinfo_local_decls != NULL)
01293 Reclaim_Token_Buffer(&PUinfo_local_decls);
01294 if (PUinfo_pragmas != NULL)
01295 Reclaim_Token_Buffer(&PUinfo_pragmas);
01296
01297 }
01298
01299
01300 TY_IDX
01301 PUinfo_Preg_Type(TY_IDX preg_ty, INT16 preg_num)
01302 {
01303
01304
01305
01306
01307
01308
01309 TY_IDX ty;
01310 PREG_INFO *preg_info;
01311 INT usage_kind, this_ukind;
01312
01313
01314
01315
01316 if (!TY_Is_Integral(preg_ty))
01317 ty = preg_ty;
01318 else
01319 {
01320 preg_info = Get_Preg_Info(preg_num);
01321 if (preg_info == NULL)
01322 {
01323 Accumulate_Preg_Info(preg_ty, preg_num);
01324 preg_info = Get_Preg_Info(preg_num);
01325 }
01326
01327 this_ukind = (INT)Mtype_to_Ukind(TY_mtype(preg_ty));
01328 for (usage_kind = (INT)LARGEST_iPREG_USAGE_KIND;
01329 (usage_kind >= this_ukind &&
01330 !PREG_INFO_use(preg_info, usage_kind));
01331 usage_kind--);
01332 ty = Stab_Mtype_To_Ty(Ukind_to_Mtype[usage_kind]);
01333 }
01334 return ty;
01335 }
01336
01337
01338 BOOL
01339 PUinfo_Is_Preg_Declared(TY_IDX preg_ty, INT16 preg_num)
01340 {
01341 if (preg_ty == 0 || preg_num == -1)
01342 return TRUE;
01343
01344 PREG_INFO *preg_info = Get_Preg_Info(preg_num);
01345
01346 if (preg_info == NULL)
01347 {
01348 Accumulate_Preg_Info(preg_ty, preg_num);
01349 preg_info = Get_Preg_Info(preg_num);
01350 }
01351
01352 return PREG_INFO_decl(preg_info, Mtype_to_Ukind(TY_mtype(preg_ty)));
01353 }
01354
01355
01356 void
01357 PUinfo_Set_Preg_Declared(TY_IDX preg_ty, INT16 preg_num)
01358 {
01359 PREG_INFO *preg_info = Get_Preg_Info(preg_num);
01360
01361 if (preg_info == NULL)
01362 {
01363 Accumulate_Preg_Info(preg_ty, preg_num);
01364 preg_info = Get_Preg_Info(preg_num);
01365 }
01366
01367 PREG_INFO_decl(preg_info, Mtype_to_Ukind(TY_mtype(preg_ty))) = TRUE;
01368 }
01369
01370
01371 CALLSITE *
01372 PUinfo_Get_CallSites(void)
01373 {
01374 return CallSite_First;
01375 }
01376
01377
01378 RETURNSITE *
01379 PUinfo_Get_ReturnSites(void)
01380 {
01381 return ReturnSite_First;
01382 }
01383
01384
01385 RETURN_PREG
01386 PUinfo_Get_ReturnPreg(TY_IDX return_ty)
01387 {
01388
01389
01390
01391 RETURN_PREG return_preg;
01392 RETURN_PREG * const return_preg_ptr = &return_preg;
01393 PREG_NUM preg_num1, preg_num2;
01394
01395 if (WHIRL_Return_Info_On) {
01396
01397 RETURN_INFO return_info = Get_Return_Info (return_ty,
01398 Use_Simulated);
01399
01400 if (TY_mtype(return_ty) == MTYPE_M) {
01401
01402 RETURN_PREG_mtype(return_preg_ptr, 0) = MTYPE_M;
01403 RETURN_PREG_mtype(return_preg_ptr, 1) = MTYPE_V;
01404 preg_num1 = -1;
01405 }
01406 else if (RETURN_INFO_count(return_info) <= 2) {
01407
01408 RETURN_PREG_mtype(return_preg_ptr, 0) = RETURN_INFO_mtype (return_info, 0);
01409 RETURN_PREG_mtype(return_preg_ptr, 1) = RETURN_INFO_mtype (return_info, 1);
01410 preg_num1 = RETURN_INFO_preg (return_info, 0);
01411 preg_num2 = RETURN_INFO_preg (return_info, 1);
01412 }
01413
01414 else
01415 Fail_FmtAssertion ("PUinfo_Get_ReturnPreg: more than 2 return registers");
01416 }
01417
01418 else {
01419
01420 Get_Return_Mtypes(return_ty,
01421 Use_Simulated,
01422 &RETURN_PREG_mtype(return_preg_ptr, 0),
01423 &RETURN_PREG_mtype(return_preg_ptr, 1));
01424
01425
01426 Get_Return_Pregs(RETURN_PREG_mtype(return_preg_ptr, 0),
01427 RETURN_PREG_mtype(return_preg_ptr, 1),
01428 &preg_num1,
01429 &preg_num2);
01430 }
01431 RETURN_PREG_offset(return_preg_ptr, 0) = preg_num1;
01432 RETURN_PREG_offset(return_preg_ptr, 1) = preg_num2;
01433
01434 if (RETURN_PREG_mtype(return_preg_ptr, 0) == MTYPE_V)
01435 RETURN_PREG_num_pregs(return_preg_ptr) = 0;
01436 else if (RETURN_PREG_mtype(return_preg_ptr, 1) == MTYPE_V)
01437 RETURN_PREG_num_pregs(return_preg_ptr) = 1;
01438 else
01439 RETURN_PREG_num_pregs(return_preg_ptr) = 2;
01440
01441 return return_preg;
01442 }
01443
01444