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
00074
00075
00076
00077
00078
00079
00080
00081 #define region_init_CXX "region_init.cxx"
00082 #ifdef _KEEP_RCS_ID
00083 static char *rcs_id = region_init_CXX"$Revision: 1.9 $";
00084 #endif
00085
00086 #include "wn.h"
00087 #include "wn_util.h"
00088 #include "ir_reader.h"
00089 #include "region_util.h"
00090 #include "tracing.h"
00091 #include "erglob.h"
00092 #include "config.h"
00093 #include "cxx_memory.h"
00094 #include "region_whirl_templates.h"
00095
00096
00097
00098 class RINIT;
00099 class LABEL_ALIAS;
00100
00101
00102 class GOTO {
00103 private:
00104 WN *_wn;
00105 WN *_block;
00106 RID *_rid;
00107 BOOL _outside;
00108 BOOL _io_goto;
00109 BOOL _comp_goto;
00110 INT64 _linenum;
00111 GOTO *_next;
00112
00113 public:
00114 GOTO() { }
00115 ~GOTO() { }
00116 BOOL Trace(void) { return Get_Trace(TP_REGION,
00117 TT_REGION_RGN_INIT_DEBUG); }
00118 WN *Wn(void) { return _wn; }
00119 void Set_wn(WN *wn) { _wn = wn; }
00120 void Set_block(WN *block) { _block = block; }
00121 void Set_rid(RID *rid) { _rid = rid; }
00122 void Set_linenum(INT64 line) { _linenum = line; }
00123 void Set_io_goto(BOOL io) { _io_goto = io; }
00124 void Set_comp_goto(BOOL comp) { _comp_goto = comp; }
00125 void Set_label_number(WN *wn) { WN_label_number(_wn) = WN_label_number(wn);
00126 WN_st_idx(_wn) = WN_st_idx(wn); }
00127 OPCODE Opcode(void) { return WN_opcode(_wn); }
00128
00129 void Set_region_exit(RID *rid, RINIT *rinit);
00130 INT32 Label_number(void) { return WN_label_number(_wn); }
00131 WN *Block(void) { return _block; }
00132 RID *Rid(void) { return _rid; }
00133 INT64 Linenum(void) { return _linenum; }
00134 BOOL Outside(void) { return _outside; }
00135 BOOL Is_io_goto(void) { return _io_goto; }
00136 BOOL Is_comp_goto(void) { return _comp_goto; }
00137 void Set_inside(void) { _outside = FALSE; }
00138 void Set_outside(void) { _outside = TRUE; }
00139 GOTO *Next(void) { return _next; }
00140 void Set_next(GOTO *gtmp) { _next = gtmp; }
00141 BOOL Compare_labels(WN *label);
00142 BOOL Compare_labels(LABEL_IDX label);
00143 BOOL Compare_labels(GOTO *label);
00144 void Modify_exits(RID *, RID *, WN *);
00145 void fdump(FILE *fd) { fprintf(fd," %s %s L%d %s RGN %d\n",
00146 _outside ? "" : "<cancelled>",
00147 OPCODE_name(Opcode()),
00148 Is_io_goto()?WN_label_number(_wn):
00149 Label_number(),
00150 Is_io_goto() ? "(IO exit)" : "",
00151 RID_id(Rid()) ); }
00152 };
00153
00154
00155
00156 class RGN_LABEL {
00157 private:
00158 WN *_block;
00159 WN *_label;
00160 WN *_replace;
00161 WN *_split;
00162 RGN_LABEL *_next;
00163 public:
00164 RGN_LABEL() { _split = NULL; }
00165 ~RGN_LABEL() { }
00166 WN *Block(void) { return _block; }
00167 WN *Label(void) { return _label; }
00168 WN *Replace_label(void) { return _replace; }
00169 WN *Split_label(void) { return _split; }
00170 RGN_LABEL *Next(void) { return _next; }
00171 void Set_block(WN *block) { _block = block; }
00172 void Set_label(WN *label) { _label = label; }
00173 void Set_replace_label(WN *replace) { _replace = replace; }
00174 void Set_split_label(WN *split) { _split = split; }
00175 void Set_next(RGN_LABEL *next) { _next = next; }
00176 void Print(const char *str);
00177 };
00178
00179
00180
00181 class LITE_LABEL {
00182 private:
00183 INT32 _label;
00184 ST_IDX _st;
00185 LITE_LABEL *_next;
00186 public:
00187 LITE_LABEL() { _next = NULL; }
00188 ~LITE_LABEL() { }
00189 INT32 Label(void) { return _label; }
00190 ST_IDX St(void) { return _st; }
00191 LITE_LABEL *Next(void) { return _next; }
00192 void Set_label(INT32 label) { _label = label; }
00193 void Set_st(ST_IDX st) { _st = st; }
00194 void Set_next(LITE_LABEL *next) { _next = next; }
00195 };
00196
00197
00198
00199
00200 class LABEL_ALIAS {
00201 private:
00202 INT32 _key_label_no;
00203 LITE_LABEL *_alias_list;
00204 LITE_LABEL *_last;
00205 LABEL_ALIAS *_next;
00206 public:
00207 LABEL_ALIAS() { _key_label_no = -1;
00208 _alias_list = NULL;
00209 _last = NULL;
00210 _next = NULL;
00211 }
00212 ~LABEL_ALIAS() { }
00213 LABEL_ALIAS *Next(void) { return _next; }
00214 INT32 Key(void) { return _key_label_no; }
00215 LITE_LABEL *Alias_list(void) { return _alias_list; }
00216 LITE_LABEL *Last(void) { return _last; }
00217 void Set_next(LABEL_ALIAS *next) { _next = next; }
00218 void Set_key(INT32 key) { _key_label_no = key; }
00219 void Set_alias_list(LITE_LABEL *ll) { _alias_list = ll; }
00220 void Set_last(LITE_LABEL *ll) { _last = ll; }
00221 void Add_label_alias(INT32, ST_IDX, MEM_POOL *);
00222 void Merge_label_alias(LABEL_ALIAS *, MEM_POOL *);
00223 void Print(FILE *fd);
00224 };
00225
00226
00227
00228 class RINIT {
00229
00230 private:
00231 BOOL _trace_flag;
00232 MEM_POOL *_mem_pool;
00233 RID *_rid;
00234 INT32 _nregions;
00235 INT32 _nexits;
00236 RGN_LABEL *_head_list;
00237 RGN_LABEL *_label_list;
00238 GOTO *_goto_list;
00239 LABEL_ALIAS *_label_alias;
00240
00241 void Process_region(WN *, WN *, INT32, RID *, char *);
00242
00243 public:
00244 RINIT(RID *, MEM_POOL *);
00245 ~RINIT() { }
00246 BOOL Trace(void) { return _trace_flag; }
00247 MEM_POOL *Mem_pool(void) { return _mem_pool; }
00248 INT32 Nregions(void) { return _nregions; }
00249 INT32 Nexits(void) { return _nexits; }
00250 RGN_LABEL *Head_list(void) { return _head_list; }
00251 RGN_LABEL *Label_list(void) { return _label_list; }
00252 GOTO *Goto_list(void) { return _goto_list; }
00253 LABEL_ALIAS *Label_alias(void){ return _label_alias; }
00254 RID *Rid(void) { return _rid; }
00255 void Set_head_list(RGN_LABEL *head) { _head_list = head; }
00256 void Set_label_list(RGN_LABEL *label) { _label_list = label; }
00257 void Set_goto_list(GOTO *goto_) { _goto_list = goto_; }
00258 void Set_label_alias(LABEL_ALIAS *la) { _label_alias = la; }
00259 void Add_goto(WN *, WN *, BOOL, BOOL);
00260 void Concat_goto(GOTO *);
00261 RGN_LABEL *Add_label(WN *, WN *);
00262
00263 RGN_LABEL *Add_head_label(WN *, WN *);
00264 void Print_sets(void);
00265 GOTO *Cancel_internal_gotos(BOOL);
00266 void Handle_split_label(WN *, WN *, WN *, RINIT *);
00267 void Region_init(WN *, INT32, RID *, char *);
00268 void Add_label_alias(WN *, WN *);
00269 void Expand_label_alias(RGN_LABEL *);
00270 void Merge_label_alias(LABEL_ALIAS *);
00271 };
00272
00273
00274
00275
00276
00277 void
00278 GOTO::Modify_exits(RID *child_rid, RID *parent_rid, WN *new_wn)
00279 {
00280 Is_True(child_rid != NULL, ("GOTO::Modify_exits, child_rid is NULL"));
00281 Is_True(parent_rid != NULL, ("GOTO::Modify_exits, parent_rid is NULL"));
00282 Is_True(child_rid != parent_rid, ("GOTO::Modify_exits, RIDs are the same"));
00283 Is_True(new_wn != NULL, ("GOTO::Modify_exits, NULL new_wn"));
00284 Is_True(_wn != NULL, ("GOTO::Modify_exits, NULL _wn"));
00285
00286
00287
00288 for (RID *rtmp = child_rid; rtmp != parent_rid; rtmp = RID_parent(rtmp)) {
00289
00290 Is_True(RID_rwn(rtmp) != NULL,
00291 ("GOTO::Modify_exits, RID WN pointer is wrong"));
00292 Is_True(WN_region_exits(RID_rwn(rtmp)) != NULL,
00293 ("GOTO::Modify_exits, exits list is wrong"));
00294 WN *exit_block = WN_region_exits(RID_rwn(rtmp));
00295 Is_True(exit_block != NULL && WN_opcode(exit_block) == OPC_BLOCK,
00296 ("GOTO::Modify_exits, exit_block is wrong"));
00297
00298
00299
00300
00301 WN *wtmp = REGION_search_block(exit_block,
00302 comp_same_label_no(WN_label_number(_wn)));
00303 Is_True(wtmp != NULL, ("GOTO::Modify_exits, exit not found in exit list"));
00304 WN_DELETE_FromBlock(exit_block, wtmp);
00305
00306 if (WN_operator(new_wn) == OPR_LABEL) {
00307
00308
00309 new_wn = WN_CreateRegionExit (WN_label_number(new_wn));
00310 }
00311 Is_Trace(Trace(),(TFile,
00312 " GOTO::Modify_Exits, exit L%d replaced by L%d in RGN %d\n",
00313 WN_label_number(_wn), WN_label_number(new_wn), RID_id(rtmp)));
00314
00315 WN_INSERT_BlockLast(exit_block, WN_CopyNode(new_wn));
00316 }
00317 }
00318
00319
00320 void
00321 GOTO::Set_region_exit(RID *rid, RINIT *rinit)
00322 {
00323 Is_True(rid != NULL, ("GOTO::Set_region_exit, NULL rid"));
00324 Is_True(RID_rwn(rid) != NULL, ("GOTO::Set_region_exit, NULL rwn"));
00325 Is_True(!Is_comp_goto(),
00326 ("GOTO::Set_region_exit, a COMPGOTO must have targets inside the "
00327 "region, RID %d", RID_id(rid)));
00328
00329 switch (WN_opcode(_wn)) {
00330 case OPC_TRUEBR:
00331 case OPC_FALSEBR:
00332 {
00333
00334 LABEL_IDX label_no;
00335 New_LABEL(CURRENT_SYMTAB, label_no);
00336 WN *wn_label = WN_CreateLabel (label_no, 0, NULL);
00337 WN_Set_Linenum(wn_label, WN_Get_Linenum(_wn));
00338
00339 WN *wn_rgn_exit = WN_CreateRegionExit (WN_label_number(_wn));
00340 WN_Set_Linenum(wn_rgn_exit, WN_Get_Linenum(_wn));
00341 Is_Trace(Trace(),(TFile,
00342 "===== Set_region_exit(T/Fbr), converting %s L%d to\n",
00343 OPCODE_name(WN_opcode(_wn)), WN_label_number(_wn)));
00344
00345 if (WN_opcode(_wn) == OPC_TRUEBR)
00346 WN_set_opcode(_wn, OPC_FALSEBR);
00347 else
00348 WN_set_opcode(_wn, OPC_TRUEBR);
00349 WN_label_number(_wn) = label_no;
00350
00351 WN_INSERT_BlockAfter(_block, _wn, wn_rgn_exit);
00352 WN_INSERT_BlockAfter(_block, wn_rgn_exit, wn_label);
00353 Is_Trace(Trace(),(TFile,"\t%s L%d, %s L%d, L%d:\n",
00354 OPCODE_name(WN_opcode(_wn)), label_no,
00355 OPCODE_name(WN_opcode(wn_rgn_exit)), WN_label_number(wn_rgn_exit),
00356 label_no));
00357 _wn = wn_rgn_exit;
00358 }
00359 break;
00360
00361 case OPC_GOTO:
00362 Is_Trace(Trace(),(TFile,
00363 "===== Set_region_exit(goto), converting %s L%d to %s\n",
00364 OPCODE_name(Opcode()), Label_number(),
00365 OPCODE_name(OPC_REGION_EXIT)));
00366 WN_set_opcode(_wn, OPC_REGION_EXIT);
00367 break;
00368
00369 case OPC_U8LDA:
00370 case OPC_U4LDA:
00371 {
00372 Is_True(Is_io_goto(),("GOTO::Set_region_exit, error in IO stmt"));
00373
00374
00375
00376
00377 LABEL_IDX new_label_no;
00378 LABEL_IDX old_label_no = WN_label_number(_wn);
00379 New_LABEL(CURRENT_SYMTAB, new_label_no);
00380 WN *new_label_wn = WN_CreateLabel (new_label_no, 0, NULL);
00381
00382 Is_Trace(Trace(),(TFile,
00383 "===== Set_region_exit, IO exit, converting %s L%d to %s L%d, RGN %d\n",
00384 OPCODE_name(Opcode()), old_label_no,
00385 OPCODE_name(Opcode()), new_label_no,
00386 RID_id(rid)));
00387
00388 WN_Set_Linenum(new_label_wn, WN_Get_Linenum(_wn));
00389 WN_label_number(_wn) = new_label_no;
00390 WN *rgn_exit_wn = WN_CreateRegionExit (old_label_no);
00391 WN_Set_Linenum(rgn_exit_wn, WN_Get_Linenum(_wn));
00392 WN_INSERT_BlockLast(Block(), new_label_wn);
00393 WN_INSERT_BlockLast(Block(), rgn_exit_wn);
00394
00395
00396 _wn = rgn_exit_wn;
00397 }
00398 break;
00399
00400 case OPC_REGION_EXIT:
00401
00402 break;
00403 default:
00404 FmtAssert(0,("GOTO::Set_region_exit, unknown region exit: %s",
00405 OPCODE_name(WN_opcode(_wn))));
00406 break;
00407 }
00408
00409
00410 WN *exit_block = WN_region_exits(RID_rwn(rid));
00411 Is_True(exit_block && WN_opcode(exit_block) == OPC_BLOCK,
00412 ("GOTO::Set_region_exit, exit block is not a block"));
00413
00414
00415 if (REGION_search_block(exit_block,
00416 comp_same_label_no(WN_label_number(_wn)))) {
00417
00418
00419 LABEL_IDX new_label_no;
00420 New_LABEL(CURRENT_SYMTAB, new_label_no);
00421 Is_Trace(Trace(), (TFile," GOTO::Set_region_exit, avoiding duplicate: "
00422 "L%d --> L%d\n",WN_label_number(_wn), new_label_no));
00423 WN *rgn_exit_wn = WN_CreateRegionExit (new_label_no);
00424
00425 rinit->Add_label_alias(_wn, rgn_exit_wn);
00426
00427
00428
00429 if (Rid() != rid)
00430 Modify_exits(Rid(), rid, rgn_exit_wn);
00431
00432
00433 WN_INSERT_BlockAfter(Block(), _wn, rgn_exit_wn);
00434 WN_DELETE_FromBlock(Block(), _wn);
00435
00436
00437 Is_Trace(Trace(),(TFile," GOTO::Set_region_exit, changed L%d to L%d\n",
00438 WN_label_number(_wn),WN_label_number(rgn_exit_wn)));
00439 _wn = rgn_exit_wn;
00440 }
00441
00442
00443 Is_True(!REGION_search_block(exit_block,
00444 comp_same_label_no(WN_label_number(_wn))),
00445 ("GOTO::Set_region_exit, duplicate exit in RGN %d exit list",
00446 RID_id(rid)));
00447
00448
00449 WN_INSERT_BlockLast(exit_block, WN_CopyNode(_wn));
00450 }
00451
00452
00453 BOOL
00454 GOTO::Compare_labels(WN *label)
00455 {
00456 if (Is_io_goto())
00457 return WN_label_number(Wn()) == WN_label_number(label);
00458 else
00459 return Label_number() == WN_label_number(label);
00460 }
00461
00462
00463 BOOL
00464 GOTO::Compare_labels(LABEL_IDX label)
00465 {
00466 if (Is_io_goto())
00467 return WN_label_number(Wn()) == label;
00468 else
00469 return Label_number() == label;
00470 }
00471
00472
00473 BOOL
00474 GOTO::Compare_labels(GOTO *label)
00475 {
00476 INT32 l1 = (Is_io_goto()) ? WN_label_number(Wn()) :
00477 Label_number();
00478 INT32 l2 = (label->Is_io_goto()) ? WN_label_number(label->Wn()) :
00479 label->Label_number();
00480 return l1 == l2;
00481 }
00482
00483
00484
00485
00486 void
00487 LABEL_ALIAS::Add_label_alias(INT32 new_label,
00488 ST_IDX new_st,
00489 MEM_POOL *mem_pool)
00490 {
00491 LITE_LABEL *ltmp;
00492 #ifdef Is_True_On
00493
00494 for (ltmp = Alias_list(); ltmp; ltmp = ltmp->Next()) {
00495 Is_True(ltmp->Label() != new_label,
00496 ("LABEL_ALIAS::Add_label_alias, duplicate in label alias list"));
00497
00498 if (ltmp->Next() == NULL)
00499 Is_True(Last() == ltmp,
00500 ("LABEL_ALIAS::Add_label_alias, Last pointer not set right"));
00501 }
00502 #endif
00503
00504 ltmp = CXX_NEW(LITE_LABEL(), mem_pool);
00505
00506 Is_True(new_label != 0, ("LABEL_ALIAS::Add_label_alias, invalid new_label"));
00507 ltmp->Set_label(new_label);
00508
00509
00510 if (Last())
00511 Last()->Set_next(ltmp);
00512 else
00513 Set_alias_list(ltmp);
00514 Set_last(ltmp);
00515 }
00516
00517
00518
00519 void
00520 LABEL_ALIAS::Merge_label_alias(LABEL_ALIAS *la2, MEM_POOL *mem_pool)
00521 {
00522 Is_True(Alias_list() != NULL && Last() != NULL,
00523 ("LABEL_ALIAS::Merge_label_alias, Alias_list is NULL"));
00524 Is_True(la2->Alias_list() != NULL && la2->Last() != NULL,
00525 ("LABEL_ALIAS::Merge_label_alias, la2->Alias_list is NULL"));
00526
00527 for (LITE_LABEL *ltmp2 = la2->Alias_list(); ltmp2; ltmp2 = ltmp2->Next()) {
00528 BOOL duplicate = FALSE;
00529 for (LITE_LABEL *ltmp1 = Alias_list(); ltmp1; ltmp1 = ltmp1->Next()) {
00530 if (ltmp1->Label() == ltmp2->Label()) {
00531 duplicate = TRUE;
00532 break;
00533 }
00534 }
00535 if (!duplicate)
00536 Add_label_alias(ltmp2->Label(), ltmp2->St(), mem_pool);
00537 }
00538 }
00539
00540 void
00541 LABEL_ALIAS::Print(FILE *fd)
00542 {
00543 for (LABEL_ALIAS *ltmp = this; ltmp; ltmp = ltmp->Next()) {
00544 fprintf(fd," Key: L%d, aliases: ",ltmp->Key());
00545 for (LITE_LABEL *lltmp = ltmp->Alias_list(); lltmp; lltmp = lltmp->Next()){
00546 fprintf(fd,"L%d ",lltmp->Label());
00547 #ifdef Is_True_On
00548
00549 if (lltmp->Next() == NULL)
00550 Is_True(ltmp->Last() == lltmp,
00551 ("LABEL_ALIAS::Print, Last pointer wrong"));
00552 #endif
00553 }
00554 fprintf(fd,"\n");
00555 }
00556 }
00557
00558
00559
00560 RINIT::RINIT(RID *rid, MEM_POOL *mem_pool) :
00561 _rid(rid), _mem_pool(mem_pool)
00562 {
00563 _trace_flag = Get_Trace(TP_REGION, TT_REGION_RGN_INIT_DEBUG);
00564 _nregions = 0;
00565 _nexits = 0;
00566 _head_list = NULL;
00567 _label_list = NULL;
00568 _goto_list = NULL;
00569 _label_alias = NULL;
00570 }
00571
00572 inline void
00573 RINIT::Add_goto(WN *wn, WN *block, BOOL io, BOOL comp)
00574 {
00575 GOTO *gnew = CXX_NEW(GOTO(), Mem_pool());
00576
00577 if (io) {
00578 Is_True(WN_operator(wn) == OPR_LDA,
00579 ("RINIT::Add_goto, IO, unexpected opcode: %s",
00580 OPCODE_name(WN_opcode(wn))));
00581 gnew->Set_io_goto(TRUE);
00582 gnew->Set_comp_goto(FALSE);
00583 } else if (comp) {
00584 Is_True(WN_opcode(wn) == OPC_GOTO,
00585 ("RINIT::Add_goto, COMPGOTO, unexpected opcode: %s",
00586 OPCODE_name(WN_opcode(wn))));
00587 gnew->Set_io_goto(FALSE);
00588 gnew->Set_comp_goto(TRUE);
00589 } else {
00590 Is_True(WN_opcode(wn) == OPC_GOTO || WN_opcode(wn) == OPC_TRUEBR ||
00591 WN_opcode(wn) == OPC_FALSEBR || WN_opcode(wn) == OPC_REGION_EXIT,
00592 ("RINIT::Add_goto, unexpected opcode: %s",
00593 OPCODE_name(WN_opcode(wn))));
00594 gnew->Set_io_goto(FALSE);
00595 gnew->Set_comp_goto(FALSE);
00596 }
00597 Is_True(WN_opcode(block) == OPC_BLOCK,
00598 ("RINIT::Add_goto, unexpected opcode: %s",
00599 OPCODE_name(WN_opcode(block))));
00600
00601 gnew->Set_wn(wn);
00602 gnew->Set_block(block);
00603 gnew->Set_rid(Rid());
00604 gnew->Set_outside();
00605 gnew->Set_linenum(WN_Get_Linenum(wn));
00606 gnew->Set_next(_goto_list);
00607 _goto_list = gnew;
00608 }
00609
00610
00611 inline void
00612 RINIT::Concat_goto(GOTO *gnew)
00613 {
00614 if (gnew != NULL) {
00615
00616 GOTO *gtmp;
00617 for (gtmp=gnew; gtmp->Next() != NULL; gtmp=gtmp->Next())
00618 ;
00619
00620 gtmp->Set_next(_goto_list);
00621 _goto_list = gnew;
00622 }
00623 }
00624
00625
00626
00627 RGN_LABEL *
00628 RINIT::Add_label(WN *wn, WN *block)
00629 {
00630 RGN_LABEL *htmp;
00631 Is_True(WN_opcode(wn) == OPC_LABEL,
00632 ("RINIT::Add_label, unexpected opcode: %s",
00633 OPCODE_name(WN_opcode(wn))));
00634 for (htmp=Head_list(); htmp; htmp=htmp->Next()) {
00635 if (WN_label_number(htmp->Label()) == WN_label_number(wn))
00636 return htmp;
00637 }
00638 htmp = CXX_NEW(RGN_LABEL(), Mem_pool());
00639 htmp->Set_block(block);
00640 htmp->Set_label(wn);
00641 htmp->Set_replace_label(WN_CopyNode(wn));
00642 htmp->Set_next(Label_list());
00643 Set_label_list(htmp);
00644 return htmp;
00645 }
00646
00647
00648 RGN_LABEL *
00649 RINIT::Add_head_label(WN *wn, WN *block)
00650 {
00651 Is_True(WN_opcode(wn) == OPC_LABEL,
00652 ("RINIT::Add_head_label, unexpected opcode: %s",
00653 OPCODE_name(WN_opcode(wn))));
00654 RGN_LABEL *htmp = CXX_NEW(RGN_LABEL(), Mem_pool());
00655 htmp->Set_block(block);
00656 htmp->Set_label(WN_CopyNode(wn));
00657 htmp->Set_replace_label(WN_CopyNode(wn));
00658 htmp->Set_next(Head_list());
00659 Set_head_list(htmp);
00660 return htmp;
00661 }
00662
00663
00664 void
00665 RINIT::Add_label_alias(WN *old_wn, WN *new_wn)
00666 {
00667
00668 LABEL_ALIAS *ltmp;
00669 BOOL found = FALSE;
00670 for (ltmp = Label_alias(); ltmp; ltmp = ltmp->Next()) {
00671 if (ltmp->Key() == WN_label_number(old_wn)) {
00672 found = TRUE;
00673 break;
00674 }
00675 }
00676
00677 if (!found) {
00678 ltmp = CXX_NEW(LABEL_ALIAS(), Mem_pool());
00679 ltmp->Set_key(WN_label_number(old_wn));
00680 ltmp->Set_next(Label_alias());
00681 Set_label_alias(ltmp);
00682 }
00683 ltmp->Add_label_alias(WN_label_number(new_wn), WN_st_idx(new_wn), Mem_pool());
00684 Is_Trace(Trace(), (TFile," RINIT::Add_label_alias(%s), L%d --> L%d, "
00685 "RGN %d\n", found ? "found" : "new",
00686 WN_label_number(old_wn), WN_label_number(new_wn),
00687 RID_id(Rid())));
00688 Is_Trace_cmd(Trace(), Label_alias()->Print(TFile));
00689 }
00690
00691
00692 void
00693 RINIT::Expand_label_alias(RGN_LABEL *label)
00694 {
00695 Is_True(Label_alias() != NULL, ("RINIT::Expand_label_alias, no alias list"));
00696 Is_True(label->Block() != NULL, ("RINIT::Expand_label_alias, NULL block"));
00697 Is_True(label->Label() != NULL && WN_opcode(label->Label()) == OPC_LABEL,
00698 ("RINIT::Expand_label_alias, label is wrong"));
00699
00700 LABEL_ALIAS *prev = NULL;
00701 for (LABEL_ALIAS *ltmp = Label_alias(); ltmp; ltmp = ltmp->Next()) {
00702 if (ltmp->Key() == WN_label_number(label->Label())) {
00703
00704 Is_True(ltmp->Alias_list() != NULL && ltmp->Last() != NULL,
00705 ("RINIT::Expand_label_alias, alias list is wrong"));
00706
00707
00708 LITE_LABEL *ntmp;
00709 for (ntmp=ltmp->Alias_list(); ntmp; ntmp=ntmp->Next()) {
00710 if (Trace())
00711 fprintf(TFile,"RINIT::Expand_label_alias, expanding L%d to L%d for "
00712 "RGN %d\n",
00713 WN_label_number(label->Label()), ntmp->Label(),
00714 RID_id(Rid()));
00715 Is_True(ntmp->Label() != 0,
00716 ("RINIT::Expand_label_alias, incorrect LITE_LABEL"));
00717 WN *wtmp = WN_CreateLabel (ntmp->Label(), 0, NULL);
00718 WN_INSERT_BlockAfter(label->Block(), label->Label(), wtmp);
00719
00720
00721 Add_label(wtmp, label->Block());
00722
00723 #ifdef Is_True_On
00724
00725 if (ntmp->Next() == NULL)
00726 Is_True(ltmp->Last() == ntmp,
00727 ("RINIT::Expand_label_alias, Last pointer is wrong"));
00728 #endif
00729 }
00730
00731
00732 Is_Trace(Trace(),(TFile,
00733 "RINIT::Expand_label_alias, deleting list for L%d\n",
00734 ltmp->Key()));
00735 ltmp->Set_alias_list(NULL);
00736 ltmp->Set_last(NULL);
00737 if (prev == NULL)
00738 Set_label_alias(ltmp->Next());
00739 else
00740 prev->Set_next(ltmp->Next());
00741
00742 break;
00743 }
00744 prev = ltmp;
00745 }
00746 }
00747
00748
00749
00750
00751 void
00752 RINIT::Merge_label_alias(LABEL_ALIAS *la)
00753 {
00754
00755 if (la) {
00756
00757 LABEL_ALIAS *new_list = NULL;
00758
00759
00760
00761
00762 start:
00763 LABEL_ALIAS *prev1 = NULL;
00764 for (LABEL_ALIAS *ltmp1 = Label_alias(); ltmp1; ltmp1 = ltmp1->Next()) {
00765
00766
00767 BOOL merged = FALSE;
00768 for (LABEL_ALIAS *ltmp2 = la; ltmp2; ltmp2 = ltmp2->Next()) {
00769
00770 if (ltmp1->Key() == ltmp2->Key()) {
00771 Is_True(ltmp1->Alias_list() != NULL && ltmp1->Last() != NULL,
00772 ("RINIT::Merge_label_alias, ltmp1->Alias_list is NULL"));
00773 Is_True(ltmp2->Alias_list() != NULL && ltmp2->Last() != NULL,
00774 ("RINIT::Merge_label_alias, ltmp2->Alias_list is NULL"));
00775
00776 ltmp2->Merge_label_alias(ltmp1, Mem_pool());
00777 merged = TRUE;
00778 break;
00779 }
00780 }
00781
00782
00783 if (!merged) {
00784
00785 if (prev1 == NULL)
00786 Set_label_alias(ltmp1->Next());
00787 else
00788 prev1->Set_next(ltmp1->Next());
00789
00790 ltmp1->Set_next(new_list);
00791 new_list = ltmp1;
00792
00793 goto start;
00794 }
00795 prev1 = ltmp1;
00796
00797 }
00798
00799
00800
00801 LABEL_ALIAS *ltmp2;
00802 for (ltmp2 = la; ltmp2->Next() != NULL; ltmp2 = ltmp2->Next())
00803 ;
00804 ltmp2->Set_next(new_list);
00805
00806
00807 Set_label_alias(la);
00808 }
00809 }
00810
00811 void
00812 RGN_LABEL::Print(const char *str)
00813 {
00814 fprintf(TFile,"\t%s: ",str);
00815 fdump_wn(TFile,Label());
00816 if (WN_label_number(Label()) != WN_label_number(Replace_label())) {
00817 fprintf(TFile,"\treplace: ");
00818 fdump_wn(TFile,Replace_label());
00819 }
00820 if (Split_label() != NULL) {
00821 fprintf(TFile,"\tsplit: ");
00822 fdump_wn(TFile,Split_label());
00823 }
00824 }
00825
00826 void
00827 RINIT::Print_sets(void)
00828 {
00829 RGN_LABEL *htmp;
00830
00831 fprintf(TFile,"RGN %d\n",RID_id(Rid()));
00832 fprintf(TFile,"goto_list:\n");
00833 if (_goto_list != NULL) {
00834 for (GOTO *gtmp=_goto_list; gtmp; gtmp=gtmp->Next())
00835 gtmp->fdump(TFile);
00836 } else
00837 fprintf(TFile," <null>\n");
00838
00839 fprintf(TFile,"label_list:\n");
00840 if (_label_list != NULL) {
00841 for (htmp=Label_list(); htmp; htmp=htmp->Next())
00842 htmp->Print("label");
00843 } else
00844 fprintf(TFile," <null>\n");
00845
00846 fprintf(TFile,"head_list:\n");
00847 if (Head_list() != NULL) {
00848 for (RGN_LABEL *htmp=Head_list(); htmp; htmp=htmp->Next())
00849 htmp->Print("head ");
00850 } else
00851 fprintf(TFile," <null>\n");
00852
00853 fprintf(TFile,"alias label list:\n");
00854 if (Label_alias() != NULL) {
00855 Label_alias()->Print(TFile);
00856 } else
00857 fprintf(TFile," <null>\n");
00858 }
00859
00860
00861
00862
00863
00864
00865 GOTO *
00866 RINIT::Cancel_internal_gotos(BOOL prop_up)
00867 {
00868 GOTO *gtmp;
00869 RGN_LABEL *htmp;
00870 BOOL found;
00871
00872
00873
00874
00875
00876 if (Label_alias()) {
00877 for (htmp=Label_list(); htmp && Label_alias(); htmp=htmp->Next()) {
00878
00879 Expand_label_alias(htmp);
00880 }
00881
00882 for (htmp=Head_list(); htmp && Label_alias(); htmp=htmp->Next()) {
00883
00884 Expand_label_alias(htmp);
00885 }
00886 }
00887
00888
00889 for (gtmp=_goto_list; gtmp; gtmp=gtmp->Next()) {
00890 found = FALSE;
00891 if (gtmp->Outside()) {
00892
00893
00894
00895 for (htmp=Label_list(); htmp; htmp=htmp->Next()) {
00896 Is_True(htmp->Label() != NULL,
00897 ("RINIT::Cancel_internal_gotos, null label"));
00898 Is_True(htmp->Replace_label() != NULL,
00899 ("RINIT::Cancel_internal_gotos, null replace label"));
00900
00901
00902 if (gtmp->Compare_labels(htmp->Label())) {
00903 gtmp->Set_inside();
00904 if (Trace()) {
00905 fprintf(TFile,
00906 "===== RINIT::Cancel_internal_gotos: cancelled to label_list:\n");
00907 gtmp->fdump(TFile);
00908 }
00909 found = TRUE;
00910 break;
00911 }
00912
00913
00914 if (WN_label_number(htmp->Label()) !=
00915 WN_label_number(htmp->Replace_label()) &&
00916 gtmp->Compare_labels(htmp->Replace_label())) {
00917 gtmp->Set_inside();
00918 if (Trace()) {
00919 fprintf(TFile,
00920 "===== RINIT::Cancel_internal_gotos: cancelled to replace:\n");
00921 gtmp->fdump(TFile);
00922 fprintf(TFile," 1) rewriting L%d to L%d for RGN %d\n",
00923 gtmp->Label_number(), WN_label_number(htmp->Label()),
00924 RID_id(gtmp->Rid()));
00925 }
00926
00927 if (gtmp->Rid() != Rid()) {
00928 Is_Trace(Trace(),
00929 (TFile," 1) rewriting exit list L%d to L%d for RGN %d\n",
00930 gtmp->Label_number(),
00931 WN_label_number(htmp->Label()),
00932 RID_id(gtmp->Rid())));
00933
00934 gtmp->Modify_exits(gtmp->Rid(), Rid(), htmp->Label());
00935 }
00936
00937 gtmp->Set_label_number(htmp->Label());
00938 found = TRUE;
00939 break;
00940 }
00941 }
00942 if (found)
00943 continue;
00944
00945
00946
00947 for (htmp=Head_list(); htmp; htmp=htmp->Next()) {
00948 Is_True(htmp->Label() != NULL,
00949 ("RINIT::Cancel_internal_gotos, null head label"));
00950 Is_True(htmp->Replace_label() != NULL,
00951 ("RINIT::Cancel_internal_gotos, null head replace label"));
00952
00953
00954 if (gtmp->Compare_labels(htmp->Label())) {
00955 gtmp->Set_inside();
00956 if (Trace()) {
00957 fprintf(TFile,
00958 "===== RINIT::Cancel_internal_gotos: cancelled to head:\n");
00959 gtmp->fdump(TFile);
00960 }
00961 break;
00962 }
00963
00964
00965 if (WN_label_number(htmp->Label()) !=
00966 WN_label_number(htmp->Replace_label()) &&
00967 gtmp->Compare_labels(htmp->Replace_label())) {
00968 gtmp->Set_inside();
00969 Is_True(htmp->Split_label() != NULL,
00970 ("RINIT::Cancel_internal_gotos, replace label exists (L%d) "
00971 "without split label",
00972 WN_label_number(htmp->Replace_label())));
00973 if (Trace()) {
00974 fprintf(TFile,"===== RINIT::Cancel_internal_gotos: cancelled "
00975 "to head replace:\n");
00976 gtmp->fdump(TFile);
00977 fprintf(TFile," 2) rewriting L%d to L%d for RGN %d\n",
00978 gtmp->Label_number(), WN_label_number(htmp->Split_label()),
00979 RID_id(gtmp->Rid()));
00980 }
00981
00982 if (gtmp->Rid() != Rid()) {
00983 Is_Trace(Trace(),
00984 (TFile," 2) rewriting exit list L%d to L%d for RGN %d\n",
00985 gtmp->Label_number(),
00986 WN_label_number(htmp->Split_label()),
00987 RID_id(gtmp->Rid())));
00988
00989 gtmp->Modify_exits(gtmp->Rid(), Rid(), htmp->Split_label());
00990 }
00991
00992 gtmp->Set_label_number(htmp->Split_label());
00993 break;
00994 }
00995 }
00996
00997 }
00998 }
00999
01000
01001
01002 _nexits = 0;
01003 GOTO *gnew = NULL, *gtmp_next;
01004 for (gtmp=Goto_list(); gtmp; gtmp=gtmp_next) {
01005 gtmp_next = gtmp->Next();
01006 if (gtmp->Outside()) {
01007
01008 if (RID_TYPE_mp(Rid())) {
01009 char label_str[20];
01010 sprintf(label_str,"L%d",gtmp->Label_number());
01011 ErrMsg(EC_Rgn_Ill_Exit, label_str, Srcpos_To_Line(gtmp->Linenum()));
01012 }
01013
01014
01015
01016
01017 if (prop_up) {
01018 gtmp->Set_region_exit(Rid(), this);
01019 _nexits++;
01020 }
01021
01022
01023 gtmp->Set_next(gnew);
01024 gnew = gtmp;
01025
01026 if (Trace()) {
01027 fprintf(TFile,
01028 "===== RINIT::Cancel_internal_gotos, propagated up from RGN %d:\n",
01029 RID_id(Rid()));
01030 gtmp->fdump(TFile);
01031 }
01032 }
01033 }
01034
01035 Set_goto_list(NULL);
01036 return gnew;
01037 }
01038
01039
01040
01041
01042
01043 void
01044 RINIT::Handle_split_label(WN *region, WN *orig_label, WN *block, RINIT *rinit)
01045 {
01046
01047
01048
01049
01050
01051 LABEL_IDX label_no;
01052 New_LABEL(CURRENT_SYMTAB, label_no);
01053 WN *label_wn = WN_CreateLabel (label_no, 0, NULL);
01054 WN_Set_Linenum(label_wn, WN_Get_Linenum(region));
01055 RGN_LABEL *head = rinit->Add_head_label(label_wn, block);
01056
01057
01058 WN_INSERT_BlockAfter(WN_region_body(region), orig_label, label_wn);
01059
01060 WN *orig_wn = WN_CopyNode(orig_label);
01061 WN_DELETE_FromBlock(WN_region_body(region), orig_label);
01062 orig_label = NULL;
01063
01064 WN_INSERT_BlockBefore(block, region, orig_wn);
01065
01066 head->Set_replace_label(orig_wn);
01067
01068
01069 head->Set_split_label(label_wn);
01070
01071 if (Trace())
01072 fprintf(TFile,"RINIT::Handle_split_label, inserted outside label L%d for "
01073 "L%d in RGN %d (parent RGN %d)\n", WN_label_number(label_wn),
01074 WN_label_number(orig_wn), RID_id(rinit->Rid()), RID_id(Rid()));
01075
01076
01077
01078 RGN_LABEL *uplevel;
01079 uplevel = (WN_first(WN_region_body(RID_rwn(Rid()))) == orig_wn) ?
01080 Add_head_label(orig_wn, block) : Add_label(orig_wn, block);
01081 uplevel->Set_replace_label(orig_wn);
01082 if (Trace())
01083 fprintf(TFile,"RINIT::Handle_split_label, propagated L%d up to "
01084 "RGN %d\n", WN_label_number(orig_wn), RID_id(Rid()));
01085 }
01086
01087
01088 void
01089 RINIT::Process_region(WN *wtmp, WN *block, INT32 level, RID *root,
01090 char *parent_options)
01091 {
01092 WN *wtmp2;
01093 char *region_options = NULL;
01094
01095 Set_PU_has_region (Get_Current_PU ());
01096 Is_True(wtmp && WN_opcode(wtmp) == OPC_REGION,
01097 ("RINIT::Process_region, not a region"));
01098 RID *rid = RID_Create(WN_region_id(wtmp), level, wtmp);
01099 RID_level(rid) = RL_RGN_INIT;
01100 RID_bounds_exist(rid) = REGION_BOUND_UNKNOWN;
01101 RID_is_glue_code(rid) = FALSE;
01102 Is_True(block != NULL, ("RINIT::Process_region, block is NULL"));
01103
01104 REGION_kind_to_type(wtmp, rid);
01105
01106 if (!RID_TYPE_mp(rid))
01107 _nregions++;
01108
01109 Is_True(RID_type(rid) != RID_TYPE_undefined,
01110 ("RINIT::Process_region, unknown region type"));
01111
01112
01113 if (!RID_TYPE_transparent(rid)) {
01114
01115
01116
01117
01118
01119
01120 region_options = REGION_get_options_string(wtmp);
01121
01122
01123 if (parent_options != NULL) {
01124 INT len = strlen(parent_options) + 2 +
01125 (region_options ? strlen(region_options) : 0);
01126 char *tmp = CXX_NEW_ARRAY(char, len, ®ION_mem_pool);
01127 strcpy(tmp, parent_options);
01128 strcat(tmp, " ");
01129 if (region_options)
01130 strcat(tmp, region_options);
01131 region_options = tmp;
01132 }
01133 RID_options(rid) = region_options;
01134 }
01135
01136 WN_MAP_Set(RID_map, wtmp, (void *)rid);
01137 RID_Add_kid(rid, root);
01138
01139
01140
01141
01142 wtmp2 = WN_last(WN_region_body(wtmp));
01143 #if defined(TARG_SL)
01144
01145 if (wtmp2 && !RID_TYPE_sl2_para(rid) && !RID_TYPE_mp(rid) && !RID_TYPE_eh(rid) &&
01146 WN_opcode(wtmp2) != OPC_GOTO && WN_opcode(wtmp2) != OPC_RETURN &&
01147 WN_opcode(wtmp2) != OPC_REGION_EXIT) {
01148 #else
01149 if (wtmp2 && !RID_TYPE_mp(rid) && !RID_TYPE_eh(rid) &&
01150 WN_opcode(wtmp2) != OPC_GOTO && WN_opcode(wtmp2) != OPC_RETURN &&
01151 WN_opcode(wtmp2) != OPC_REGION_EXIT) {
01152 #endif
01153
01154 WN *wtmp3 = REGION_add_exit(block, WN_next(wtmp), wtmp);
01155 RID_num_exits(rid)++;
01156 Is_Trace(Trace(),(TFile,"RINIT::Process_region, added fall-thru "
01157 "REGION_EXIT L%d, RGN %d\n", WN_label_number(wtmp3),RID_id(rid)));
01158 }
01159
01160
01161 #ifdef TARG_SL //add_type_for_minor //PARA_EXTENSION
01162 if (!RID_TYPE_eh(rid) && !RID_TYPE_mp(rid) && !RID_TYPE_sl2_para(rid))
01163 #else
01164 if (!RID_TYPE_eh(rid) && !RID_TYPE_mp(rid))
01165 #endif
01166 REGION_has_black_regions(rid);
01167
01168
01169 if (!RID_TYPE_transparent(rid) || RID_contains_bounds(rid))
01170 #ifdef TARG_SL //fork_joint
01171 {
01172
01173
01174
01175
01176 if(RID_TYPE_sl2_para(rid))
01177 RID_contains_bounds(rid) = TRUE;
01178
01179 RID* tmp_rid = root;
01180 while(!RID_TYPE_func_entry(tmp_rid))
01181 tmp_rid = RID_parent(tmp_rid);
01182
01183 RID_contains_bounds(tmp_rid) = TRUE;
01184 }
01185 #else
01186 RID_contains_bounds(root) = TRUE;
01187 #endif //fork_joint
01188
01189
01190
01191 RINIT rinit(rid, Mem_pool());
01192
01193
01194 BOOL found_split = FALSE;
01195 wtmp2 = WN_first(WN_region_body(wtmp));
01196 if (wtmp2 && WN_opcode(wtmp2) == OPC_LABEL) {
01197 Handle_split_label(wtmp, wtmp2, block, &rinit);
01198 found_split = TRUE;
01199 }
01200
01201 rinit.Region_init(WN_region_body(wtmp), level, rid, region_options);
01202 _nregions += rinit.Nregions();
01203
01204
01205
01206 wtmp2 = WN_first(WN_region_body(wtmp));
01207 if (wtmp2 && !found_split && rinit.Head_list() &&
01208 WN_opcode(wtmp2) == OPC_LABEL)
01209 Handle_split_label(wtmp, wtmp2, block, &rinit);
01210
01211 if (Trace()) {
01212 fprintf(TFile,
01213 "===== RINIT::Process_region, RGN %d, %s, loop level = %d\n",
01214 RID_id(rid),RID_type_str(RID_type(rid)),level);
01215 rinit.Print_sets();
01216 }
01217
01218 #ifdef KEY
01219
01220
01221
01222
01223 for (RGN_LABEL * labels = rinit.Label_list();
01224 labels;
01225 labels = labels->Next())
01226 Add_label (labels->Label(), labels->Block());
01227 #endif // KEY
01228
01229
01230
01231 GOTO *glist = rinit.Cancel_internal_gotos(TRUE);
01232 Concat_goto(glist);
01233 Merge_label_alias(rinit.Label_alias());
01234 Is_Trace(Trace(), (TFile,
01235 "Merge_label_alias from RGN %d to RGN %d\n",
01236 RID_id(rinit.Rid()), RID_id(Rid())));
01237 Is_Trace_cmd(Trace(), Label_alias()->Print(TFile));
01238 RID_num_exits(rid) = REGION_count_exits(WN_region_exits(RID_rwn(rid)));
01239 Is_Trace(Trace(), (TFile,"RINIT::Process_region, RGN %d, after "
01240 "Cancel_internal_gotos, num_exits = %d\n",
01241 RID_id(rid),RID_num_exits(rid)));
01242 Is_Trace_cmd(Trace(), fdump_tree(TFile,WN_region_exits(RID_rwn(rid))));
01243 }
01244
01245
01246
01247
01248
01249
01250
01251
01252 void
01253 RINIT::Region_init(WN *block, INT32 level, RID *root, char *options)
01254 {
01255 #ifdef KEY
01256
01257 if (WN_operator(block) != OPR_BLOCK)
01258 {
01259 for (INT32 i=0; i<WN_kid_count(block); i++)
01260 Region_init (WN_kid(block, i), level, root, options);
01261 return;
01262 }
01263 #endif
01264
01265 for (WN *wtmp=WN_first(block); wtmp; wtmp=WN_next(wtmp)) {
01266
01267 switch (WN_operator(wtmp)) {
01268 case OPR_REGION:
01269
01270
01271 Is_True(WN_region_exits(wtmp) &&
01272 WN_opcode(WN_region_exits(wtmp)) == OPC_BLOCK,
01273 ("RINIT::Region_init, malformed region exit block"));
01274 if (WN_first(WN_region_exits(wtmp)) != NULL) {
01275 WN_DELETE_Tree(WN_region_exits(wtmp));
01276 WN_region_exits(wtmp) = WN_CreateBlock();
01277 }
01278
01279 Process_region(wtmp, block, level, root, options);
01280 break;
01281 case OPR_DO_LOOP:
01282 Region_init(WN_do_body(wtmp), level+1, root, options);
01283 break;
01284 case OPR_WHILE_DO:
01285 case OPR_DO_WHILE:
01286 Region_init(WN_while_body(wtmp), level+1, root, options);
01287 break;
01288 case OPR_BLOCK:
01289 Region_init(wtmp, level, root, options);
01290 break;
01291 case OPR_IF:
01292 Region_init(WN_then(wtmp), level, root, options);
01293 Region_init(WN_else(wtmp), level, root, options);
01294 break;
01295 case OPR_IO:
01296 if (WN_operator(RID_rwn(root)) == OPR_REGION && !RID_TYPE_mp(root)) {
01297 for (INT32 i=0; i<WN_kid_count(wtmp); i++) {
01298 WN *kid = WN_kid(wtmp, i);
01299 if (WN_opcode(kid) == OPC_IO_ITEM &&
01300 (WN_io_item(kid) == IOC_END || WN_io_item(kid)==IOC_ERR ||
01301 WN_io_item(kid) == IOC_EOR)) {
01302 WN *kid0 = WN_kid0(kid);
01303
01304
01305
01306
01307
01308
01309 Add_goto(kid0, WN_region_body(RID_rwn(root)), TRUE, FALSE);
01310 }
01311 }
01312 }
01313 break;
01314 case OPR_GOTO:
01315 case OPR_TRUEBR:
01316 case OPR_FALSEBR:
01317 case OPR_REGION_EXIT:
01318 Add_goto(wtmp, block, FALSE, FALSE);
01319 break;
01320 case OPR_COMPGOTO:
01321 { WN *gotoblock = WN_kid(wtmp,1);
01322 Is_True(WN_opcode(gotoblock) == OPC_BLOCK,
01323 ("RINIT::Region_init, comp goto in wrong form"));
01324 for (WN *wtmp2=WN_first(gotoblock); wtmp2; wtmp2=WN_next(wtmp2))
01325 Add_goto(wtmp2, gotoblock, FALSE, TRUE);
01326 }
01327 break;
01328 case OPR_LABEL:
01329 Add_label(wtmp, block);
01330 break;
01331 case OPR_RETURN:
01332 REGION_propagate_return(root);
01333 break;
01334
01335 default:
01336 #ifdef KEY
01337
01338 for (INT32 i=0; i<WN_kid_count(wtmp); i++)
01339 Region_init (WN_kid (wtmp, i), level, root, options);
01340 #endif // KEY
01341 break;
01342 }
01343
01344 }
01345 }
01346
01347
01348
01349
01350
01351 static INT
01352 REGION_init(WN *itree, RID *root)
01353 {
01354 Is_True(WN_opcode(itree) == OPC_FUNC_ENTRY,
01355 ("REGION_init must be called on a func_entry"));
01356
01357 Set_Error_Phase("Region Init");
01358
01359 MEM_POOL REGION_init_pool;
01360 MEM_POOL_Initialize(®ION_init_pool, "REGION_init_pool", FALSE);
01361 MEM_POOL_Push(®ION_init_pool);
01362
01363 RINIT rtmp(root, ®ION_init_pool);
01364 rtmp.Region_init(WN_func_body(itree), 0, root, RID_options(root));
01365
01366 GOTO *g_unresolved = rtmp.Cancel_internal_gotos(0);
01367
01368 for (GOTO *gtmp=g_unresolved; gtmp; gtmp=gtmp->Next()) {
01369 BOOL found = FALSE;
01370 LABEL_IDX label;
01371 for (label=0; label < Scope_tab[CURRENT_SYMTAB].label_tab->Size();label++){
01372 if (gtmp->Compare_labels(label)) {
01373 #ifndef KEY
01374 Is_Trace_cmd(rtmp.Trace(), fdump_tree(TFile, itree));
01375 Is_Trace_cmd(rtmp.Trace(), RID_Tree_Print(TFile, root));
01376 char buffer [20];
01377 sprintf(buffer, "%d", label);
01378 ErrMsg(EC_Rgn_Ill_Entry, buffer, Srcpos_To_Line(gtmp->Linenum()));
01379 found = TRUE;
01380 #else
01381
01382
01383
01384
01385
01386
01387
01388
01389 found = TRUE;
01390 break;
01391 #endif
01392 }
01393 }
01394 if (!found) {
01395 Is_Trace_cmd(rtmp.Trace(), fdump_tree(TFile, itree));
01396 Is_Trace_cmd(rtmp.Trace(), RID_Tree_Print(TFile, root));
01397 char label_str[20];
01398 sprintf(label_str,"L%d",gtmp->Label_number());
01399 ErrMsg(EC_Rgn_Ill_Entry, label_str, Srcpos_To_Line(gtmp->Linenum()));
01400 }
01401 }
01402
01403 if (rtmp.Trace()) {
01404 fprintf(TFile,"===== Region_init, %s%d\n",
01405 RID_TYPE_func_entry(root) ? "PU" : "RGN", RID_id(root));
01406 rtmp.Print_sets();
01407 }
01408
01409 INT32 nregions = rtmp.Nregions();
01410 MEM_POOL_Delete(®ION_init_pool);
01411 return nregions;
01412 }
01413
01414
01415
01416
01417
01418
01419
01420
01421
01422 static bool Region_skip(WN *block, WN *wn)
01423 {
01424 WN *wtmp;
01425 INT i;
01426
01427 Is_True(wn, ("Region_skip, NULL wn"));
01428
01429 switch (WN_operator(wn)) {
01430
01431 case OPR_REGION:
01432 Is_True(block && WN_operator(block) == OPR_BLOCK,
01433 ("Region_skip, NULL block"));
01434 if (Query_Skiplist(Region_Skip_List, WN_region_id(wn))) {
01435 ErrMsg (EC_Region_Skipped, WN_region_id(wn) );
01436 #ifdef Is_True_On
01437
01438 for (wtmp = WN_first(block); wtmp && wtmp != wn; wtmp = WN_next(wtmp))
01439 ;
01440 Is_True(wtmp == wn, ("Region_skip, cannot find wn in block"));
01441 #endif
01442
01443 wtmp = WN_next(wn);
01444
01445 WN *region_body = WN_region_body(WN_EXTRACT_FromBlock(block, wn));
01446 Is_True(WN_operator(region_body) == OPR_BLOCK,
01447 ("Region_skip, region body is not a block"));
01448
01449
01450 if (wtmp == NULL)
01451 WN_INSERT_BlockLast(block, region_body);
01452 else
01453 WN_INSERT_BlockBefore(block, wtmp, region_body);
01454
01455 return TRUE;
01456 } else
01457 Region_skip(NULL, WN_region_body(wn));
01458 break;
01459
01460 case OPR_FUNC_ENTRY:
01461 Is_True(!block, ("Region_skip, non-NULL block in func_entry"));
01462 Is_True(WN_operator(WN_func_body(wn)) == OPR_BLOCK,
01463 ("Region_skip, func_body messed up"));
01464 Region_skip(NULL, WN_func_body(wn));
01465 break;
01466
01467 case OPR_BLOCK:
01468 { BOOL redoit;
01469 do {
01470 redoit = FALSE;
01471 for (wtmp=WN_first(wn); wtmp; wtmp=WN_next(wtmp)) {
01472
01473
01474
01475 if (Region_skip(wn, wtmp)) {
01476 redoit = TRUE;
01477 break;
01478 }
01479 }
01480 } while (redoit);
01481 }
01482 break;
01483
01484 default:
01485 for (i=0; i<WN_kid_count(wn); i++)
01486 Region_skip(block, WN_kid(wn,i));
01487 break;
01488 }
01489 return FALSE;
01490 }
01491
01492 #ifdef Is_True_On
01493
01494
01495
01496
01497 static void verify_region_initialization(RID *rid, RID *root)
01498 {
01499 RID *rtmp;
01500
01501 Is_True(rid != NULL, ("verify_region_initialization, NULL rid"));
01502 Is_Trace(Get_Trace(TP_REGION, TT_REGION_ALL),
01503 (TFile,"verify_region_initialization, RGN %d\n",RID_id(rid)));
01504
01505
01506 REGION_consistency_check(RID_rwn(rid));
01507
01508
01509 if (RID_TYPE_func_entry(rid))
01510 Is_True(root == NULL, ("verify_region_initialization, non-NULL root"));
01511 else
01512 Is_True(RID_parent(rid) == root,
01513 ("verify_region_initialization, messed up parent"));
01514
01515 for (rtmp=RID_first_kid(rid); rtmp; rtmp=RID_next(rtmp))
01516 verify_region_initialization(rtmp, rid);
01517 }
01518 #endif
01519
01520
01521
01522
01523
01524
01525
01526
01527
01528
01529 MEM_POOL REGION_mem_pool;
01530 WN_MAP RID_map = WN_MAP_UNDEFINED;
01531
01532 #define REGION_MAP_ARRAY_SIZE 32
01533 static WN_MAP region_map_array[REGION_MAP_ARRAY_SIZE];
01534 static INT32 region_map_index = -1;
01535
01536 extern "C"
01537 INT REGION_Initialize(WN *wn, BOOL has_rgns)
01538 {
01539 RID *rid;
01540 INT nregions = 0;
01541
01542
01543 {
01544
01545 static BOOL region_mem_pool_initialized = FALSE;
01546 if (region_mem_pool_initialized == FALSE) {
01547 MEM_POOL_Initialize(®ION_mem_pool, "REGION", TRUE);
01548 region_mem_pool_initialized = TRUE;
01549 }
01550 }
01551 MEM_POOL_Push(®ION_mem_pool);
01552
01553 RID_map = WN_MAP_Create(®ION_mem_pool);
01554 WN_MAP_Set_dont_copy(RID_map, TRUE);
01555
01556
01557 region_map_index++;
01558 FmtAssert(0 <= region_map_index && region_map_index < REGION_MAP_ARRAY_SIZE,
01559 ("REGION_Initialize: region_map_index is out of range"));
01560 region_map_array[region_map_index] = RID_map;
01561
01562 Is_True(WN_opcode(wn) == OPC_FUNC_ENTRY,
01563 ("REGION_Initialize, not a func_entry"));
01564
01565 rid = RID_Create(0, 0, wn);
01566 RID_level(rid) = RL_RGN_INIT;
01567 RID_bounds_exist(rid) = REGION_BOUND_UNKNOWN;
01568 RID_has_return(rid) = REGION_NO_RETURN;
01569 RID_num_exits(rid) = 0;
01570 RID_TYPE_func_entry_Set(rid);
01571 RID_options(rid) = REGION_get_options_string(wn);
01572 WN_MAP_Set(RID_map, wn, (void *)rid);
01573 nregions++;
01574
01575
01576 if (Region_Skip_List != NULL)
01577 Region_skip(NULL,wn);
01578
01579
01580
01581
01582 if (has_rgns)
01583 nregions += REGION_init(wn, rid);
01584
01585 if (Get_Trace(TKIND_IR, TP_REGION)) {
01586 fputs(DBar, TFile);
01587 fprintf(TFile, "After Region Init:\n");
01588 fdump_tree(TFile, wn);
01589 fputs(DBar, TFile);
01590 }
01591 if (Get_Trace(TP_REGION, TT_REGION_ALL)) {
01592 fprintf(TFile,"===== REGION_Initialize, nregions = %d\n",nregions);
01593 RID_WN_Tree_Print(TFile,wn);
01594 Is_Trace_cmd(Get_Trace(TP_REGION, TT_REGION_ALL),
01595 fdump_tree(TFile,wn));
01596 Is_Trace_cmd(Get_Trace(TP_REGION, TT_REGION_ALL),
01597 fprintf(TFile,"%s\n",DBar));
01598 }
01599 #ifdef Is_True_On
01600 Set_Error_Phase("Verify Region Init");
01601 verify_region_initialization(REGION_get_rid(wn), NULL);
01602 #endif
01603 return nregions;
01604 }
01605
01606
01607
01608
01609 extern "C" void REGION_Finalize(void)
01610 {
01611 WN_MAP_Delete(RID_map);
01612 MEM_POOL_Pop(®ION_mem_pool);
01613
01614 region_map_index--;
01615 if (region_map_index >= 0) {
01616
01617 RID_map = region_map_array[region_map_index];
01618 }
01619 else {
01620
01621 RID_map = WN_MAP_UNDEFINED;
01622 }
01623 }