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
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094 #ifdef USE_PCH
00095 #include "be_com_pch.h"
00096 #endif
00097 #pragma hdrstop
00098
00099
00100 #include "opt_goto.h"
00101 #include "wn_util.h"
00102 #include "config_targ.h"
00103 #include "strtab.h"
00104 #include "stab.h"
00105 #include "wn_lower.h"
00106 #include "targ_sim.h"
00107 #include "fb_whirl.h"
00108
00109 #ifdef _KEEP_RCS_ID
00110 #define opt_goto_CXX "opt_goto.cxx"
00111 static char *rcs_id = opt_goto_CXX" $Revision: 1.21 $";
00112 #endif
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123 void GOTO_TABLE::Build()
00124 {
00125 _parent_map = WN_MAP_Create(_pool);
00126 Is_True(_parent_map != -1, ("Ran out of mappings in GOTO_TABLE::Build"));
00127 if (_parent_map == -1) {
00128 return;
00129 }
00130
00131
00132 typedef HASH_TABLE<INT, LABEL_DESCRIPTOR *> THIS_HASH_TABLE;
00133 _label_table =
00134 CXX_NEW(THIS_HASH_TABLE(200, _pool), _pool);
00135
00136 Build_Rec(WN_func_body(_func_nd), _func_nd, FALSE);
00137 Backpatch();
00138 }
00139
00140 void GOTO_TABLE::Fixup_Parents(WN *wn, WN *parent)
00141 {
00142 const OPCODE opcode = WN_opcode(wn);
00143
00144 if (opcode == OPC_BLOCK) {
00145 Set_Parent(wn, parent);
00146 WN *kid = WN_first(wn);
00147 while (kid) {
00148 Fixup_Parents(kid, wn);
00149 kid = WN_next(kid);
00150 }
00151 return;
00152 }
00153 if (opcode == OPC_ALTENTRY) {
00154 Set_Parent(wn, parent);
00155 }
00156
00157
00158
00159 if ((opcode == OPC_DO_LOOP) || (opcode == OPC_DO_WHILE) ||
00160 (opcode == OPC_REGION) ||
00161 (opcode == OPC_WHILE_DO) || (opcode == OPC_IF)) {
00162 Set_Parent(wn, parent);
00163 for (INT kidno = 0; kidno < WN_kid_count(wn); kidno++) {
00164 Fixup_Parents(WN_kid(wn, kidno), wn);
00165 }
00166 return;
00167 }
00168 if (opcode == OPC_COMPGOTO) {
00169 Set_Parent(wn, parent);
00170 for (INT kidno = 0; kidno < WN_kid_count(wn); kidno++) {
00171 Fixup_Parents(WN_kid(wn, kidno), wn);
00172 }
00173 return;
00174 }
00175
00176 if ((opcode == OPC_GOTO) || (opcode == OPC_TRUEBR) ||
00177 (opcode == OPC_FALSEBR)) {
00178 Set_Parent(wn, parent);
00179 } else if (opcode == OPC_LABEL) {
00180 Set_Parent(wn, parent);
00181 }
00182 }
00183
00184 void GOTO_TABLE::Build_Rec(WN *wn, WN *parent, BOOL inside_compgoto)
00185 {
00186 const OPCODE opcode = WN_opcode(wn);
00187
00188 if (opcode == OPC_BLOCK) {
00189 Set_Parent(wn, parent);
00190 WN *kid = WN_first(wn);
00191 while (kid) {
00192 Build_Rec(kid, wn, inside_compgoto);
00193 kid = WN_next(kid);
00194 }
00195 return;
00196 }
00197 if (opcode == OPC_ALTENTRY) {
00198 Set_Parent(wn, parent);
00199 }
00200
00201
00202
00203 if ((opcode == OPC_DO_LOOP) || (opcode == OPC_DO_WHILE) ||
00204 (opcode == OPC_REGION) ||
00205 (opcode == OPC_WHILE_DO) || (opcode == OPC_IF)) {
00206 Set_Parent(wn, parent);
00207 for (INT kidno = 0; kidno < WN_kid_count(wn); kidno++) {
00208 Build_Rec(WN_kid(wn, kidno), wn, inside_compgoto);
00209 }
00210 return;
00211 }
00212 if (opcode == OPC_COMPGOTO) {
00213 Set_Parent(wn, parent);
00214 for (INT kidno = 0; kidno < WN_kid_count(wn); kidno++) {
00215 Build_Rec(WN_kid(wn, kidno), wn, TRUE);
00216 }
00217 return;
00218 }
00219
00220 if ((opcode == OPC_GOTO) || (opcode == OPC_TRUEBR) ||
00221 (opcode == OPC_FALSEBR)) {
00222 Set_Parent(wn, parent);
00223 _gd.Push(GOTO_DESCRIPTOR(wn, NULL, _offset, 0, inside_compgoto));
00224 _offset++;
00225 } else if (opcode == OPC_LABEL) {
00226 Set_Parent(wn, parent);
00227 LABEL_DESCRIPTOR *ld = CXX_NEW(LABEL_DESCRIPTOR(wn, _offset), _pool);
00228 if (LABEL_kind (Label_Table[WN_label_number(wn)]) == LKIND_ASSIGNED) {
00229 _bad_label.Push(*ld);
00230 }
00231 _label_table->Enter(WN_label_number(wn), ld);
00232 _offset++;
00233 } else if (opcode == OPC_ALTENTRY) {
00234 _contains_altentry = TRUE;
00235 _altentry.Push(wn);
00236 }
00237 }
00238
00239
00240
00241
00242 void GOTO_TABLE::Backpatch()
00243 {
00244 for (INT i = 0; i<_gd.Elements(); i++) {
00245 GOTO_DESCRIPTOR *gd = &_gd.Bottom_nth(i);
00246 INT label_num = WN_label_number(gd->Goto_Wn);
00247 LABEL_DESCRIPTOR *ld = _label_table->Find(label_num);
00248 if (ld != NULL) {
00249 gd->Label_Wn = ld->Label_Wn;
00250 gd->Label_Offset = ld->Offset;
00251 }
00252 }
00253 }
00254
00255
00256 void GOTO_TABLE::Remove_Gotos()
00257 {
00258 INT goto_expanding_transformations = 0;
00259
00260 INT i;
00261 BOOL created_whiles=FALSE;
00262 for (i = _gd.Elements() - 1; i >= 0; i--) {
00263 GOTO_DESCRIPTOR *gd = &_gd.Bottom_nth(i);
00264
00265 if (gd->Label_Wn && ! WN_Label_Is_Break(gd->Label_Wn)
00266 && ! gd->Is_Compgoto) {
00267 if (Is_Truebr(gd)) {
00268 Create_Truebr(gd);
00269 }
00270 if (Can_Move_Into_Else(gd)) {
00271 Move_Into_Else(gd);
00272 }
00273 if (Goto_Is_Noop(gd)) {
00274 WN_DELETE_FromBlock(Get_Parent(gd->Goto_Wn), gd->Goto_Wn);
00275 gd->Is_Dismantled = TRUE;
00276 } else {
00277
00278
00279
00280
00281 if (Parent_Through_If(gd) && !_contains_altentry) {
00282 Move_Goto_Out(gd);
00283 goto_expanding_transformations++;
00284 }
00285 if (Sibling(gd)) {
00286 if (gd->Goto_Offset < gd->Label_Offset) {
00287 Replace_Goto_With_If(gd);
00288 } else {
00289 Replace_Goto_With_While(gd);
00290 created_whiles = TRUE;
00291 }
00292 }
00293 }
00294 }
00295 }
00296
00297 if (created_whiles) {
00298 Promote_Do_While(Func_Nd());
00299 }
00300
00301
00302 for (i = _gd.Elements() - 1; i >= 0; i--) {
00303 GOTO_DESCRIPTOR *gd = &_gd.Bottom_nth(i);
00304 if (gd->Label_Wn && !gd->Is_Dismantled) {
00305 WN *label_wn = gd->Label_Wn;
00306 WN *goto_wn = gd->Goto_Wn;
00307 WN *ancestor = Find_Common_Ancestor(label_wn, goto_wn);
00308 WN *tmp = Get_Parent(label_wn);
00309 while (tmp != ancestor) {
00310 WN *next_tmp = Get_Parent(tmp);
00311 OPCODE opcode = WN_opcode(tmp);
00312 if ((opcode == OPC_DO_LOOP) || (opcode == OPC_DO_WHILE) ||
00313 (opcode == OPC_WHILE_DO) || (opcode == OPC_IF)) {
00314 Dismantle(tmp, next_tmp);
00315 }
00316 tmp = next_tmp;
00317 }
00318 }
00319 }
00320 for (i = _bad_label.Elements() - 1; i >= 0; i--) {
00321 WN *label_wn = _bad_label.Bottom_nth(i).Label_Wn;
00322 if (label_wn) {
00323 WN *tmp = Get_Parent(label_wn);
00324 while (tmp) {
00325 WN *next_tmp = Get_Parent(tmp);
00326 OPCODE opcode = WN_opcode(tmp);
00327 if ((opcode == OPC_DO_LOOP) || (opcode == OPC_DO_WHILE) ||
00328 (opcode == OPC_WHILE_DO) || (opcode == OPC_IF)) {
00329 Dismantle(tmp, next_tmp);
00330 }
00331 tmp = next_tmp;
00332 }
00333 }
00334 }
00335 for (i = _altentry.Elements() - 1; i >= 0; i--) {
00336 WN *tmp = _altentry.Bottom_nth(i);
00337 while (tmp) {
00338 WN *next_tmp = Get_Parent(tmp);
00339 OPCODE opcode = WN_opcode(tmp);
00340 if ((opcode == OPC_DO_LOOP) || (opcode == OPC_DO_WHILE) ||
00341 (opcode == OPC_WHILE_DO) || (opcode == OPC_IF)) {
00342 Dismantle(tmp, next_tmp);
00343 }
00344 tmp = next_tmp;
00345 }
00346 }
00347 }
00348
00349
00350 WN *GOTO_TABLE::Find_Common_Ancestor(WN *wn1, WN *wn2)
00351 {
00352 INT l1 = Find_Level(wn1);
00353 INT l2 = Find_Level(wn2);
00354
00355 if (l1 > l2) {
00356 for (INT i = 0; i < l1 - l2; i++) {
00357 wn1 = Get_Parent(wn1);
00358 }
00359 } else if (l2 > l1) {
00360 for (INT i = 0; i < l2 - l1; i++) {
00361 wn2 = Get_Parent(wn2);
00362 }
00363 }
00364 while (wn1 != wn2) {
00365 wn1 = Get_Parent(wn1);
00366 wn2 = Get_Parent(wn2);
00367 }
00368 return wn1;
00369 }
00370
00371 INT GOTO_TABLE::Find_Level(WN *wn)
00372 {
00373 INT result = 0;
00374 while ((wn = Get_Parent(wn)) != 0) {
00375 result++;
00376 }
00377 return result;
00378 }
00379
00380
00381
00382
00383
00384
00385
00386
00387 BOOL GOTO_TABLE::Goto_Is_Noop(GOTO_DESCRIPTOR *gd) const
00388 {
00389 WN *goto_wn = gd->Goto_Wn;
00390
00391 if (WN_next(goto_wn) == gd->Label_Wn) {
00392 return TRUE;
00393 }
00394
00395 WN *tmp = goto_wn;
00396 WN *grand_parent = goto_wn;
00397 while (!WN_next(tmp)) {
00398 tmp = grand_parent;
00399 WN *parent = Get_Parent(tmp);
00400 if (WN_opcode(parent) != OPC_BLOCK) {
00401 return FALSE;
00402 }
00403 grand_parent = Get_Parent(parent);
00404 if (WN_opcode(grand_parent) != OPC_IF) {
00405 return FALSE;
00406 }
00407 }
00408 return (WN_next(tmp) == gd->Label_Wn);
00409 }
00410
00411
00412 BOOL GOTO_TABLE::Ancestor_Through_If(GOTO_DESCRIPTOR *gd)
00413 {
00414 INT goto_level = Find_Level(gd->Goto_Wn);
00415 INT label_level = Find_Level(gd->Label_Wn);
00416 if (goto_level <= label_level) {
00417 return(FALSE);
00418 }
00419
00420 WN *tmp = gd->Goto_Wn;
00421 for (INT i=goto_level; i>label_level; i--) {
00422 tmp = Get_Parent(tmp);
00423 const OPCODE opcode = WN_opcode(tmp);
00424 if ((opcode != OPC_BLOCK) && (opcode != OPC_IF)) {
00425 return(FALSE);
00426 }
00427 }
00428
00429 return (Get_Parent(tmp) == Get_Parent(gd->Label_Wn));
00430 }
00431
00432
00433 BOOL GOTO_TABLE::Parent_Through_If(GOTO_DESCRIPTOR *gd)
00434 {
00435 INT goto_level = Find_Level(gd->Goto_Wn);
00436 INT label_level = Find_Level(gd->Label_Wn);
00437 if (goto_level != label_level+2) {
00438 return(FALSE);
00439 }
00440
00441 WN *tmp = Get_Parent(gd->Goto_Wn);
00442 OPCODE opcode = WN_opcode(tmp);
00443 if (opcode != OPC_BLOCK) return FALSE;
00444 tmp = Get_Parent(tmp);
00445 opcode = WN_opcode(tmp);
00446 if (opcode != OPC_IF) return FALSE;
00447 return (Get_Parent(tmp) == Get_Parent(gd->Label_Wn));
00448 }
00449
00450
00451 BOOL GOTO_TABLE::Sibling(GOTO_DESCRIPTOR *gd)
00452 {
00453 return (Get_Parent(gd->Label_Wn) == Get_Parent(gd->Goto_Wn));
00454 }
00455
00456
00457
00458 BOOL GOTO_TABLE::Is_Truebr(GOTO_DESCRIPTOR *gd)
00459 {
00460 WN *wn = gd->Goto_Wn;
00461 if (WN_opcode(wn) != OPC_GOTO) {
00462 return FALSE;
00463 }
00464 WN *parent = Get_Parent(wn);
00465 if (WN_opcode(parent) != OPC_BLOCK) {
00466 return FALSE;
00467 }
00468 WN *grand_parent = Get_Parent(parent);
00469 if (WN_opcode(grand_parent) != OPC_IF) {
00470 return FALSE;
00471 }
00472
00473 WN *wn_else = WN_else(grand_parent);
00474 if (WN_first(wn_else)) {
00475 return FALSE;
00476 }
00477
00478 if (wn != WN_last(parent) || wn != WN_first(parent)) {
00479 return FALSE;
00480 }
00481 return TRUE;
00482 }
00483
00484 void GOTO_TABLE::Create_Truebr(GOTO_DESCRIPTOR *gd)
00485 {
00486 WN *block_wn = Get_Parent(gd->Goto_Wn);
00487 WN *if_wn = Get_Parent(block_wn);
00488 WN *if_parent = Get_Parent(if_wn);
00489 WN *if_test = WN_if_test(if_wn);
00490
00491 WN *truebr = WN_CreateTruebr(WN_label_number(gd->Goto_Wn),if_test);
00492 WN_Set_Linenum(truebr, WN_Get_Linenum(gd->Goto_Wn));
00493 WN_INSERT_BlockBefore(if_parent,if_wn,truebr);
00494 gd->Goto_Wn = truebr;
00495 if (Cur_PU_Feedback) {
00496 Cur_PU_Feedback->FB_lower_branch( if_wn, truebr );
00497 }
00498 Set_Parent(truebr, if_parent);
00499 WN_if_test(if_wn) = NULL;
00500 WN_DELETE_FromBlock(if_parent,if_wn);
00501 }
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512 BOOL GOTO_TABLE::Can_Move_Into_Else(GOTO_DESCRIPTOR *gd)
00513 {
00514 WN *wn = gd->Goto_Wn;
00515 if (WN_opcode(wn) != OPC_GOTO) {
00516 return FALSE;
00517 }
00518 WN *parent = Get_Parent(wn);
00519 if (WN_opcode(parent) != OPC_BLOCK) {
00520 return FALSE;
00521 }
00522 WN *grand_parent = Get_Parent(parent);
00523 if (WN_opcode(grand_parent) != OPC_IF) {
00524 return FALSE;
00525 }
00526 if (wn != WN_last(parent)) {
00527 return FALSE;
00528 }
00529 return TRUE;
00530 }
00531
00532 void GOTO_TABLE::Move_Into_Else(GOTO_DESCRIPTOR *gd)
00533 {
00534 WN *block_wn = Get_Parent(gd->Goto_Wn);
00535 WN *if_wn = Get_Parent(block_wn);
00536 WN *if_parent = Get_Parent(if_wn);
00537
00538 WN *insert_block = NULL;
00539 if (block_wn == WN_then(if_wn)) {
00540 insert_block = WN_else(if_wn);
00541 } else {
00542 insert_block = WN_then(if_wn);
00543 }
00544
00545 WN *label_wn = gd->Label_Wn;
00546 while (WN_next(if_wn) && (WN_next(if_wn) != label_wn)) {
00547 WN *tmp = WN_EXTRACT_FromBlock(if_parent, WN_next(if_wn));
00548 WN_INSERT_BlockBefore(insert_block, NULL, tmp);
00549 Set_Parent(tmp, insert_block);
00550 }
00551 }
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561 static WN *
00562 Find_last_arg_copy( WN *func_body )
00563 {
00564 Is_True( WN_opcode(func_body) == OPC_BLOCK,
00565 ("Find_last_arg_copy: function body is not block") );
00566
00567 WN *last_arg_copy = NULL;
00568 for ( WN *stmt = WN_first(func_body); stmt; stmt = WN_next(stmt) ) {
00569 const OPERATOR opr = WN_operator(stmt);
00570 if ( opr != OPR_STID )
00571 break;
00572
00573 WN *rhs = WN_kid0(stmt);
00574 OPERATOR rhs_opr = WN_operator(rhs);
00575
00576
00577 if ( rhs_opr == OPR_CVTL || rhs_opr == OPR_CVT ) {
00578 rhs = WN_kid0(rhs);
00579 rhs_opr = WN_operator(rhs);
00580 }
00581
00582 if ( rhs_opr != OPR_LDID )
00583 break;
00584
00585 if ( ST_class(WN_st(rhs)) != CLASS_PREG ||
00586 !Preg_Is_Dedicated(WN_load_offset(rhs)) )
00587 break;
00588
00589
00590
00591
00592 last_arg_copy = stmt;
00593 }
00594
00595 return last_arg_copy;
00596 }
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613 void GOTO_TABLE::Move_Goto_Out(GOTO_DESCRIPTOR *gd)
00614 {
00615 WN *goto_wn = gd->Goto_Wn;
00616 WN *parent = Get_Parent(goto_wn);
00617 INT64 goto_line = WN_Get_Linenum(goto_wn);
00618
00619
00620 WN *if_wn = parent;
00621 while (WN_opcode(if_wn) != OPC_IF) {
00622 if_wn = Get_Parent(if_wn);
00623 }
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633 char new_var[15];
00634 INT label_name_num = WN_label_number(goto_wn) % 9999999;
00635 sprintf(new_var, ".goto_L%d", label_name_num);
00636 ST *st = MTYPE_To_PREG(Boolean_type);
00637 WN_OFFSET offset = Create_Preg(Boolean_type, new_var);
00638
00639
00640 WN *func_body = WN_func_body(_func_nd);
00641 WN *init_val = WN_CreateIntconst(OPCODE_make_op(OPR_INTCONST, Boolean_type,
00642 MTYPE_V), 0);
00643 WN *stid = WN_CreateStid(OPCODE_make_op(OPR_STID, MTYPE_V, Boolean_type),
00644 offset, st, Be_Type_Tbl(Boolean_type), init_val);
00645 WN_Set_Linenum(stid, WN_Get_Linenum(func_body));
00646
00647
00648 WN *last_arg_copy = Find_last_arg_copy( func_body );
00649 WN_INSERT_BlockAfter(func_body, last_arg_copy, stid);
00650
00651
00652 init_val = WN_CreateIntconst(OPCODE_make_op(OPR_INTCONST, Boolean_type,
00653 MTYPE_V), 0);
00654 stid = WN_CreateStid(OPCODE_make_op(OPR_STID, MTYPE_V, Boolean_type),
00655 offset, st, Be_Type_Tbl(Boolean_type), init_val);
00656 WN_Set_Linenum(stid, WN_Get_Linenum(gd->Label_Wn));
00657 WN_INSERT_BlockAfter(Get_Parent(gd->Label_Wn), gd->Label_Wn, stid);
00658
00659
00660
00661
00662 WN *tmp = Get_Parent(if_wn);
00663 while (tmp && (WN_opcode(tmp) != OPC_REGION)) {
00664 tmp = Get_Parent(tmp);
00665 }
00666 if (tmp) {
00667 init_val = WN_CreateIntconst(OPCODE_make_op(OPR_INTCONST, Boolean_type,
00668 MTYPE_V), 0);
00669 stid = WN_CreateStid(OPCODE_make_op(OPR_STID, MTYPE_V, Boolean_type),
00670 offset, st, Be_Type_Tbl(Boolean_type), init_val);
00671 WN_Set_Linenum(stid, WN_Get_Linenum(gd->Label_Wn));
00672 WN_INSERT_BlockAfter(WN_region_body(tmp), NULL, stid);
00673 }
00674
00675
00676 const OPCODE opcode = WN_opcode(goto_wn);
00677 WN *val;
00678 if (opcode == OPC_GOTO) {
00679 val = WN_CreateIntconst(OPCODE_make_op(OPR_INTCONST, Boolean_type,
00680 MTYPE_V), 1);
00681 } else if (opcode == OPC_TRUEBR) {
00682 val = WN_kid0(goto_wn);
00683 } else {
00684 val = WN_CreateExp1(OPCODE_make_op(OPR_LNOT, Boolean_type, MTYPE_V),
00685 WN_kid0(goto_wn));
00686 }
00687 stid = WN_CreateStid(OPCODE_make_op(OPR_STID, MTYPE_V, Boolean_type),
00688 offset, st, Be_Type_Tbl(Boolean_type), val);
00689 WN_INSERT_BlockBefore(parent, goto_wn, stid);
00690 WN_Set_Linenum(stid, goto_line);
00691
00692
00693
00694
00695
00696 WN *new_if = NULL;
00697 if (WN_next(goto_wn)) {
00698 WN *then_block = WN_CreateBlock();
00699 WN *else_block = WN_CreateBlock();
00700 WN_Set_Linenum(then_block, goto_line);
00701 WN_Set_Linenum(else_block, goto_line);
00702 WN *next_wn=NULL;
00703 for (WN *wn = WN_next(goto_wn); wn; wn = next_wn) {
00704 next_wn = WN_next(wn);
00705 wn = WN_EXTRACT_FromBlock(parent, wn);
00706 WN_INSERT_BlockBefore(then_block, NULL, wn);
00707 if (Get_Parent(wn)) Set_Parent(wn, then_block);
00708 }
00709 WN *ldid = WN_CreateLdid(OPCODE_make_op(OPR_LDID, Boolean_type,
00710 Boolean_type),
00711 offset, st, Be_Type_Tbl(Boolean_type));
00712 WN *cond = WN_CreateExp1(OPCODE_make_op(OPR_LNOT, Boolean_type, MTYPE_V),
00713 ldid);
00714 new_if = WN_CreateIf(cond, then_block, else_block);
00715 Set_Parent(then_block, new_if);
00716 Set_Parent(else_block, new_if);
00717 Set_Parent(new_if, parent);
00718 WN_INSERT_BlockAfter(parent, goto_wn, new_if);
00719 WN_Set_Linenum(new_if, goto_line);
00720 }
00721 WN_EXTRACT_FromBlock(parent, goto_wn);
00722
00723
00724
00725
00726
00727
00728 WN *ldid = WN_CreateLdid(OPCODE_make_op(OPR_LDID, Boolean_type,
00729 Boolean_type),
00730 offset, st, Be_Type_Tbl(Boolean_type));
00731 WN *condbr = WN_CreateTruebr(WN_label_number(goto_wn), ldid);
00732 WN_INSERT_BlockAfter(Get_Parent(if_wn), if_wn, condbr);
00733 Set_Parent(condbr, Get_Parent(if_wn));
00734 gd->Goto_Wn = condbr;
00735 WN_Set_Linenum(condbr, goto_line);
00736 if (Cur_PU_Feedback) {
00737 Cur_PU_Feedback->FB_move_goto_out(goto_wn, new_if, condbr);
00738 }
00739 WN_Delete(goto_wn);
00740 }
00741
00742
00743
00744
00745
00746
00747
00748 void GOTO_TABLE::Replace_Goto_With_If(GOTO_DESCRIPTOR *gd)
00749 {
00750 WN *goto_wn = gd->Goto_Wn;
00751 WN *label_wn = gd->Label_Wn;
00752 WN *parent = Get_Parent(goto_wn);
00753
00754 if (WN_next(goto_wn) == label_wn) {
00755 WN_DELETE_FromBlock(parent, goto_wn);
00756 gd->Is_Dismantled = TRUE;
00757 return;
00758 }
00759
00760 const OPCODE goto_opcode = WN_opcode(goto_wn);
00761 WN *cond;
00762 if (goto_opcode == OPC_GOTO) {
00763
00764
00765 return;
00766
00767
00768 } else if (goto_opcode == OPC_TRUEBR) {
00769 cond = WN_CreateExp1(OPCODE_make_op(OPR_LNOT, Boolean_type, MTYPE_V),
00770 WN_kid0(goto_wn));
00771 } else {
00772 Is_True(goto_opcode == OPC_FALSEBR,
00773 ("Unknown goto in Replace_Goto_With_If"));
00774 cond = WN_kid0(goto_wn);
00775 }
00776
00777 WN *then_block = WN_CreateBlock();
00778 WN *else_block = WN_CreateBlock();
00779 WN_Set_Linenum(then_block, WN_Get_Linenum(goto_wn));
00780 WN_Set_Linenum(else_block, WN_Get_Linenum(goto_wn));
00781
00782
00783 WN *next_wn = NULL;
00784 for (WN *wn = WN_next(goto_wn); wn != label_wn; wn = next_wn) {
00785 next_wn = WN_next(wn);
00786 wn = WN_EXTRACT_FromBlock(parent, wn);
00787 WN_INSERT_BlockBefore(then_block, NULL, wn);
00788 if (Get_Parent(wn)) Set_Parent(wn, then_block);
00789 }
00790
00791 WN *if_wn = WN_CreateIf(cond, then_block, else_block);
00792 Set_Parent(then_block, if_wn);
00793 Set_Parent(else_block, if_wn);
00794 Set_Parent(if_wn, parent);
00795 WN_Set_Linenum(if_wn, WN_Get_Linenum(goto_wn));
00796
00797 WN_INSERT_BlockAfter(parent, goto_wn, if_wn);
00798 WN_EXTRACT_FromBlock(parent, goto_wn);
00799 gd->Is_Dismantled = TRUE;
00800
00801 if (Cur_PU_Feedback) {
00802 Cur_PU_Feedback->FB_convert_goto_to_if(goto_wn, if_wn);
00803 }
00804 WN_Delete(goto_wn);
00805 }
00806
00807
00808 static BOOL Equivalent(WN *wn1, WN *wn2)
00809 {
00810 if (!WN_Equiv(wn1, wn2)) return FALSE;
00811 for (INT i=0; i<WN_kid_count(wn1); i++) {
00812 if (!Equivalent(WN_kid(wn1,i), WN_kid(wn2,i))) return FALSE;
00813 }
00814 return TRUE;
00815 }
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825 void GOTO_TABLE::Promote_Do_While(WN *wn)
00826 {
00827 OPCODE opcode = WN_opcode(wn);
00828 if (opcode == OPC_BLOCK) {
00829 WN *kid = WN_first(wn);
00830 while (kid) {
00831 WN *next_kid = WN_next(kid);
00832 Promote_Do_While(kid);
00833 kid = next_kid;
00834 }
00835 } else {
00836 if (OPCODE_is_scf(opcode)) {
00837 if (opcode == OPC_IF) {
00838 if (WN_first(WN_else(wn)) == NULL) {
00839 if (WN_first(WN_then(wn)) && (WN_first(WN_then(wn)) == WN_last(WN_then(wn)))) {
00840 if (WN_opcode(WN_first(WN_then(wn))) == OPC_DO_WHILE) {
00841 WN *while_wn = WN_first(WN_then(wn));
00842 if (Equivalent(WN_if_test(wn), WN_while_test(while_wn))) {
00843 WN_set_opcode(while_wn, OPC_WHILE_DO);
00844 WN *parent = Get_Parent(wn);
00845 WN_INSERT_BlockBefore(parent, wn, while_wn);
00846 Set_Parent(while_wn, parent);
00847 WN_first(WN_then(wn)) = NULL;
00848 WN_DELETE_FromBlock(parent, wn);
00849 Promote_Do_While(while_wn);
00850 return;
00851 }
00852 }
00853 }
00854 }
00855 }
00856 }
00857 for (INT kidno=0; kidno<WN_kid_count(wn); kidno++) {
00858 Promote_Do_While(WN_kid(wn,kidno));
00859 }
00860 }
00861 }
00862
00863
00864
00865
00866
00867
00868
00869 void GOTO_TABLE::Replace_Goto_With_While(GOTO_DESCRIPTOR *gd)
00870 {
00871 WN *goto_wn = gd->Goto_Wn;
00872 WN *label_wn = gd->Label_Wn;
00873 WN *parent = Get_Parent(goto_wn);
00874
00875
00876 const OPCODE goto_opcode = WN_opcode(goto_wn);
00877 WN *cond;
00878 if (goto_opcode == OPC_GOTO) {
00879 cond = WN_CreateIntconst(OPCODE_make_op(OPR_INTCONST, Boolean_type,
00880 MTYPE_V), 1);
00881 } else if (goto_opcode == OPC_FALSEBR) {
00882 cond = WN_CreateExp1(OPCODE_make_op(OPR_LNOT, Boolean_type, MTYPE_V),
00883 WN_kid0(goto_wn));
00884 } else {
00885 Is_True(goto_opcode == OPC_TRUEBR,
00886 ("Unknown goto in Replace_Goto_With_While"));
00887 cond = WN_kid0(goto_wn);
00888 }
00889
00890 WN *block = WN_CreateBlock();
00891 WN_Set_Linenum(block, WN_Get_Linenum(goto_wn));
00892
00893
00894 WN *next_wn = NULL;
00895 for (WN *wn = label_wn; wn != goto_wn; wn = next_wn) {
00896 next_wn = WN_next(wn);
00897 wn = WN_EXTRACT_FromBlock(parent, wn);
00898 WN_INSERT_BlockBefore(block, NULL, wn);
00899 if (Get_Parent(wn)) Set_Parent(wn, block);
00900 }
00901
00902
00903 WN *while_wn = WN_CreateDoWhile(cond, block);
00904 Set_Parent(block, while_wn);
00905 Set_Parent(while_wn, parent);
00906 WN_Set_Linenum(while_wn, WN_Get_Linenum(goto_wn));
00907
00908 WN_INSERT_BlockAfter(parent, goto_wn, while_wn);
00909 WN_EXTRACT_FromBlock(parent, goto_wn);
00910 gd->Is_Dismantled = TRUE;
00911
00912 if (Cur_PU_Feedback) {
00913 Cur_PU_Feedback->FB_convert_goto_to_loop(goto_wn, while_wn);
00914 }
00915 WN_Delete(goto_wn);
00916 }
00917
00918 void GOTO_TABLE::Print(FILE *fp)
00919 {
00920 fprintf(fp, "Printing a GOTO_TABLE\n");
00921 for (INT i = 0; i < _gd.Elements(); i++) {
00922 GOTO_DESCRIPTOR *gd = &_gd.Bottom_nth(i);
00923 fprintf(fp, "A goto with: \n");
00924 fprintf(fp, " offset = %d \n", gd->Goto_Offset);
00925 fprintf(fp, "to label = %d with \n", WN_label_number(gd->Goto_Wn));
00926 fprintf(fp, " offset = %d \n", gd->Label_Offset);
00927 fprintf(fp, "\n");
00928 }
00929 }
00930
00931
00932
00933 void GOTO_TABLE::Dismantle(WN *bad, WN *parent)
00934 {
00935 WN *prev = WN_prev(bad);
00936 WN *block = WN_CreateBlock();
00937 WN_EXTRACT_FromBlock(parent, bad);
00938 WN *scf_wn = lower_scf_non_recursive(block, bad,
00939 LOWER_SCF | LOWER_FREQUENCY_MAPS);
00940 WN_INSERT_BlockLast(block, scf_wn);
00941
00942
00943 while (WN_last(block)) {
00944 WN *element = WN_EXTRACT_FromBlock(block, WN_last(block));
00945 WN_INSERT_BlockAfter(parent, prev, element);
00946 Fixup_Parents(element, parent);
00947 }
00948 WN_Delete(block);
00949 }
00950