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 #include "lwn_util.h"
00037 #include "lnoutils.h"
00038 #include "lnopt_main.h"
00039 #include "symtab_utils.h"
00040 #include "eliminate.h"
00041
00042
00043
00044
00045
00046
00047 GOTO_LIST::GOTO_LIST(MEM_POOL* mem_pool)
00048 {
00049 _mem_pool = mem_pool;
00050 _label = NULL;
00051 _label_number = -1;
00052 _gotos = CXX_NEW(DYN_ARRAY<WN*>(mem_pool), mem_pool);
00053 }
00054
00055
00056
00057
00058
00059
00060
00061 void GOTO_LIST::Add_Goto_Unique(WN* wn)
00062 {
00063 for (INT i = 0; i <= _gotos->Lastidx(); i++)
00064 if ((*_gotos)[i] == wn)
00065 return;
00066 _gotos->AddElement(wn);
00067 }
00068
00069
00070
00071
00072
00073
00074 void GOTO_LIST::Print(FILE* fp, INT increment)
00075 {
00076 fprintf(fp, "LABEL #%d: (0x%p): \n", _label_number, _label);
00077 for (INT i = 0; i < Elements(); i++) {
00078 for (INT j = 0; j < increment; j++)
00079 fprintf(fp, " ");
00080 WN* wn_goto = Goto(i);
00081 INT label_number = WN_label_number(wn_goto);
00082 const char* goto_type = WN_operator(wn_goto) == OPR_GOTO ? "GOTO"
00083 : WN_operator(wn_goto) == OPR_TRUEBR ? "TRUEBR"
00084 : WN_operator(wn_goto) == OPR_FALSEBR ? "FALSEBR"
00085 : "UNKNOWN";
00086 fprintf(fp, "[%d] %s #%d (0x%p)\n", i, goto_type, label_number, wn_goto);
00087 }
00088 }
00089
00090
00091
00092
00093
00094
00095 LABEL_LIST::LABEL_LIST(MEM_POOL* mem_pool)
00096 {
00097 _mem_pool = mem_pool;
00098 _has_assigned_goto = FALSE;
00099 _labels = CXX_NEW(DYN_ARRAY<GOTO_LIST>(mem_pool), mem_pool);
00100 }
00101
00102
00103
00104
00105
00106
00107
00108 void LABEL_LIST::Label_List_Label_Traverse(MEM_POOL* mem_pool,
00109 WN* wn_tree)
00110 {
00111 if (WN_operator(wn_tree) == OPR_LABEL)
00112 Add_Label_Unique(wn_tree);
00113
00114 if (WN_operator(wn_tree) == OPR_BLOCK) {
00115 for (WN* wn = WN_first(wn_tree); wn != NULL; wn = WN_next(wn)) {
00116 Label_List_Label_Traverse(mem_pool, wn);
00117 }
00118 } else {
00119 for (INT i = 0; i < WN_kid_count(wn_tree); i++)
00120 Label_List_Label_Traverse(mem_pool, WN_kid(wn_tree, i));
00121 }
00122 }
00123
00124
00125
00126
00127
00128
00129
00130 void LABEL_LIST::Label_List_Goto_Traverse(MEM_POOL* mem_pool,
00131 WN* wn_tree)
00132 {
00133 switch (WN_operator(wn_tree)) {
00134 case OPR_GOTO:
00135 case OPR_FALSEBR:
00136 case OPR_TRUEBR:
00137 Add_Goto_Unique(wn_tree);
00138 break;
00139 case OPR_AGOTO:
00140 _has_assigned_goto = TRUE;
00141 break;
00142 }
00143
00144 if (WN_operator(wn_tree) == OPR_BLOCK) {
00145 for (WN* wn = WN_first(wn_tree); wn != NULL; wn = WN_next(wn)) {
00146 Label_List_Goto_Traverse(mem_pool, wn);
00147 }
00148 } else {
00149 for (INT i = 0; i < WN_kid_count(wn_tree); i++)
00150 Label_List_Goto_Traverse(mem_pool, WN_kid(wn_tree, i));
00151 }
00152 }
00153
00154
00155
00156
00157
00158
00159
00160 LABEL_LIST::LABEL_LIST(MEM_POOL* mem_pool,
00161 WN* wn_func)
00162 {
00163 _mem_pool = mem_pool;
00164 _has_assigned_goto = FALSE;
00165 _labels = CXX_NEW(DYN_ARRAY<GOTO_LIST>(mem_pool), mem_pool);
00166 Label_List_Label_Traverse(mem_pool, wn_func);
00167 if (_labels->Elements() > 0)
00168 Label_List_Goto_Traverse(mem_pool, wn_func);
00169 }
00170
00171
00172
00173
00174
00175
00176 void LABEL_LIST::Add_Label(WN* wn_label)
00177 {
00178 FmtAssert(WN_operator(wn_label) == OPR_LABEL,
00179 ("LABEL_LIST::Add_Label: Expecting a LABEL node"));
00180 GOTO_LIST* goto_list = CXX_NEW(GOTO_LIST(_mem_pool), _mem_pool);
00181 goto_list->Set_Label(wn_label);
00182 goto_list->Set_Label_Number(WN_label_number(wn_label));
00183 _labels->AddElement(*goto_list);
00184 }
00185
00186
00187
00188
00189
00190
00191
00192 void LABEL_LIST::Add_Label_Unique(WN* wn_label)
00193 {
00194 FmtAssert(WN_operator(wn_label) == OPR_LABEL,
00195 ("LABEL_LIST::Add_Label_Unique: Expecting a LABEL node"));
00196 INT label_number = WN_label_number(wn_label);
00197 for (INT i = 0; i <= _labels->Lastidx(); i++)
00198 if ((*_labels)[i].Label_Number() == label_number) {
00199 if ((*_labels)[i].Label() == NULL)
00200 (*_labels)[i].Set_Label(wn_label);
00201 return;
00202 }
00203 Add_Label(wn_label);
00204 }
00205
00206
00207
00208
00209
00210
00211
00212 void LABEL_LIST::Add_Goto_Unique(WN* wn_goto)
00213 {
00214 INT label_number = WN_label_number(wn_goto);
00215 INT i;
00216 for (i = 0; i <= _labels->Lastidx(); i++)
00217 if ((*_labels)[i].Label_Number() == label_number)
00218 break;
00219 if (i > _labels->Lastidx()) {
00220 GOTO_LIST* goto_list = CXX_NEW(GOTO_LIST(_mem_pool), _mem_pool);
00221 goto_list->Set_Label(NULL);
00222 goto_list->Set_Label_Number(label_number);
00223 _labels->AddElement(*goto_list);
00224 }
00225 (*_labels)[i].Add_Goto_Unique(wn_goto);
00226 }
00227
00228
00229
00230
00231
00232
00233
00234 GOTO_LIST* LABEL_LIST::Find_Label_Number(INT label_number)
00235 {
00236 for (INT i = 0; i < Elements(); i++)
00237 if (Label(i)->Label_Number() == label_number)
00238 return Label(i);
00239 return NULL;
00240 }
00241
00242
00243
00244
00245
00246
00247
00248 static BOOL Label_Used_In_InitV(INITV_IDX inv,
00249 LABEL_IDX label_idx)
00250 {
00251 INITV_IDX invv;
00252 switch (INITV_kind(inv)) {
00253 case INITVKIND_SYMDIFF:
00254 case INITVKIND_SYMDIFF16: {
00255 LABEL_IDX lbl_idx = INITV_lab1(inv);
00256 if (lbl_idx == label_idx)
00257 return TRUE;
00258 }
00259 break;
00260 case INITVKIND_LABEL: {
00261 LABEL_IDX lbl_idx = INITV_lab(inv);
00262 if (lbl_idx == label_idx)
00263 return TRUE;
00264 }
00265 break;
00266 case INITVKIND_BLOCK: {
00267 FOREACH_INITV(INITV_blk(inv), invv)
00268 if (Label_Used_In_InitV(invv, label_idx))
00269 return TRUE;
00270 }
00271 break;
00272 }
00273 return FALSE;
00274 }
00275
00276
00277
00278
00279
00280
00281
00282 static BOOL Label_Used_In_Init(LABEL_IDX label_idx)
00283 {
00284 INT i;
00285 INITO* ino;
00286 INITV_IDX inv;
00287 FOREACH_INITO(CURRENT_SYMTAB, ino, i)
00288 FOREACH_INITV(INITO_val(*ino), inv)
00289 if (Label_Used_In_InitV(inv, label_idx))
00290 return TRUE;
00291 return FALSE;
00292 }
00293
00294
00295
00296
00297
00298
00299 BOOL LABEL_LIST::Label_Is_Targeted_Outside_Scope(WN* wn_label)
00300 {
00301 if (Label_Used_In_Init(WN_label_number(wn_label)))
00302 return TRUE;
00303 WN* wnn = NULL;
00304 WN* wn = 0;
00305 for (wn = wn_label; wn != NULL; wn = LWN_Get_Parent(wn)) {
00306 if (WN_operator(wn) == OPR_IF || WN_operator(wn) == OPR_DO_LOOP)
00307 break;
00308 wnn = wn;
00309 }
00310 if (wn == NULL)
00311 return FALSE;
00312 WN* wn_control_label = wnn;
00313 GOTO_LIST* goto_list = Find_Label_Number(WN_label_number(wn_label));
00314 if (goto_list != NULL) {
00315 for (INT i = 0; i < goto_list->Elements(); i++) {
00316 WN* wn_goto = goto_list->Goto(i);
00317 WN* wnn = NULL;
00318 for (WN* wn = wn_goto; wn != NULL; wn = LWN_Get_Parent(wn)) {
00319 if (WN_operator(wn) == OPR_IF || WN_operator(wn) == OPR_DO_LOOP)
00320 break;
00321 wnn = wn;
00322 }
00323 if (wnn != wn_control_label)
00324 return TRUE;
00325 }
00326 }
00327 return FALSE;
00328 }
00329
00330
00331
00332
00333
00334
00335
00336 BOOL LABEL_LIST::Has_Targeted_Label(WN* wn_tree)
00337 {
00338 if (WN_operator(wn_tree) == OPR_LABEL
00339 && Label_Is_Targeted_Outside_Scope(wn_tree))
00340 return TRUE;
00341
00342 if (OPERATOR_is_expression(WN_operator(wn_tree)))
00343 return FALSE;
00344
00345 if (WN_operator(wn_tree) == OPR_BLOCK) {
00346 for (WN* wn = WN_first(wn_tree); wn != NULL; wn = WN_next(wn))
00347 if (Has_Targeted_Label(wn))
00348 return TRUE;
00349 } else {
00350 for (INT i = 0; i < WN_kid_count(wn_tree); i++)
00351 if (Has_Targeted_Label(WN_kid(wn_tree, i)))
00352 return TRUE;
00353 }
00354 return FALSE;
00355 }
00356
00357
00358
00359
00360
00361
00362 void LABEL_LIST::Print(FILE* fp, INT increment)
00363 {
00364 if (Has_Assigned_Goto())
00365 fprintf(fp, "Has Assigned Goto\n");
00366 for (INT i = 0; i < Elements(); i++) {
00367 for (INT j = 0; j < increment; j++)
00368 fprintf(fp, " ");
00369 fprintf(fp, "[%d] ", i);
00370 Label(i)->Print(fp, 4 + increment);
00371 }
00372 }
00373
00374
00375
00376
00377
00378
00379 void LABEL_LIST::Remove_Label(WN* wn_label)
00380 {
00381 LABEL_LIST* new_list =
00382 CXX_NEW(LABEL_LIST(Mem_Pool()), Mem_Pool());
00383 INT i;
00384 for (i = 0; i < Elements(); i++) {
00385 if (Label(i)->Label() != wn_label) {
00386 new_list->Add_Label_Unique(Label(i)->Label());
00387 for (INT j = 0; j < Label(i)->Elements(); j++)
00388 new_list->Add_Goto_Unique(Label(i)->Goto(j));
00389 }
00390 }
00391 _labels->Resetidx();
00392 for (i = 0; i < new_list->Elements(); i++) {
00393 Add_Label_Unique(new_list->Label(i)->Label());
00394 for (INT j = 0; j < new_list->Label(i)->Elements(); j++)
00395 Add_Goto_Unique(new_list->Label(i)->Goto(j));
00396 }
00397 }
00398
00399
00400
00401
00402
00403
00404 void LABEL_LIST::Remove_Target(WN* wn_target)
00405 {
00406 INT i;
00407 for (i = 0; i < Elements(); i++)
00408 if (Label(i)->Label_Number() == WN_label_number(wn_target))
00409 break;
00410 if (i == Elements())
00411 return;
00412 INT j;
00413 for (j = 0; j < Label(i)->Elements(); j++)
00414 if (Label(i)->Goto(j) == wn_target)
00415 break;
00416 if (j == Label(i)->Elements())
00417 return;
00418 INT bad_index = j;
00419 GOTO_LIST* new_list = CXX_NEW(GOTO_LIST(Mem_Pool()), Mem_Pool());
00420 for (j = 0; j < Label(i)->Elements(); j++)
00421 if (j != bad_index)
00422 new_list->Add_Goto_Unique(Label(i)->Goto(j));
00423 Label(i)->Reset_Targets();
00424 for (j = 0; j < new_list->Elements(); j++)
00425 Label(i)->Add_Goto_Unique(new_list->Goto(j));
00426 }
00427
00428
00429
00430
00431
00432
00433
00434 void LABEL_LIST::Remove_Tree(WN* wn_tree)
00435 {
00436 switch (WN_operator(wn_tree)) {
00437 case OPR_LABEL:
00438 Remove_Label(wn_tree);
00439 break;
00440 case OPR_GOTO:
00441 case OPR_FALSEBR:
00442 case OPR_TRUEBR:
00443 Remove_Target(wn_tree);
00444 break;
00445 }
00446
00447 if (WN_operator(wn_tree) == OPR_BLOCK) {
00448 for (WN* wn = WN_first(wn_tree); wn != NULL; wn = WN_next(wn))
00449 Remove_Tree(wn);
00450 } else {
00451 for (INT i = 0; i < WN_kid_count(wn_tree); i++)
00452 Remove_Tree(WN_kid(wn_tree, i));
00453 }
00454 }
00455