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 #include <ext/slist>
00043 #include <algorithm>
00044 #include "defs.h"
00045 #include "errors.h"
00046 #include "tracing.h"
00047 #include "cgir.h"
00048 #include "opcode.h"
00049 #include "wn_util.h"
00050 #include "wn_map.h"
00051 #include "tn_map.h"
00052 #include "whirl2ops.h"
00053 #include "region_util.h"
00054 #include "cg_region.h"
00055 #include "annotations.h"
00056 #include "cg_flags.h"
00057 #include "cg_internal.h"
00058 #include "ir_reader.h"
00059 #include "label_util.h"
00060 #include "region_whirl_templates.h"
00061 #include "strtab.h"
00062 #include "targ_sim.h"
00063 #if defined(TARG_SL) && defined(TARG_SL2)
00064 #include "fb_whirl.h"
00065 #endif
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075 CGRIN *CGRIN_Create( INT num_exits )
00076 {
00077 CGRIN *cgrin;
00078 BB **exits;
00079 LABEL_IDX *exit_labels;
00080 WN *entry_glue, **exit_glue;
00081 INT i;
00082
00083 cgrin = TYPE_MEM_POOL_ALLOC( CGRIN, ®ION_mem_pool );
00084
00085 if (num_exits > 0) {
00086 exits = TYPE_MEM_POOL_ALLOC_N( BB *, ®ION_mem_pool, num_exits );
00087 CGRIN_exits( cgrin ) = exits;
00088 } else
00089 CGRIN_exits( cgrin ) = NULL;
00090
00091 exit_labels = TYPE_MEM_POOL_ALLOC_N( LABEL_IDX, ®ION_mem_pool, num_exits );
00092 CGRIN_exit_labels( cgrin ) = exit_labels;
00093
00094 entry_glue = WN_CreateBlock();
00095 CGRIN_entry_glue( cgrin ) = entry_glue;
00096 exit_glue = TYPE_MEM_POOL_ALLOC_N( WN *, ®ION_mem_pool, num_exits );
00097 CGRIN_exit_glue( cgrin ) = exit_glue;
00098
00099 for ( i = 0; i < num_exits; i++ )
00100 CGRIN_exit_glue_i( cgrin, i ) = WN_CreateBlock();
00101
00102 CGRIN_nested_exit(cgrin) = WN_CreateBlock();
00103
00104 return cgrin;
00105 }
00106
00107
00108 TN_LIST *
00109 REGION_Get_TN_In_List (RID *rid)
00110 {
00111 BB *bb = CGRIN_entry( RID_cginfo( rid ));
00112 OP *op;
00113 TN_LIST *tnl = NULL;
00114 TN *tn;
00115 if (CG_localize_tns) DevWarn("REGION_Get_TN_In_List NYI when localized");
00116 FOR_ALL_BB_OPs (bb, op) {
00117 if (OP_code(op) != TOP_begin_pregtn) continue;
00118 tn = OP_opnd(op,0);
00119
00120
00121 tnl = TN_LIST_Push( tn, tnl, ®ION_mem_pool);
00122 }
00123 return tnl;
00124 }
00125
00126
00127 TN_LIST *
00128 REGION_Get_TN_Out_List (RID *rid, INT exit_num)
00129 {
00130 BB *bb = CGRIN_exit_i( RID_cginfo( rid ), exit_num);
00131 OP *op;
00132 TN_LIST *tnl = NULL;
00133 TN *tn;
00134 if (CG_localize_tns) DevWarn("REGION_Get_TN_Out_List NYI when localized");
00135 FOR_ALL_BB_OPs (bb, op) {
00136 if (OP_code(op) != TOP_end_pregtn) continue;
00137 tn = OP_opnd(op,0);
00138
00139
00140 tnl = TN_LIST_Push( tn, tnl, ®ION_mem_pool);
00141 }
00142 return tnl;
00143 }
00144
00145
00146
00147
00148
00149
00150
00151
00152 #ifdef Is_True_On
00153 static
00154 void verify_pregs_list(RID *rid, PREG_LIST *prl)
00155 {
00156 PREG_NUM pr;
00157
00158
00159
00160 for ( ; prl; prl = PREG_LIST_rest(prl)) {
00161 pr = PREG_LIST_first(prl);
00162 if (pr <= Last_Dedicated_Preg_Offset)
00163 continue;
00164 if (REGION_search_preg_set(RID_pregs_quad(rid), pr)) {
00165 Is_True(pr + 1 == PREG_LIST_first(PREG_LIST_rest(prl)),
00166 ("verify_pregs_list(RGN %d), pregs_in list out "
00167 "of order", RID_id(rid)));
00168 } else if (REGION_search_preg_set(RID_pregs_complex_quad(rid), pr)) {
00169 PREG_LIST *tmp = PREG_LIST_rest(prl);
00170 Is_True(pr + 1 == PREG_LIST_first(tmp),
00171 ("verify_pregs_list(RGN %d), pregs_in list out "
00172 "of order", RID_id(rid)));
00173 tmp = PREG_LIST_rest(tmp);
00174 Is_True(pr + 2 == PREG_LIST_first(tmp),
00175 ("verify_pregs_list(RGN %d), pregs_in list out "
00176 "of order", RID_id(rid)));
00177 tmp = PREG_LIST_rest(tmp);
00178 Is_True(pr + 3 == PREG_LIST_first(tmp),
00179 ("verify_pregs_list(RGN %d), pregs_in list out "
00180 "of order", RID_id(rid)));
00181 }
00182 }
00183 }
00184 #endif
00185
00186
00187
00188
00189
00190
00191
00192
00193 #ifdef Is_True_On
00194 #define verify_macro(preg_n) \
00195 tmp = OP_next(op); \
00196 while (tmp != NULL && OP_code(tmp) != opc) \
00197 tmp = OP_next(tmp); \
00198 Is_True(tmp != NULL && OP_code(tmp) == opc, \
00199 ("verify_pregtn_order, preg_tns are mixed")); \
00200 Is_True((preg_n) == TN_value(OP_opnd(tmp, 1)), \
00201 ("verify_pregtn_order(BB %d), preg_tns out of order", \
00202 BB_id(bb)));
00203
00204 static
00205 void verify_pregtn_order(BB *bb, RID *rid, TOP opc)
00206 {
00207 OP *op = BB_first_op(bb), *tmp;
00208 while (op != NULL) {
00209 if (OP_code(op) == opc) {
00210 PREG_NUM pr = TN_value(OP_opnd(op, 1));
00211 if (REGION_search_preg_set(RID_pregs_quad(rid), pr)) {
00212 verify_macro(pr+1);
00213 } else if (REGION_search_preg_set(RID_pregs_complex_quad(rid), pr)) {
00214 verify_macro(pr+1);
00215 verify_macro(pr+2);
00216 verify_macro(pr+3);
00217 }
00218 }
00219 op = OP_next(op);
00220 }
00221 }
00222 #endif
00223
00224
00225
00226
00227
00228
00229
00230
00231 static inline
00232 void Update_preg_to_tn_array(OP *op, TOP opc)
00233 {
00234 Is_True(!CG_localize_tns,
00235 ("Update_preg_to_tn_array, don't call this routine at -O0"));
00236
00237 while (op != NULL) {
00238 if (OP_code(op) == opc) {
00239 TN *tn = OP_opnd(op, 0);
00240 PREG_NUM pr = TN_value(OP_opnd(op, 1));
00241 PREG_NUM ppr = TN_To_Assigned_PREG(tn);
00242 PREG_To_TN_Array[pr] = tn;
00243 PREG_To_TN_Array[ppr] = tn;
00244 Is_Trace(Get_Trace(TP_REGION, TT_REGION_CG_DEBUG) ||
00245 Get_Trace(TP_REGION, TT_REGION_BOUND_DEBUG),
00246 (TFile,"Update_preg_to_tn_array, updating PREG %d <-> TN %d\n",
00247 ppr, TN_number(tn)));
00248 Is_Trace(Get_Trace(TP_REGION, TT_REGION_CG_DEBUG) ||
00249 Get_Trace(TP_REGION, TT_REGION_BOUND_DEBUG),
00250 (TFile,"Update_preg_to_tn_array, updating PREG %d <-> TN %d\n",
00251 pr, TN_number(tn)));
00252 Is_Trace_cmd(Get_Trace(TP_REGION, TT_REGION_CG_DEBUG) ||
00253 Get_Trace(TP_REGION, TT_REGION_BOUND_DEBUG),
00254 Print_OP(op));
00255 }
00256 op = OP_next(op);
00257 }
00258 }
00259
00260
00261
00262
00263
00264 static ST *gen_quad;
00265 static ST *gen_complex_quad;
00266
00267
00268
00269 extern "C" void Init_gen_quad_preg(void)
00270 {
00271 gen_quad = NULL;
00272 gen_complex_quad = NULL;
00273 }
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293 static
00294 void Gen_quad_preg(PREG_NUM pr, TN_LIST **tnl, WN *block,
00295 WN **after, TYPE_ID mtype, BOOL in_glue, RID *rid,
00296 INT exit_num, ALIAS_MANAGER *am)
00297 {
00298 Is_True(mtype == MTYPE_FQ || mtype == MTYPE_CQ,
00299 ("Gen_quad_preg, unknown mtype"));
00300 if (CG_localize_tns)
00301 Is_True(rid != NULL && am != NULL, ("Gen_quad_preg, RID or AM is NULL"));
00302 else
00303 Is_True(rid != NULL, ("Gen_quad_preg, RID is NULL"));
00304 #ifdef Is_True_On
00305 BOOL trace = Get_Trace(TP_REGION, TT_REGION_CG_DEBUG) ||
00306 Get_Trace(TP_REGION, TT_REGION_BOUND_DEBUG);
00307 #endif
00308 ST *newst;
00309 TYPE_ID type = PREG_To_TN_Mtype[pr];
00310 Is_True(type == MTYPE_F8, ("Gen_quad_preg, type error, expecting F8, %s",
00311 MTYPE_name(type)));
00312
00313
00314 if ((gen_quad == NULL && mtype == MTYPE_FQ) ||
00315 (gen_complex_quad == NULL && mtype == MTYPE_CQ)) {
00316
00317 newst = New_ST();
00318 ST_Init(newst,
00319 (mtype == MTYPE_FQ) ? Save_Str("region_bound_quad")
00320 : Save_Str("region_bound_complex_quad"),
00321 CLASS_VAR, SCLASS_AUTO, EXPORT_LOCAL, MTYPE_To_TY(mtype));
00322 Set_ST_is_temp_var(newst);
00323 if (mtype == MTYPE_FQ)
00324 gen_quad = newst;
00325 else
00326 gen_complex_quad = newst;
00327 Is_Trace(trace, (TFile,"Gen_quad_preg, generated temp for quad\n"));
00328 } else {
00329
00330 newst = (mtype == MTYPE_FQ) ? gen_quad : gen_complex_quad;
00331 }
00332
00333 WN *load, *store;
00334
00335 INT N = (mtype == MTYPE_FQ) ? 2 : 4;
00336 if (in_glue) {
00337
00338 load = WN_LdidPreg(mtype, pr);
00339 store = WN_Stid(mtype, (WN_OFFSET)0, newst, ST_type(newst), load);
00340 WN_INSERT_BlockLast(block, store);
00341
00342 for (INT i=0; i<N; i++) {
00343 TN *tn2 = PREG_To_TN_Array[pr+i];
00344 Is_True(tn2 != NULL, ("Gen_quad_preg, tn2 is NULL, PREG %d", pr+i));
00345 load = WN_Ldid(type, (WN_OFFSET)(i*8), newst, ST_type(newst));
00346 if (CG_localize_tns) {
00347 ST *spill_loc2 = TN_spill(tn2);
00348 Is_True(strncmp(ST_name(spill_loc2),"lcl_spill_temp",14) == 0,
00349 ("Gen_quad_preg, not a spill loc"));
00350 store = WN_Stid(TY_mtype(ST_type(spill_loc2)), 0, spill_loc2,
00351 ST_type(spill_loc2), load);
00352 REGION_add_wn_points_to(&RID_used_in(rid), store, am);
00353 Is_Trace(trace, (TFile, "Gen_quad_preg(in glue), TN %d <-> PREG %d\n",
00354 TN_number(tn2), pr+i));
00355 } else {
00356 ST *spill_loc2 = TN_spill(tn2);
00357 if (TN_is_rematerializable(tn2)) {
00358 DevWarn("region bounds has rematerializable tn; can ignore?");
00359 spill_loc2 = NULL;
00360 }
00361 if (TN_is_gra_homeable(tn2)) {
00362 DevWarn("region bounds has home-able tn; should store to home, but just use reg for now");
00363 spill_loc2 = NULL;
00364 }
00365 if (spill_loc2) {
00366 Is_True(strncmp(ST_name(spill_loc2),"gra_spill_temp",14) == 0,
00367 ("Gen_quad_preg, not a spill loc"));
00368 store = WN_Stid(TY_mtype(ST_type(spill_loc2)), 0, spill_loc2,
00369 ST_type(spill_loc2), load);
00370 REGION_add_wn_points_to(&RID_used_in(rid), store, am);
00371 Is_Trace(trace, (TFile, "Gen_quad_preg(in glue), "
00372 "TN %d <-> PREG %d\n",
00373 TN_number(tn2), pr+i));
00374 }
00375 else {
00376 PREG_NUM ppr2 = TN_To_Assigned_PREG(tn2);
00377 store = WN_StidIntoPreg(type, ppr2, MTYPE_To_PREG(type), load);
00378 REGION_add_preg_in(rid, ppr2, MTYPE_V);
00379 Is_Trace(trace, (TFile, "Gen_quad_preg(in glue), "
00380 "TN %d (assigned to PREG %d) <-> PREG %d\n",
00381 TN_number(tn2), ppr2, pr+i));
00382 }
00383 }
00384 *tnl = TN_LIST_Push(tn2, *tnl, ®ION_mem_pool);
00385 WN_INSERT_BlockLast(block, store);
00386 }
00387
00388 } else {
00389
00390 for (INT i=0; i<N; i++) {
00391 TN *tn2 = PREG_To_TN_Array[pr+i];
00392 Is_True(tn2 != NULL, ("Gen_quad_preg, tn2 is NULL PREG %d", pr+i));
00393 if (CG_localize_tns) {
00394 ST *spill_loc2 = TN_spill(tn2);
00395 Is_True(strncmp(ST_name(spill_loc2),"lcl_spill_temp",14) == 0,
00396 ("Gen_quad_preg, not a spill loc"));
00397 load = WN_Ldid(TY_mtype(ST_type(spill_loc2)), 0, spill_loc2,
00398 ST_type(spill_loc2));
00399 store = WN_Stid(type, (WN_OFFSET)(i*8), newst, ST_type(newst), load);
00400 REGION_add_wn_points_to(&RID_def_in_live_out(rid), store, am);
00401 Is_Trace(trace, (TFile, "Gen_quad_preg(out glue), TN %d <-> PREG %d\n",
00402 TN_number(tn2), pr+i));
00403 } else {
00404 ST *spill_loc2 = TN_spill(tn2);
00405 if (TN_is_rematerializable(tn2)) {
00406 DevWarn("region bounds has rematerializable tn; can ignore?");
00407 spill_loc2 = NULL;
00408 }
00409 if (TN_is_gra_homeable(tn2)) {
00410 DevWarn("region bounds has home-able tn; should store to home, but just use reg for now");
00411 spill_loc2 = NULL;
00412 }
00413 if (spill_loc2) {
00414 Is_True(strncmp(ST_name(spill_loc2),"gra_spill_temp",14) == 0,
00415 ("Gen_quad_preg, not a spill loc"));
00416 load = WN_Ldid(TY_mtype(ST_type(spill_loc2)), 0, spill_loc2,
00417 ST_type(spill_loc2));
00418 REGION_add_wn_points_to(&RID_def_in_live_out(rid), store, am);
00419 Is_Trace(trace, (TFile, "Gen_quad_preg(out glue), "
00420 "TN %d <-> PREG %d\n",
00421 TN_number(tn2), pr+i));
00422 }
00423 else {
00424 PREG_NUM ppr2 = TN_To_Assigned_PREG(tn2);
00425 load = WN_LdidPreg(type, ppr2);
00426 REGION_add_preg_out(rid, exit_num, ppr2, MTYPE_V);
00427 Is_Trace(trace, (TFile, "Gen_quad_preg(out glue), "
00428 "TN %d (assigned to PREG %d) <-> PREG %d\n",
00429 TN_number(tn2), ppr2, pr+i));
00430 }
00431 store = WN_Stid(type, (WN_OFFSET)(i*8), newst, ST_type(newst), load);
00432 }
00433 *tnl = TN_LIST_Push(tn2, *tnl, ®ION_mem_pool);
00434 WN_INSERT_BlockAfter(block, *after, store);
00435 *after = store;
00436 }
00437
00438
00439 load = WN_Ldid(mtype, (WN_OFFSET)0, newst, ST_type(newst));
00440 store = WN_StidIntoPreg(mtype, pr, MTYPE_To_PREG(mtype), load);
00441 WN_INSERT_BlockAfter(block, *after, store);
00442 *after = store;
00443 }
00444 }
00445
00446
00447
00448
00449 void
00450 REGION_Entry_PREG_Whirl( RID *rid, WN *entry_whirl, TN_LIST *inlist,
00451 struct ALIAS_MANAGER *am)
00452 {
00453 TN_LIST *tnl;
00454 #ifdef Is_True_On
00455 BOOL trace = Get_Trace(TP_REGION, TT_REGION_CG_DEBUG) ||
00456 Get_Trace(TP_REGION, TT_REGION_BOUND_DEBUG);
00457 #endif
00458
00459 if (RID_pregs_in(rid) != NULL) {
00460 CGRIN *cgrin = RID_cginfo( rid );
00461 Is_True(cgrin != NULL, ("REGION_Entry_PREG_Whirl, NULL cgrin"));
00462 tnl = NULL;
00463
00464
00465
00466
00467 if (CG_localize_tns) {
00468 PREG_LIST *prl;
00469
00470 slist<PREG_NUM> skip_list;
00471 #ifdef Is_True_On
00472 verify_pregs_list(rid, RID_pregs_in(rid));
00473 #endif
00474 for (prl = RID_pregs_in(rid); prl; prl = PREG_LIST_rest(prl)) {
00475 PREG_NUM pr = PREG_LIST_first( prl );
00476 if (pr <= Last_Dedicated_Preg_Offset)
00477 continue;
00478
00479
00480
00481 if (skip_list.size()) {
00482 slist<PREG_NUM>::iterator skip_search =
00483 find(skip_list.begin(), skip_list.end(), pr);
00484 if (skip_search != skip_list.end()) {
00485 Is_Trace(trace, (TFile, "REGION_Entry_PREG_Whirl(CG_localize_tns)"
00486 ", skipping PREG %d\n\tbecause of (complex) quad\n",
00487 pr));
00488 continue;
00489 }
00490 }
00491
00492 TN *tn = PREG_To_TN_Array[pr];
00493 Is_True(tn != NULL,
00494 ("REGION_Entry_PREG_Whirl(CG_localize_tns), NULL tn"));
00495 ST *spill_loc = TN_spill(tn);
00496
00497 if (spill_loc == NULL && TN_register(tn) != REGISTER_UNDEFINED) {
00498
00499 }
00500 else if (spill_loc == NULL || TN_is_rematerializable(tn)) {
00501
00502
00503 DevWarn("REGION_Entry_PREG_Whirl: no spill location "
00504 "for tn in entry list?");
00505 continue;
00506 }
00507
00508
00509
00510 if (REGION_search_preg_set(RID_pregs_quad(rid), pr)) {
00511 Gen_quad_preg(pr, &tnl, entry_whirl, NULL, MTYPE_FQ,
00512 TRUE, rid, 0, am);
00513 skip_list.push_front(pr + 1);
00514 } else if (REGION_search_preg_set(RID_pregs_complex_quad(rid), pr)) {
00515 Gen_quad_preg(pr, &tnl, entry_whirl, NULL, MTYPE_CQ,
00516 TRUE, rid, 0, am);
00517 skip_list.push_front(pr + 1);
00518 skip_list.push_front(pr + 2);
00519 skip_list.push_front(pr + 3);
00520 } else {
00521
00522 TYPE_ID type = PREG_To_TN_Mtype[pr];
00523
00524 WN *ld = WN_LdidPreg(type, pr);
00525 WN *st;
00526 if (spill_loc) {
00527 st = WN_Stid(TY_mtype(ST_type(spill_loc)),
00528 0, spill_loc, ST_type(spill_loc), ld);
00529
00530
00531 Is_True(strncmp(ST_name(spill_loc),"lcl_spill_temp",14) == 0,
00532 ("REGION_Entry_PREG_Whirl, not a spill loc"));
00533 REGION_add_wn_points_to(&RID_used_in(rid), st, am);
00534 Is_Trace(trace,(TFile,"REGION_Entry_PREG_Whirl(CG_localize_tns), "
00535 "TN %d <-> PREG %d, %s\n",
00536 TN_number(tn), pr, ST_name(spill_loc)));
00537 }
00538 else {
00539 PREG_NUM ppr = TN_To_Assigned_PREG(tn);
00540 st = WN_StidIntoPreg(type, ppr, MTYPE_To_PREG(type), ld);
00541 REGION_add_preg_in(rid, ppr, MTYPE_V);
00542 Is_Trace(trace,(TFile,"REGION_Entry_PREG_Whirl, "
00543 "TN %d (assigned to PREG %d) <--> PREG %d\n",
00544 TN_number(tn), ppr, pr));
00545 }
00546
00547
00548 tnl = TN_LIST_Push(tn, tnl, ®ION_mem_pool);
00549 WN_INSERT_BlockLast(entry_whirl, st);
00550 }
00551 }
00552 }
00553 else {
00554 BB *bb = CGRIN_entry(cgrin);
00555 OP *op = BB_first_op(bb);
00556 OP *next;
00557 #ifdef Is_True_On
00558
00559 #endif
00560
00561 Update_preg_to_tn_array(op, TOP_begin_pregtn);
00562
00563 slist<PREG_NUM> skip_list;
00564
00565
00566 while (op != NULL) {
00567 if (OP_code(op) == TOP_begin_pregtn) {
00568 PREG_NUM pr = TN_value(OP_opnd(op, 1));
00569
00570
00571
00572 if (skip_list.size()) {
00573 slist<PREG_NUM>::iterator skip_search =
00574 find(skip_list.begin(), skip_list.end(), pr);
00575 if (skip_search != skip_list.end()) {
00576 Is_Trace(trace, (TFile, "REGION_Entry_PREG_Whirl, skipping "
00577 "PREG %d\n\tbecause of (complex) quad\n", pr));
00578 next = OP_next(op);
00579 op = next;
00580 continue;
00581 }
00582 }
00583
00584
00585
00586 if (REGION_search_preg_set(RID_pregs_quad(rid), pr)) {
00587 Gen_quad_preg(pr, &tnl, entry_whirl, NULL, MTYPE_FQ,
00588 TRUE, rid, 0, am);
00589 skip_list.push_front(pr + 1);
00590 } else if (REGION_search_preg_set(RID_pregs_complex_quad(rid), pr)) {
00591 Gen_quad_preg(pr, &tnl, entry_whirl, NULL, MTYPE_CQ,
00592 TRUE, rid, 0, am);
00593 skip_list.push_front(pr + 1);
00594 skip_list.push_front(pr + 2);
00595 skip_list.push_front(pr + 3);
00596 } else {
00597 TN *tn = OP_opnd(op, 0);
00598 Is_True(tn != NULL, ("REGION_Entry_PREG_Whirl, NULL tn"));
00599
00600 TYPE_ID type = PREG_To_TN_Mtype[pr];
00601 WN *ld = WN_LdidPreg(type, pr);
00602 WN *st;
00603 ST *spill_loc = TN_spill(tn);
00604 if (TN_is_rematerializable(tn)) {
00605 DevWarn("region bounds has rematerializable tn; can ignore?");
00606 spill_loc = NULL;
00607 }
00608 if (TN_is_gra_homeable(tn)) {
00609 DevWarn("region bounds has home-able tn; should store to home, but just use reg for now");
00610 spill_loc = NULL;
00611 }
00612 if (spill_loc) {
00613 Is_True(strncmp(ST_name(spill_loc),"gra_spill_temp",14) == 0,
00614 ("REGION_Entry_PREG_Whirl, not a gra spill loc"));
00615 st = WN_Stid(TY_mtype(ST_type(spill_loc)),
00616 0, spill_loc, ST_type(spill_loc), ld);
00617 REGION_add_wn_points_to(&RID_used_in(rid), st, am);
00618 Is_Trace(trace,(TFile,"REGION_Entry_PREG_Whirl, "
00619 "TN %d <-> PREG %d, %s\n",
00620 TN_number(tn), pr, ST_name(spill_loc)));
00621 }
00622 else {
00623 PREG_NUM ppr = TN_To_Assigned_PREG(tn);
00624 st = WN_StidIntoPreg(type, ppr, MTYPE_To_PREG(type), ld);
00625 REGION_add_preg_in(rid, ppr, MTYPE_V);
00626 Is_Trace(trace,(TFile,"REGION_Entry_PREG_Whirl, "
00627 "TN %d (assigned to PREG %d) <--> PREG %d\n",
00628 TN_number(tn), ppr, pr));
00629 }
00630
00631
00632 tnl = TN_LIST_Push(tn, tnl, ®ION_mem_pool);
00633 WN_INSERT_BlockLast( entry_whirl, st );
00634 }
00635
00636 next = OP_next(op);
00637 op = next;
00638 } else
00639 op = OP_next(op);
00640 }
00641 }
00642
00643 CGRIN_tns_in(cgrin) = tnl;
00644 Is_Trace(trace, (TFile,"REGION_Entry_PREG_Whirl, tnl =\n"));
00645 Is_Trace_cmd(trace, Print_TN_List(TFile, tnl));
00646 Is_Trace(trace, (TFile,"REGION_Entry_PREG_Whirl, RGN %d bounds =\n",
00647 RID_id(rid)));
00648 Is_Trace_cmd(trace, RID_set_print(TFile, rid));
00649 }
00650 }
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660 LABEL_IDX
00661 REGION_Exit_Whirl_Labels( WN *exit_whirl, BB *exit_bb, LABEL_IDX external_label,
00662 RID *rid )
00663 {
00664 WN *label_wn, *goto_wn, *last, *parent_exit;
00665 LABEL_IDX new_label;
00666 TN *new_target, *opndi;
00667 OP *br_op;
00668 INT i;
00669
00670 Is_True(rid != NULL, ("REGION_Exit_Whirl_Labels, NULL rid"));
00671 Is_True(external_label != (LABEL_IDX) 0,
00672 ("null external label in REGION_Exit_Whirl_Labels"));
00673 Is_True(WN_opcode(exit_whirl) == OPC_BLOCK,
00674 ("unexpected opcode for exit_whirl"));
00675
00676 last = WN_last( exit_whirl );
00677 if ( last != NULL && WN_opcode( last ) == OPC_RETURN ) {
00678
00679
00680 label_wn = WN_CreateLabel( external_label, 0, NULL );
00681 WN_INSERT_BlockFirst( exit_whirl, label_wn );
00682 return LABEL_IDX_ZERO;
00683 }
00684
00685
00686 new_label = Gen_Temp_Label();
00687 label_wn = WN_CreateLabel( new_label, 0, NULL );
00688
00689 #if defined(TARG_SL) && defined(TARG_SL2)
00690 if(Cur_PU_Feedback) {
00691 FB_FREQ out_rgn=Cur_PU_Feedback->Query(rid->rwn, FB_EDGE_CALL_OUTGOING);
00692 FB_Info_Invoke fb_inv(out_rgn);
00693 Cur_PU_Feedback->Annot_invoke(label_wn, fb_inv);
00694 }
00695 #endif
00696
00697 WN_INSERT_BlockFirst( exit_whirl, label_wn );
00698
00699
00700
00701
00702
00703 parent_exit = NULL;
00704 Is_True(RID_parent(rid) != NULL,
00705 ("REGION_Exit_Whirl_Labels, NULL parent rid"));
00706
00707 if (!RID_TYPE_func_entry(RID_parent(rid))) {
00708 Is_True(RID_rwn(RID_parent(rid)) != NULL,
00709 ("REGION_Exit_Whirl_Labels, NULL rwn"));
00710 Is_True(WN_region_exits(RID_rwn(RID_parent(rid))) != NULL,
00711 ("REGION_Exit_Whirl_Labels, NULL exit block"));
00712 parent_exit = WN_region_exits(RID_rwn(RID_parent(rid)));
00713 parent_exit = REGION_search_block(parent_exit,
00714 comp_same_label_no(external_label));
00715 }
00716 if (parent_exit != NULL)
00717 goto_wn = WN_CreateRegionExit(external_label);
00718 else
00719 goto_wn = WN_CreateGoto(external_label);
00720
00721 #if defined(TARG_SL) && defined(TARG_SL2)
00722 if(Cur_PU_Feedback) {
00723 FB_FREQ out_rgn=Cur_PU_Feedback->Query(rid->rwn, FB_EDGE_CALL_OUTGOING);
00724 FB_Info_Invoke fb_inv(out_rgn);
00725 Cur_PU_Feedback->Annot_invoke(goto_wn, fb_inv);
00726 }
00727 #endif
00728
00729 WN_INSERT_BlockLast(exit_whirl, goto_wn);
00730
00731 new_target = Gen_Label_TN( new_label, 0 );
00732 br_op = BB_branch_op( exit_bb );
00733 Is_True( br_op != NULL, ("REGION_Exit_Whirl_Labels, no branch op "
00734 "in block exiting to an external label") );
00735 for ( i = 0; i < OP_opnds(br_op); i++ ) {
00736 opndi = OP_opnd( br_op, i );
00737 if ( ! TN_is_label( opndi ) )
00738 continue;
00739 if ( TN_label( opndi ) != external_label )
00740 continue;
00741 Set_OP_opnd( br_op, i, new_target );
00742 }
00743
00744 return new_label;
00745 }
00746
00747
00748
00749
00750
00751
00752
00753
00754
00755 void
00756 REGION_Exit_PREG_Whirl( RID *rid, INT exit_num, WN *exit_whirl,
00757 TN_LIST *outlist, struct ALIAS_MANAGER *am)
00758 {
00759 WN *after;
00760 TN_LIST *tnl;
00761 #ifdef Is_True_On
00762 BOOL trace = Get_Trace(TP_REGION, TT_REGION_CG_DEBUG) ||
00763 Get_Trace(TP_REGION, TT_REGION_BOUND_DEBUG);
00764 #endif
00765
00766 FmtAssert( WN_opcode( exit_whirl ) == OPC_BLOCK,
00767 ("REGION_Exit_PREG_Whirl, unexpected opcode for exit_whirl") );
00768 Is_True(rid != NULL && exit_num < RID_num_exits(rid),
00769 ("REGION_Exit_PREG_Whirl, inconsistency in num_exits"));
00770
00771
00772
00773 {
00774 WN *last_label, *next;
00775 WN *first = WN_first( exit_whirl );
00776 if ( first == (WN *)NULL || WN_opcode(first) != OPC_LABEL ) {
00777 last_label = NULL;
00778 } else {
00779 last_label = first;
00780 while ( (next = WN_next(last_label)) && WN_opcode(next) == OPC_LABEL ) {
00781 last_label = next;
00782 }
00783 }
00784 after = last_label;
00785 }
00786
00787 if (RID_pregs_out(rid) != NULL && RID_pregs_out_i(rid,exit_num) != NULL) {
00788 CGRIN *cgrin = RID_cginfo( rid );
00789 tnl = NULL;
00790 if (CG_localize_tns) {
00791 PREG_LIST *prl;
00792
00793 slist<PREG_NUM> skip_list;
00794 #ifdef Is_True_On
00795 verify_pregs_list(rid, RID_pregs_out_i(rid, exit_num));
00796 #endif
00797 for (prl=RID_pregs_out_i(rid, exit_num); prl; prl=PREG_LIST_rest(prl)) {
00798 PREG_NUM pr = PREG_LIST_first( prl );
00799 if (pr <= Last_Dedicated_Preg_Offset)
00800 continue;
00801
00802
00803
00804 if (skip_list.size()) {
00805 slist<PREG_NUM>::iterator skip_search =
00806 find(skip_list.begin(), skip_list.end(), pr);
00807 if (skip_search != skip_list.end()) {
00808 Is_Trace(trace, (TFile, "REGION_Exit_PREG_Whirl(CG_localize_tns)"
00809 ", skipping PREG %d\n\tbecause of (complex) quad\n",
00810 pr));
00811 continue;
00812 }
00813 }
00814
00815
00816 TYPE_ID type = PREG_To_TN_Mtype[pr];
00817 TN *tn = PREG_To_TN_Array[pr];
00818 Is_True(tn != NULL,
00819 ("REGION_Exit_PREG_Whirl(CG_localize_tns), NULL tn"));
00820 ST *spill_loc = TN_spill( tn );
00821 if (spill_loc == NULL && TN_register(tn) != REGISTER_UNDEFINED) {
00822
00823 }
00824 else if (spill_loc == NULL || TN_is_rematerializable(tn)) {
00825 DevWarn ("REGION_Exit_PREG_Whirl: no spill location "
00826 "for tn in exit list?");
00827 continue;
00828 }
00829
00830
00831
00832 if (REGION_search_preg_set(RID_pregs_quad(rid), pr)) {
00833 Gen_quad_preg(pr, &tnl, exit_whirl, &after, MTYPE_FQ,
00834 FALSE, rid, exit_num, am);
00835 skip_list.push_front(pr + 1);
00836 } else if (REGION_search_preg_set(RID_pregs_complex_quad(rid), pr)) {
00837 Gen_quad_preg(pr, &tnl, exit_whirl, &after, MTYPE_CQ,
00838 FALSE, rid, exit_num, am);
00839 skip_list.push_front(pr + 1);
00840 skip_list.push_front(pr + 2);
00841 skip_list.push_front(pr + 3);
00842 } else {
00843 WN *ld;
00844 if (spill_loc) {
00845
00846 ld = WN_Ldid( TY_mtype(ST_type(spill_loc)),
00847 0, spill_loc, ST_type( spill_loc ) );
00848
00849
00850 Is_True(strncmp(ST_name(spill_loc),"lcl_spill_temp",14) == 0,
00851 ("REGION_Exit_PREG_Whirl, not a spill loc"));
00852 REGION_add_wn_points_to(&RID_def_in_live_out(rid), ld, am);
00853 Is_Trace(trace,(TFile,"REGION_Exit_PREG_Whirl(CG_localize_tns), "
00854 "TN %d <-> PREG %d, %s\n",
00855 TN_number(tn), pr, ST_name(spill_loc)));
00856 }
00857 else {
00858 PREG_NUM ppr = TN_To_Assigned_PREG(tn);
00859 ld = WN_LdidPreg(type, ppr);
00860 REGION_add_preg_out(rid, exit_num, ppr, MTYPE_V);
00861 Is_Trace(trace,(TFile,"REGION_Exit_PREG_Whirl, "
00862 "TN %d (assigned to PREG %d) <-> PREG %d\n",
00863 TN_number(tn), ppr, pr));
00864 }
00865 WN *st = WN_StidIntoPreg( type, pr, MTYPE_To_PREG( type ), ld );
00866
00867
00868 tnl = TN_LIST_Push(tn, tnl, ®ION_mem_pool);
00869 WN_INSERT_BlockAfter(exit_whirl, after, st);
00870 after = st;
00871 }
00872 }
00873 }
00874 else {
00875 BB *bb = CGRIN_exit_i(cgrin,exit_num);
00876 OP *op = BB_first_op(bb);
00877 OP *next;
00878 #ifdef Is_True_On
00879
00880 #endif
00881
00882 Update_preg_to_tn_array(op, TOP_end_pregtn);
00883
00884 slist<PREG_NUM> skip_list;
00885
00886
00887 while (op != NULL) {
00888 if (OP_code(op) == TOP_end_pregtn) {
00889 TN *tn = OP_opnd(op, 0);
00890 Is_True(tn != NULL, ("REGION_Exit_PREG_Whirl, NULL tn"));
00891 PREG_NUM pr = TN_value(OP_opnd(op, 1));
00892
00893
00894
00895 if (skip_list.size()) {
00896 slist<PREG_NUM>::iterator skip_search =
00897 find(skip_list.begin(), skip_list.end(), pr);
00898 if (skip_search != skip_list.end()) {
00899 Is_Trace(trace, (TFile, "REGION_Exit_PREG_Whirl, skipping "
00900 "PREG %d\n\tbecause of (complex) quad\n", pr));
00901 next = OP_next(op);
00902 op = next;
00903 continue;
00904 }
00905 }
00906
00907
00908 TYPE_ID type = PREG_To_TN_Mtype[pr];
00909
00910
00911
00912 if (REGION_search_preg_set(RID_pregs_quad(rid), pr)) {
00913 Gen_quad_preg(pr, &tnl, exit_whirl, &after, MTYPE_FQ,
00914 FALSE, rid, exit_num, am);
00915 skip_list.push_front(pr + 1);
00916 } else if (REGION_search_preg_set(RID_pregs_complex_quad(rid), pr)) {
00917 Gen_quad_preg(pr, &tnl, exit_whirl, &after, MTYPE_CQ,
00918 FALSE, rid, exit_num, am);
00919 skip_list.push_front(pr + 1);
00920 skip_list.push_front(pr + 2);
00921 skip_list.push_front(pr + 3);
00922 } else {
00923 WN *ld;
00924 ST *spill_loc = TN_spill(tn);
00925 if (TN_is_rematerializable(tn)) {
00926 DevWarn("region bounds has rematerializable tn; can ignore?");
00927 spill_loc = NULL;
00928 }
00929 if (TN_is_gra_homeable(tn)) {
00930 DevWarn("region bounds has home-able tn; should store to home, but just use reg for now");
00931 spill_loc = NULL;
00932 }
00933 if (spill_loc) {
00934 Is_True(strncmp(ST_name(spill_loc),"gra_spill_temp",14) == 0,
00935 ("REGION_Exit_PREG_Whirl, not a gra spill loc"));
00936 ld = WN_Ldid( TY_mtype(ST_type(spill_loc)),
00937 0, spill_loc, ST_type( spill_loc ) );
00938 REGION_add_wn_points_to(&RID_def_in_live_out(rid), ld, am);
00939 Is_Trace(trace,(TFile,"REGION_Exit_PREG_Whirl, "
00940 "TN %d <-> PREG %d, %s\n",
00941 TN_number(tn), pr, ST_name(spill_loc)));
00942 }
00943 else {
00944 PREG_NUM ppr = TN_To_Assigned_PREG(tn);
00945 ld = WN_LdidPreg(type, ppr);
00946 REGION_add_preg_out(rid, exit_num, ppr, MTYPE_V);
00947 Is_Trace(trace,(TFile,"REGION_Exit_PREG_Whirl, "
00948 "TN %d (assigned to PREG %d) <-> PREG %d\n",
00949 TN_number(tn), ppr, pr));
00950 }
00951 WN *st = WN_StidIntoPreg(type, pr, MTYPE_To_PREG(type), ld);
00952
00953
00954 tnl = TN_LIST_Push(tn, tnl, ®ION_mem_pool);
00955 WN_INSERT_BlockAfter(exit_whirl, after, st);
00956 after = st;
00957 }
00958
00959 next = OP_next(op);
00960 op = next;
00961 } else
00962 op = OP_next(op);
00963 }
00964 }
00965 CGRIN_tns_out_i(cgrin,exit_num) = tnl;
00966 Is_Trace(trace, (TFile,"REGION_Exit_PREG_Whirl, tnl =\n"));
00967 Is_Trace_cmd(trace, Print_TN_List(TFile, tnl));
00968 Is_Trace(trace, (TFile,"REGION_Exit_PREG_Whirl, RGN %d bounds =\n",
00969 RID_id(rid)));
00970 Is_Trace_cmd(trace, RID_set_print(TFile, rid));
00971 }
00972 }
00973
00974
00975
00976
00977
00978
00979
00980
00981
00982 INT
00983 BB_REGION_Exit( BB *bb, RID *rid )
00984 {
00985 CGRIN *cgrin;
00986 INT n, i;
00987
00988 if ( rid == NULL )
00989 return NO_REGION_EXIT;
00990 cgrin = RID_cginfo( rid );
00991 if ( cgrin == NULL )
00992 return NO_REGION_EXIT;
00993 n = RID_num_exits( rid );
00994 for ( i = 0; i < n; i++ ) {
00995 if ( bb == CGRIN_exit_i( cgrin, i ) ) {
00996 return i;
00997 }
00998 }
00999 return NO_REGION_EXIT;
01000 }
01001
01002
01003
01004
01005
01006
01007
01008
01009
01010 void
01011 TN_LIST_Print( TN_LIST *tnl0 )
01012 {
01013 TN_LIST *tnl;
01014 TN *tn;
01015
01016 for ( tnl = tnl0; tnl; tnl = TN_LIST_rest( tnl ) ) {
01017 tn = TN_LIST_first( tnl );
01018 Print_TN( tn, TRUE );
01019 fprintf( TFile, "\n" );
01020 }
01021 }
01022
01023
01024
01025
01026
01027
01028
01029
01030
01031 CGRIN*
01032 RID_Find_Cginfo( BB *bb)
01033 {
01034 RID *tmp_rgn;
01035 tmp_rgn = BB_rid(bb);
01036 FmtAssert( tmp_rgn != NULL, ("null region found for bb"));
01037 tmp_rgn = RID_is_glue_code(tmp_rgn) ? RID_parent(tmp_rgn) : tmp_rgn;
01038 return RID_cginfo(tmp_rgn);
01039 }
01040
01041
01042
01043
01044
01045
01046 RID*
01047 Non_Transparent_RID (RID *rid)
01048 {
01049 switch (RID_type(rid)) {
01050 case RID_TYPE_func_entry:
01051 case RID_TYPE_pragma:
01052 case RID_TYPE_olimit:
01053 if (RID_is_glue_code(rid))
01054 return Non_Transparent_RID (RID_parent(rid));
01055 return rid;
01056 default:
01057 return Non_Transparent_RID (RID_parent(rid));
01058 }
01059 }
01060