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
00042 #ifdef USE_PCH
00043 #include "common_com_pch.h"
00044 #endif
00045 #pragma hdrstop
00046 #include <stdio.h>
00047 #include <stdlib.h>
00048 #include <assert.h>
00049
00050 #include "defs.h"
00051 #include "stab.h"
00052 #include "wn.h"
00053 #include "wn_simp.h"
00054 #include "opcode.h"
00055 #include "wn_util.h"
00056 #include "ir_reader.h"
00057
00058 #ifdef BACK_END
00059 #include "region_util.h"
00060 #endif
00061
00062
00063
00064
00065 static WN_STACK *
00066 WN_InitStack (void)
00067 {
00068 WN_STACK *wns;
00069 wns = (WN_STACK *) MEM_POOL_Alloc (Malloc_Mem_Pool, sizeof(WN_STACK));
00070
00071
00072
00073 WN_STACK_size(wns) = 128;
00074 WN_STACK_stack(wns) = (WN **) MEM_POOL_Alloc (Malloc_Mem_Pool,
00075 sizeof(WN *) * 128);
00076
00077 WN_STACK_sp(wns) = WN_STACK_stack(wns);
00078 return wns;
00079 }
00080
00081
00082
00083
00084 inline WN *
00085 WN_Pop (WN_STACK *wns)
00086 {
00087 if (WN_STACK_sp(wns) == WN_STACK_stack(wns))
00088 return NULL;
00089 else
00090 return *(--WN_STACK_sp(wns));
00091 }
00092
00093
00094
00095
00096 inline void
00097 WN_Push (WN* wn, WN_STACK *wns)
00098 {
00099 *(WN_STACK_sp(wns)++) = wn;
00100 if ((WN_STACK_sp(wns) - WN_STACK_stack(wns)) == WN_STACK_size(wns)) {
00101
00102 INT size = WN_STACK_size(wns) * sizeof(WN *);
00103 WN_STACK_stack(wns) = (WN **)
00104 MEM_POOL_Realloc (Malloc_Mem_Pool, WN_STACK_stack(wns),
00105 size, size * 2);
00106 WN_STACK_sp(wns) = WN_STACK_stack(wns) + WN_STACK_size(wns);
00107 WN_STACK_size(wns) *= 2;
00108 }
00109 }
00110
00111
00112
00113
00114 static void
00115 WN_FreeStack (WN_STACK *wns)
00116 {
00117 MEM_POOL_FREE (Malloc_Mem_Pool, WN_STACK_stack(wns));
00118 MEM_POOL_FREE (Malloc_Mem_Pool, wns);
00119 }
00120
00121
00122
00123
00124
00125 extern WN_ITER* WN_WALK_TreeIter(WN *wn)
00126 {
00127 WN_ITER *wni;
00128
00129 FmtAssert(wn != 0, ("Bad tree node"));
00130 FmtAssert(WN_operator(wn) >= OPERATOR_FIRST &&
00131 WN_operator(wn) <= OPERATOR_LAST,
00132 ("Bad OPERATOR %d", WN_operator(wn)));
00133
00134 wni = (WN_ITER*) malloc(sizeof(WN_ITER));
00135 WN_ITER_wn(wni) = wn;
00136 WN_ITER_stack(wni) = WN_InitStack();
00137
00138 return wni;
00139 }
00140
00141
00142
00143
00144 extern WN_ITER* WN_WALK_SCFIter(WN *wn)
00145 {
00146 WN_ITER *wni;
00147
00148 FmtAssert(wn != 0, ("Bad tree node"));
00149 FmtAssert(WN_operator(wn) >= OPERATOR_FIRST &&
00150 WN_operator(wn) <= OPERATOR_LAST,
00151 ("Bad OPERATOR %d", WN_operator(wn)));
00152 FmtAssert(OPCODE_is_scf(WN_opcode(wn)), ("Expecting a Structured Control Flow tree node"));
00153
00154 wni = (WN_ITER*) malloc(sizeof(WN_ITER));
00155 WN_ITER_wn(wni) = wn;
00156 WN_ITER_stack(wni) = WN_InitStack();
00157
00158 return wni;
00159 }
00160
00161
00162
00163
00164
00165 extern WN_ITER* WN_WALK_StmtIter(WN *wn)
00166 {
00167 WN_ITER *wni;
00168
00169 FmtAssert(wn != 0, ("Bad tree node"));
00170 FmtAssert(WN_operator(wn) >= OPERATOR_FIRST &&
00171 WN_operator(wn) <= OPERATOR_LAST,
00172 ("Bad OPERATOR %d", WN_operator(wn)));
00173
00174
00175
00176
00177 if (OPCODE_is_scf(WN_opcode(wn)) || OPCODE_is_stmt(WN_opcode(wn)))
00178 {
00179 wni = (WN_ITER*) malloc(sizeof(WN_ITER));
00180 WN_ITER_wn(wni) = wn;
00181 WN_ITER_stack(wni) = WN_InitStack();
00182 return wni;
00183 }
00184
00185 return 0;
00186
00187 }
00188
00189
00190
00191
00192
00193 extern WN_ITER *
00194 WN_WALK_TreeNext(WN_ITER *wni)
00195 {
00196 INT i;
00197 WN *wn1;
00198
00199
00200
00201
00202
00203
00204 if (WN_ITER_wn(wni) != NULL) {
00205
00206 if (WN_operator(WN_ITER_wn(wni)) == OPR_BLOCK) {
00207 wn1 = WN_last(WN_ITER_wn(wni));
00208 while (wn1) {
00209 WN_Push(wn1, WN_ITER_stack(wni));
00210 wn1 = WN_prev(wn1);
00211 }
00212 } else {
00213
00214 for (i= WN_kid_count(WN_ITER_wn(wni))-1; i >= 0; --i) {
00215 if (WN_kid(WN_ITER_wn(wni), i) != NULL)
00216 WN_Push(WN_kid(WN_ITER_wn(wni), i), WN_ITER_stack(wni));
00217 }
00218 }
00219 }
00220 if ((WN_ITER_wn(wni) = WN_Pop(WN_ITER_stack(wni))) == NULL) {
00221 WN_FreeStack(WN_ITER_stack(wni));
00222 free(wni);
00223 return NULL;
00224 }
00225
00226 return wni;
00227 }
00228
00229
00230
00231
00232 extern WN_ITER *WN_WALK_StmtNext(WN_ITER *wni)
00233 {
00234 INT i;
00235 WN *wn1;
00236
00237
00238
00239
00240
00241
00242 if (WN_ITER_wn(wni) != NULL)
00243 {
00244
00245
00246 if (WN_operator(WN_ITER_wn(wni)) == OPR_BLOCK)
00247 {
00248 wn1 = WN_last(WN_ITER_wn(wni));
00249 while (wn1)
00250 {
00251 WN_Push(wn1, WN_ITER_stack(wni));
00252 wn1 = WN_prev(wn1);
00253 }
00254 }
00255
00256
00257 else if (OPCODE_is_scf(WN_opcode(WN_ITER_wn(wni))))
00258 {
00259 for (i= WN_kid_count(WN_ITER_wn(wni))-1; i >= 0; --i)
00260 {
00261 if (WN_kid(WN_ITER_wn(wni), i) != NULL)
00262 WN_Push(WN_kid(WN_ITER_wn(wni), i), WN_ITER_stack(wni));
00263 }
00264 }
00265 }
00266
00267 if ((WN_ITER_wn(wni) = WN_Pop(WN_ITER_stack(wni))) == NULL)
00268 {
00269 WN_FreeStack(WN_ITER_stack(wni));
00270 free(wni);
00271 return NULL;
00272 }
00273 return wni;
00274 }
00275
00276
00277
00278
00279 extern WN_ITER *WN_WALK_SCFNext(WN_ITER *wni)
00280 {
00281 INT i;
00282 WN *wn1;
00283
00284
00285
00286
00287
00288
00289 if (WN_ITER_wn(wni) != NULL)
00290 {
00291
00292
00293 if (WN_operator(WN_ITER_wn(wni)) == OPR_BLOCK)
00294 {
00295 wn1 = WN_last(WN_ITER_wn(wni));
00296 while (wn1)
00297 {
00298 if (OPCODE_is_scf(WN_opcode(wn1)))
00299 WN_Push(wn1, WN_ITER_stack(wni));
00300 wn1 = WN_prev(wn1);
00301 }
00302 }
00303
00304
00305 else if (OPCODE_is_scf(WN_opcode(WN_ITER_wn(wni))))
00306 {
00307 for (i= WN_kid_count(WN_ITER_wn(wni))-1; i >= 0; --i)
00308 {
00309 if (WN_kid(WN_ITER_wn(wni),i) != NULL) {
00310 if (OPCODE_is_scf(WN_opcode(WN_kid(WN_ITER_wn(wni), i))))
00311 {
00312 WN_Push(WN_kid(WN_ITER_wn(wni), i), WN_ITER_stack(wni));
00313 }
00314 }
00315 }
00316 }
00317 }
00318
00319 if ((WN_ITER_wn(wni) = WN_Pop(WN_ITER_stack(wni))) == NULL)
00320 {
00321 WN_FreeStack(WN_ITER_stack(wni));
00322 free(wni);
00323 return NULL;
00324 }
00325 return wni;
00326 }
00327
00328
00329
00330
00331
00332 extern void WN_WALK_Abort(WN_ITER *wni)
00333 {
00334 FmtAssert(wni != 0, ("Bad stack iterator"));
00335 if (WN_ITER_stack(wni) != NULL)
00336 {
00337 WN_FreeStack(WN_ITER_stack(wni));
00338 free(wni);
00339 }
00340 }
00341
00342
00343
00344
00345
00346 extern void WN_INSERT_BlockBefore(WN *blck, WN *wn, WN *in)
00347 {
00348 WN *node, *first, *last;
00349 BOOL done = FALSE;
00350
00351
00352 FmtAssert((in != 0), ("Bad tree node"));
00353
00354
00355 FmtAssert(OPCODE_is_stmt(WN_opcode(in)) || OPCODE_is_scf(WN_opcode(in)),
00356 ("Expecting a structured control flow node or a statement node"));
00357
00358 FmtAssert(WN_operator(blck) == OPR_BLOCK,
00359 ("Expecting a BLOCK operator"));
00360
00361
00362
00363
00364 if (wn != NULL)
00365 {
00366
00367
00368
00369
00370 if (wn != WN_last(blck))
00371 {
00372 node = WN_first(blck);
00373 if (node != wn)
00374 {
00375 while (!done && (node != NULL))
00376 {
00377 if (node == wn)
00378 done = TRUE;
00379 else
00380 node = WN_next(node);
00381 }
00382 }
00383 FmtAssert(node != NULL, ("Illegal insert block operation"));
00384 }
00385
00386
00387
00388 if (WN_opcode(in) != OPC_BLOCK )
00389 {
00390 if ((WN_prev(wn) == NULL))
00391 WN_first(blck) = in;
00392
00393
00394 WN_prev(in) = WN_prev(wn);
00395 WN_prev(wn) = in;
00396 WN_next(in) = wn;
00397 if (WN_prev(in)) WN_next(WN_prev(in)) = in;
00398 }
00399
00400 else
00401 {
00402 if (WN_first(in))
00403 {
00404 first = WN_first(in);
00405 last = WN_last(in);
00406 if ((WN_prev(wn) == NULL))
00407 WN_first(blck) = first;
00408
00409
00410 WN_prev(first) = WN_prev(wn);
00411 WN_prev(wn) = last;
00412 WN_next(last) = wn;
00413 if (WN_prev(first)) WN_next(WN_prev(first)) = first;
00414 }
00415 WN_first(in) = WN_last(in) = NULL;
00416 WN_Delete(in);
00417 }
00418 }
00419
00420
00421 else
00422 {
00423 if (WN_opcode(in) != OPC_BLOCK)
00424 {
00425 if (WN_first(blck) != NULL)
00426 {
00427 WN_prev(in) = WN_last(blck);
00428 WN_next(WN_last(blck)) = in;
00429 WN_last(blck) = in;
00430 WN_next(in) = NULL;
00431 }
00432 else
00433 {
00434 WN_last(blck) = in;
00435 WN_first(blck) = in;
00436 WN_prev(in) = WN_next(in) = NULL;
00437 }
00438 }
00439
00440 else
00441 {
00442 first = WN_first(in);
00443 last = WN_last(in);
00444 if (WN_first(in))
00445 {
00446 if (WN_first(blck) != NULL)
00447 {
00448 WN_prev(first) = WN_last(blck);
00449 WN_next(WN_last(blck)) = first;
00450 WN_last(blck) = last;
00451 WN_next(last) = NULL;
00452 }
00453 else
00454 {
00455 WN_last(blck) = last;
00456 WN_first(blck) = first;
00457 WN_prev(first) = WN_next(last) = NULL;
00458 }
00459 }
00460 WN_first(in) = WN_last(in) = NULL;
00461 WN_Delete(in);
00462 }
00463 }
00464 }
00465
00466
00467
00468
00469 extern void WN_INSERT_BlockAfter(WN *blck, WN *wn, WN *in)
00470 {
00471 WN *node, *first, *last;
00472 BOOL done = FALSE;
00473
00474
00475 FmtAssert(in != 0, ("Bad tree node"));
00476
00477
00478 FmtAssert(OPCODE_is_stmt(WN_opcode(in)) || OPCODE_is_scf(WN_opcode(in)),
00479 ("Expecting a structured control flow node or a statement node"));
00480
00481
00482 FmtAssert(WN_operator(blck) == OPR_BLOCK,
00483 ("Expecting a BLOCK"));
00484
00485
00486
00487
00488 if (wn != NULL)
00489 {
00490
00491
00492
00493
00494 if (wn != WN_last(blck))
00495 {
00496 node = WN_first(blck);
00497 if (node != wn)
00498 {
00499 while (!done && (node != NULL))
00500 {
00501 if (node == wn)
00502 done = TRUE;
00503 else
00504 node = WN_next(node);
00505 }
00506 }
00507 FmtAssert(node != NULL, ("Illegal insert block operation"));
00508 }
00509
00510
00511 if (WN_opcode(in) != OPC_BLOCK)
00512 {
00513 if (WN_next(wn) == NULL)
00514 WN_last(blck) = in;
00515
00516
00517 WN_prev(in) = wn;
00518 WN_next(in) = WN_next(wn);
00519 WN_next(wn) = in;
00520
00521 if (WN_next(in))
00522 WN_prev(WN_next(in)) = in;
00523 }
00524
00525 else
00526 {
00527 if (WN_first(in))
00528 {
00529 first = WN_first(in);
00530 last = WN_last(in);
00531 if (WN_next(wn) == NULL)
00532 WN_last(blck) = last;
00533
00534
00535 WN_prev(first) = wn;
00536 WN_next(last) = WN_next(wn);
00537 WN_next(wn) = first;
00538 if (WN_next(last))
00539 WN_prev(WN_next(last)) = last;
00540 }
00541 WN_first(in) = WN_last(in) = NULL;
00542 WN_Delete(in);
00543 }
00544 }
00545
00546
00547 else
00548 {
00549 if (WN_opcode(in) != OPC_BLOCK )
00550 {
00551
00552 if (WN_last(blck) != NULL)
00553 {
00554 WN_next(in) = WN_first(blck);
00555 WN_prev(in) = NULL;
00556 WN_prev(WN_first(blck)) = in;
00557 WN_first(blck) = in;
00558 }
00559 else
00560 {
00561 WN_last(blck) = in;
00562 WN_first(blck) = in;
00563 WN_prev(in) = WN_next(in) = NULL;
00564 }
00565 }
00566 else
00567 {
00568 first = WN_first(in);
00569 last = WN_last(in);
00570 if (WN_first(in))
00571 {
00572 if (WN_first(blck) != NULL)
00573 {
00574 WN_next(last) = WN_first(blck);
00575 WN_prev(first) = NULL;
00576 WN_prev(WN_first(blck)) = last;
00577 WN_first(blck) = first;
00578 }
00579 else
00580 {
00581 WN_last(blck) = last;
00582 WN_first(blck) = first;
00583 WN_prev(first) = WN_next(last) = NULL;
00584 }
00585 }
00586 WN_first(in) = WN_last(in) = NULL;
00587 WN_Delete(in);
00588 }
00589 }
00590 }
00591
00592
00593
00594
00595
00596 WN *
00597 WN_COPY_Tree (WN *wn)
00598 {
00599 WN *new_wn;
00600 WN *kid;
00601 OPCODE op;
00602
00603 if (wn == NULL)
00604 return NULL;
00605
00606 new_wn = WN_CopyNode (wn);
00607
00608 op = WN_opcode(wn);
00609 Is_True (OPCODE_operator(op) >= OPERATOR_FIRST &&
00610 OPCODE_operator(op) <= OPERATOR_LAST,
00611 ("Bad OPERATOR %d", OPCODE_operator(op)));
00612
00613 if (op == OPC_BLOCK) {
00614 WN *prev_kid, *new_kid;
00615
00616 new_kid = NULL;
00617 kid = WN_first(wn);
00618 if (kid) {
00619 new_kid = WN_COPY_Tree (kid);
00620 WN_prev(new_kid) = NULL;
00621 WN_first(new_wn) = new_kid;
00622 kid = WN_next(kid);
00623 prev_kid = new_kid;
00624
00625 while (kid) {
00626 new_kid = WN_COPY_Tree (kid);
00627 WN_next(prev_kid) = new_kid;
00628 WN_prev(new_kid) = prev_kid;
00629
00630 prev_kid = new_kid;
00631 kid = WN_next(kid);
00632 }
00633
00634 WN_next(new_kid) = NULL;
00635
00636 } else
00637 WN_first(new_wn) = NULL;
00638
00639 WN_last(new_wn) = new_kid;
00640
00641 } else {
00642 INT kidno;
00643 for (kidno = 0; kidno < WN_kid_count(wn); kidno++) {
00644 kid = WN_kid(wn, kidno);
00645 if (kid)
00646 WN_kid(new_wn, kidno) = WN_COPY_Tree (kid);
00647 else
00648 WN_kid(new_wn, kidno) = NULL;
00649 }
00650 }
00651
00652 return new_wn;
00653 }
00654
00655
00656 #ifdef MONGOOSE_BE
00657
00658
00659
00660 void
00661 WN_COPY_All_Maps(WN *dst, WN *src)
00662 {
00663 INT32 i;
00664 for (i = 0; i < WN_MAP_MAX; i++) {
00665 if (Current_Map_Tab->_is_used[i])
00666 WN_CopyMap(dst, i, src);
00667 }
00668 }
00669
00670
00671
00672
00673
00674 WN *
00675 WN_COPY_Tree_With_Map (WN *wn)
00676 {
00677 WN *new_wn;
00678 WN *kid;
00679 OPCODE op;
00680
00681 if (wn == NULL)
00682 return NULL;
00683
00684 new_wn = WN_CopyNode (wn);
00685 WN_COPY_All_Maps(new_wn, wn);
00686
00687 op = WN_opcode(wn);
00688 Is_True (OPCODE_operator(op) >= OPERATOR_FIRST &&
00689 OPCODE_operator(op) <= OPERATOR_LAST,
00690 ("Bad OPERATOR %d", OPCODE_operator(op)));
00691
00692 if (op == OPC_BLOCK) {
00693 WN *prev_kid, *new_kid;
00694
00695 new_kid = NULL;
00696 kid = WN_first(wn);
00697 if (kid) {
00698 new_kid = WN_COPY_Tree_With_Map (kid);
00699 WN_prev(new_kid) = NULL;
00700 WN_first(new_wn) = new_kid;
00701 kid = WN_next(kid);
00702 prev_kid = new_kid;
00703
00704 while (kid) {
00705 new_kid = WN_COPY_Tree_With_Map (kid);
00706 WN_next(prev_kid) = new_kid;
00707 WN_prev(new_kid) = prev_kid;
00708
00709 prev_kid = new_kid;
00710 kid = WN_next(kid);
00711 }
00712
00713 WN_next(new_kid) = NULL;
00714
00715 } else
00716 WN_first(new_wn) = NULL;
00717
00718 WN_last(new_wn) = new_kid;
00719
00720 } else {
00721 INT kidno;
00722 for (kidno = 0; kidno < WN_kid_count(wn); kidno++) {
00723 kid = WN_kid(wn, kidno);
00724 if (kid)
00725 WN_kid(new_wn, kidno) = WN_COPY_Tree_With_Map (kid);
00726 else
00727 WN_kid(new_wn, kidno) = NULL;
00728 }
00729 }
00730
00731 return new_wn;
00732 }
00733 #endif
00734
00735
00736
00737
00738
00739 extern void WN_DELETE_Tree(WN* tree)
00740 {
00741 WN *node;
00742 INT i;
00743
00744 if (tree) {
00745 if (WN_opcode(tree) == OPC_BLOCK) {
00746 node = WN_first(tree);
00747 while (node != NULL) {
00748 WN *next = WN_next(node);
00749 WN_DELETE_Tree (node);
00750 node = next;
00751 }
00752 } else
00753 for (i = 0; i< WN_kid_count(tree); i++)
00754 WN_DELETE_Tree(WN_kid(tree,i));
00755
00756 WN_Delete(tree);
00757 }
00758 }
00759
00760
00761
00762
00763
00764 void
00765 WN_DELETE_FromBlock (WN *blck, WN* wn)
00766 {
00767 #ifdef Is_True_On
00768 WN *node;
00769 BOOL done = FALSE;
00770 #endif
00771
00772
00773 if (wn == NULL)
00774 return;
00775
00776
00777 Is_True (OPCODE_is_stmt(WN_opcode(wn)) || OPCODE_is_scf(WN_opcode(wn)),
00778 ("Expecting a structured control flow node or a statement node"));
00779
00780 #ifdef Is_True_On
00781
00782 node = WN_first(blck);
00783 while (!done && (node != NULL)) {
00784 if (node == wn)
00785 done = TRUE;
00786 else
00787 node = WN_next(node);
00788 }
00789
00790 Is_True (node != NULL, ("Illegal delete operation"));
00791 #endif
00792
00793 if (WN_first(blck) == wn)
00794 WN_first(blck) = WN_next(wn);
00795
00796 if (WN_last(blck) == wn)
00797 WN_last(blck) = WN_prev(wn);
00798
00799
00800 if (WN_prev(wn) != NULL)
00801 WN_next(WN_prev(wn)) = WN_next(wn);
00802
00803 if (WN_next(wn) != NULL)
00804 WN_prev(WN_next(wn)) = WN_prev(wn);
00805
00806 WN_DELETE_Tree(wn);
00807 }
00808
00809
00810
00811
00812
00813 WN *WN_EXTRACT_FromBlock(WN *parent, WN *item)
00814 {
00815 Is_True(parent && WN_opcode(parent) == OPC_BLOCK,
00816 ("WN_Extract_FromBlock: parent not a block"));
00817 Is_True(item, ("WN_Extract_FromBlock: null item"));
00818
00819 #ifdef Is_True_On
00820 {
00821 WN *tmp;
00822 for (tmp = WN_first(parent); tmp && tmp != item; tmp = WN_next(tmp))
00823 ;
00824 Is_True(tmp == item, ("WN_Extract_FromBlock: item not on parent's list"));
00825 }
00826 #endif
00827
00828 if (WN_first(parent) == item)
00829 WN_first(parent) = WN_next(item);
00830 else
00831 WN_next(WN_prev(item)) = WN_next(item);
00832
00833 if (WN_last(parent) == item)
00834 WN_last(parent) = WN_prev(item);
00835 else
00836 WN_prev(WN_next(item)) = WN_prev(item);
00837
00838 WN_prev(item) = NULL;
00839 WN_next(item) = NULL;
00840 return item;
00841 }
00842
00843
00844
00845
00846 WN *WN_EXTRACT_ItemsFromBlock(WN *parent, WN *first_item, WN *last_item)
00847 {
00848 Is_True(parent && WN_opcode(parent) == OPC_BLOCK,
00849 ("WN_Extract_FromBlock: parent not a block"));
00850 Is_True(first_item, ("WN_Extract_FromBlock: null item"));
00851 Is_True(last_item, ("WN_Extract_FromBlock: null item"));
00852
00853 if (first_item == last_item)
00854 return WN_EXTRACT_FromBlock (parent, first_item);
00855
00856 #ifdef Is_True_On
00857 {
00858 WN *tmp;
00859 for (tmp = WN_first(parent); tmp && tmp != first_item; tmp = WN_next(tmp))
00860 ;
00861 Is_True(tmp == first_item, ("WN_Extract_ItemsFromBlock: item not on parent's list"));
00862 }
00863 #endif
00864
00865 if (WN_first(parent) == first_item)
00866 WN_first(parent) = WN_next(last_item);
00867 else
00868 WN_next(WN_prev(first_item)) = WN_next(last_item);
00869
00870 if (WN_last(parent) == last_item)
00871 WN_last(parent) = WN_prev(first_item);
00872 else
00873 WN_prev(WN_next(last_item)) = WN_prev(first_item);
00874
00875 WN_prev(first_item) = NULL;
00876 WN_next(last_item) = NULL;
00877
00878 return first_item;
00879 }
00880
00881
00882
00883
00884
00885
00886
00887
00888
00889
00890 static void
00891 wn_loop_get_st_ofst (const WN *var, ST_IDX& var_st, WN_OFFSET& var_offset)
00892 {
00893 if ( WN_opcode(var) == OPC_IDNAME ) {
00894 var_st = WN_st_idx(var);
00895 var_offset = WN_idname_offset(var);
00896 return;
00897 } else {
00898 const OPERATOR var_opr = WN_operator(var);
00899 if ( var_opr == OPR_LDID ) {
00900 var_st = WN_st_idx(var);
00901 var_offset = WN_load_offset(var);
00902 return;
00903 }
00904 if ( var_opr == OPR_STID || var_opr == OPR_PSTID) {
00905 var_st = WN_st_idx(var);
00906 var_offset = WN_store_offset(var);
00907 return;
00908 }
00909 }
00910
00911 var_st = 0;
00912 var_offset = 0;
00913 }
00914
00915
00916
00917
00918
00919 static BOOL
00920 wn_loop_ref_matches_var (const WN *ref, ST_IDX st, WN_OFFSET ofst)
00921 {
00922 ST_IDX ref_st;
00923 WN_OFFSET ref_ofst;
00924
00925 wn_loop_get_st_ofst( ref, ref_st, ref_ofst );
00926 return ( ref_st == st && ref_ofst == ofst );
00927 }
00928
00929
00930
00931
00932
00933 static OPCODE wn_loop_reverse_compare( OPCODE comparison )
00934 {
00935 OPERATOR compare_opr = OPCODE_operator(comparison);
00936 TYPE_ID compare_desc = OPCODE_desc(comparison);
00937 TYPE_ID compare_rtype = OPCODE_rtype(comparison);
00938
00939 switch ( compare_opr ) {
00940 case OPR_LT : return OPCODE_make_op(OPR_GT,compare_rtype,compare_desc);
00941 case OPR_LE : return OPCODE_make_op(OPR_GE,compare_rtype,compare_desc);
00942 case OPR_EQ : return OPCODE_make_op(OPR_EQ,compare_rtype,compare_desc);
00943 case OPR_NE : return OPCODE_make_op(OPR_NE,compare_rtype,compare_desc);
00944 case OPR_GE : return OPCODE_make_op(OPR_LE,compare_rtype,compare_desc);
00945 case OPR_GT : return OPCODE_make_op(OPR_LT,compare_rtype,compare_desc);
00946 default:
00947 FmtAssert( FALSE,
00948 ("wn_loop_reverse_compare: not a comparison operator") );
00949 return (OPCODE)0;
00950 }
00951 }
00952
00953
00954
00955
00956
00957
00958 extern WN *WN_LOOP_InductionVariable(const WN *loop)
00959 {
00960
00961
00962
00963
00964 if ( WN_opcode(loop) != OPC_DO_LOOP )
00965 return NULL;
00966
00967 return WN_index(loop);
00968 }
00969
00970
00971
00972
00973
00974
00975
00976
00977 extern WN *WN_LOOP_LowerBound( const WN *loop )
00978 {
00979 WN *iv;
00980 ST_IDX iv_st;
00981 WN_OFFSET iv_ofst;
00982 WN *start;
00983 OPERATOR start_opr;
00984
00985
00986
00987
00988 iv = WN_LOOP_InductionVariable( loop );
00989 if ( iv == NULL )
00990 return NULL;
00991 wn_loop_get_st_ofst( iv, iv_st, iv_ofst );
00992 if ( iv_st == 0 )
00993 return NULL;
00994
00995 start = WN_start(loop);
00996 start_opr = WN_operator(start);
00997 if ( start_opr == OPR_STID || start_opr == OPR_PSTID) {
00998
00999 if ( WN_st_idx(start) == iv_st && WN_store_offset(start) == iv_ofst )
01000 return WN_kid0(start);
01001 }
01002
01003
01004 return NULL;
01005 }
01006
01007
01008
01009
01010
01011
01012
01013
01014
01015
01016
01017
01018
01019 extern WN *WN_LOOP_UpperBound( const WN *loop, OPCODE *compare )
01020 {
01021 WN *iv;
01022 ST_IDX iv_st;
01023 WN_OFFSET iv_ofst;
01024 WN *end;
01025 OPCODE end_opc;
01026
01027
01028
01029
01030 iv = WN_LOOP_InductionVariable( loop );
01031 if ( iv == NULL )
01032 return NULL;
01033 wn_loop_get_st_ofst( iv, iv_st, iv_ofst );
01034 if ( iv_st == 0 )
01035 return NULL;
01036
01037
01038
01039
01040 end = WN_end(loop);
01041 end_opc = WN_opcode(end);
01042 if ( ! OPCODE_is_compare(end_opc) )
01043 return NULL;
01044
01045
01046 if ( wn_loop_ref_matches_var( WN_kid0(end), iv_st, iv_ofst ) ) {
01047 *compare = end_opc;
01048 return WN_kid1(end);
01049 }
01050 else if ( wn_loop_ref_matches_var( WN_kid1(end), iv_st, iv_ofst ) ) {
01051 *compare = wn_loop_reverse_compare( end_opc );
01052 return WN_kid0(end);
01053 }
01054
01055
01056 *compare = OPCODE_UNKNOWN;
01057 return NULL;
01058 }
01059
01060
01061
01062
01063
01064
01065
01066
01067 extern WN *WN_LOOP_Increment( const WN *loop, BOOL *is_incr )
01068 {
01069 WN *iv;
01070 ST_IDX iv_st;
01071 WN_OFFSET iv_ofst;
01072 WN *step;
01073 OPERATOR step_opr;
01074 WN *store_val;
01075 OPERATOR store_opr;
01076
01077
01078
01079
01080 iv = WN_LOOP_InductionVariable( loop );
01081 if ( iv == NULL )
01082 return NULL;
01083 wn_loop_get_st_ofst( iv, iv_st, iv_ofst );
01084 if ( iv_st == 0 )
01085 return NULL;
01086
01087 step = WN_step(loop);
01088 step_opr = WN_operator(step);
01089
01090 if ( step_opr == OPR_STID||step_opr == OPR_PSTID) {
01091
01092 if ( iv_st != WN_st_idx(step) || iv_ofst != WN_store_offset(step) )
01093 return NULL;
01094
01095 store_val = WN_kid0(step);
01096 store_opr = WN_operator(store_val);
01097 }
01098 else {
01099
01100 return NULL;
01101 }
01102
01103 if ( store_opr == OPR_ADD )
01104 *is_incr = TRUE;
01105 else if ( store_opr == OPR_SUB )
01106 *is_incr = FALSE;
01107 else
01108 return NULL;
01109
01110
01111
01112 if ( wn_loop_ref_matches_var( WN_kid0(store_val), iv_st, iv_ofst ) ) {
01113 return WN_kid1(store_val);
01114 }
01115 else if ( wn_loop_ref_matches_var(WN_kid1(store_val),iv_st,iv_ofst) ){
01116
01117
01118
01119 if ( store_opr == OPR_ADD )
01120 return WN_kid0(store_val);
01121 else
01122 return NULL;
01123 }
01124 else {
01125
01126 return NULL;
01127 }
01128 }
01129
01130
01131
01132
01133
01134 extern WN *WN_LOOP_TripCount(const WN *loop)
01135 {
01136 WN *lb;
01137 WN *ub;
01138 OPCODE ub_compare;
01139 WN *incr;
01140 BOOL is_incr;
01141 WN *trip_cnt;
01142 BOOL saved_fold_enable;
01143 TYPE_ID trip_mtype;
01144
01145
01146
01147
01148
01149 if ( WN_opcode(loop) != OPC_DO_LOOP )
01150 return NULL;
01151
01152 lb = WN_LOOP_LowerBound( loop );
01153 if ( lb == NULL )
01154 return NULL;
01155
01156 ub = WN_LOOP_UpperBound( loop, &ub_compare );
01157 if ( ub == NULL )
01158 return NULL;
01159
01160 incr = WN_LOOP_Increment( loop, &is_incr );
01161 if ( incr == NULL )
01162 return NULL;
01163
01164
01165
01166
01167 trip_mtype = OPCODE_desc(ub_compare);
01168 if ( ! MTYPE_is_integral(WN_rtype(lb)) ||
01169 ! MTYPE_is_integral(WN_rtype(ub)) ||
01170 ! MTYPE_is_integral(WN_rtype(incr)) ||
01171 ! MTYPE_is_integral(trip_mtype) )
01172 return NULL;
01173
01174
01175 saved_fold_enable = WN_Simplifier_Enable(TRUE);
01176
01177
01178
01179
01180
01181 trip_cnt = WN_CreateExp2( OPCODE_make_op(OPR_SUB,trip_mtype,MTYPE_V),
01182 WN_COPY_Tree(ub), WN_COPY_Tree(lb) );
01183 if (OPCODE_operator(ub_compare) != OPR_GT &&
01184 OPCODE_operator(ub_compare) != OPR_LT)
01185 trip_cnt = WN_CreateExp2( OPCODE_make_op(OPR_ADD,trip_mtype,MTYPE_V),
01186 trip_cnt, WN_COPY_Tree(incr) );
01187 trip_cnt = WN_CreateExp2( OPCODE_make_op(OPR_DIV,trip_mtype,MTYPE_V),
01188 trip_cnt, WN_COPY_Tree(incr) );
01189
01190
01191 (void) WN_Simplifier_Enable(saved_fold_enable);
01192
01193 return trip_cnt;
01194 }
01195
01196
01197
01198 static TY_IDX
01199 field_type (const WN* wn)
01200 {
01201 UINT cur_field_id = 0;
01202 FLD_HANDLE fld = FLD_get_to_field (WN_ty(wn), WN_field_id(wn),
01203 cur_field_id);
01204 Is_True (! fld.Is_Null(), ("Invalid field id %d for type 0x%x",
01205 WN_field_id(wn), WN_ty(wn)));
01206 return FLD_type (fld);
01207 }
01208
01209
01210
01211
01212
01213
01214
01215
01216
01217 TY_IDX
01218 WN_object_ty (const WN *wn)
01219 {
01220 if (OPCODE_is_load(WN_opcode(wn))) {
01221 if ((WN_operator(wn) == OPR_LDID || WN_operator(wn) == OPR_LDBITS) &&
01222 WN_field_id(wn) != 0 &&
01223 TY_kind(WN_ty(wn)) == KIND_STRUCT)
01224 return field_type (wn);
01225 return WN_ty(wn);
01226 } else if (OPCODE_is_store(WN_opcode(wn))) {
01227 if (WN_operator(wn) == OPR_STID || WN_operator(wn) == OPR_STBITS
01228 || WN_operator(wn) == OPR_PSTID ) {
01229 if (WN_field_id(wn) != 0 && TY_kind(WN_ty(wn)) == KIND_STRUCT)
01230 return field_type (wn);
01231 return WN_ty(wn);
01232 } else {
01233 const TY& ty = Ty_Table[WN_ty (wn)];
01234 Is_True(TY_kind(ty) == KIND_POINTER,
01235 ("TY of ISTORE is not KIND_POINTER."));
01236 return TY_pointed(ty);
01237 }
01238 } else {
01239 return (TY_IDX) 0;
01240 }
01241 }
01242
01243
01244
01245 INT32 WN_object_size(const WN *wn)
01246 {
01247 OPERATOR opr = WN_operator(wn);
01248 switch (opr) {
01249 case OPR_ISTORE:
01250 case OPR_PSTORE:
01251 case OPR_ILOAD:
01252 case OPR_ISTOREX:
01253 case OPR_ILOADX:
01254 case OPR_LDID:
01255 case OPR_STID:
01256 case OPR_PSTID:
01257 case OPR_LDBITS:
01258 case OPR_STBITS:
01259 case OPR_ILDBITS:
01260 case OPR_ISTBITS:
01261 return (MTYPE_size_min(WN_desc(wn)) >> 3);
01262 case OPR_MLOAD:
01263 if (WN_operator(WN_kid1(wn)) == OPR_INTCONST)
01264 return WN_const_val(WN_kid1(wn));
01265 return 0;
01266 case OPR_MSTORE:
01267 if (WN_operator(WN_kid2(wn)) == OPR_INTCONST)
01268 return WN_const_val(WN_kid2(wn));
01269 return 0;
01270 case OPR_PARM:
01271 return (MTYPE_size_min(WN_rtype(wn)) >> 3);
01272 default:
01273 FmtAssert(FALSE, ("opcode not expected in WN_object_size."));
01274 return 0;
01275 }
01276 }
01277
01278
01279
01280
01281
01282
01283
01284
01285 static inline BOOL Pragma_is_Parallel_Region (WN_PRAGMA_ID pragma) {
01286
01287 switch (pragma) {
01288 case WN_PRAGMA_PARALLEL_BEGIN:
01289 case WN_PRAGMA_PARALLEL_SECTIONS:
01290 case WN_PRAGMA_PARALLEL_DO:
01291 case WN_PRAGMA_DOACROSS:
01292 return TRUE;
01293 default:
01294 return FALSE;
01295 }
01296 }
01297
01298
01299
01300
01301
01302
01303
01304 static inline BOOL Pragma_is_Work_Sharing (WN_PRAGMA_ID pragma) {
01305
01306 switch (pragma) {
01307 case WN_PRAGMA_PARALLEL_SECTIONS:
01308 case WN_PRAGMA_PARALLEL_DO:
01309 case WN_PRAGMA_DOACROSS:
01310 case WN_PRAGMA_PDO_BEGIN:
01311 case WN_PRAGMA_PSECTION_BEGIN:
01312 case WN_PRAGMA_SINGLE_PROCESS_BEGIN:
01313 return TRUE;
01314 default:
01315 return FALSE;
01316 }
01317 }
01318
01319
01320
01321
01322
01323
01324
01325
01326
01327
01328
01329
01330
01331
01332
01333
01334
01335
01336
01337
01338 extern void Add_Pragma_To_MP_Regions (WN_VECTOR *wnv,
01339 WN_PRAGMA_ID pragma_id,
01340 ST *st, WN_OFFSET ofst,
01341 WN_MAP parent_map,
01342 BOOL make_compiler_generated) {
01343
01344
01345
01346
01347
01348 FmtAssert (pragma_id == WN_PRAGMA_LOCAL || pragma_id == WN_PRAGMA_SHARED,
01349 ("Add_Pragma: can only handle LOCAL or SHARED pragmas"));
01350
01351 switch (pragma_id) {
01352 case WN_PRAGMA_SHARED: {
01353
01354
01355
01356
01357
01358
01359
01360
01361
01362
01363 for (WN_VECTOR::iterator wni = wnv->begin();
01364 wni != wnv->end();
01365 wni++) {
01366
01367 WN *region_wn = *wni;
01368
01369 #ifdef BACK_END
01370 Is_True (WN_opcode(region_wn) == OPC_REGION &&
01371 REGION_is_mp(region_wn),
01372 ("Add_Pragma: expected an MP WHIRL region"));
01373 #endif
01374 WN *pragma_wn = WN_first(WN_region_pragmas(region_wn));
01375
01376 Is_True (WN_opcode(pragma_wn) == OPC_PRAGMA,
01377 ("Add_Pragma: Expected a pragma node"));
01378 WN_PRAGMA_ID pragma = (WN_PRAGMA_ID) WN_pragma(pragma_wn);
01379
01380 if (Pragma_is_Parallel_Region(pragma)) {
01381 WN *shared_pwn = WN_CreatePragma (pragma_id, st, ofst, 0);
01382 if (make_compiler_generated) {
01383 WN_set_pragma_compiler_generated(shared_pwn);
01384 }
01385
01386 #ifdef Is_True_On
01387 {
01388
01389
01390
01391 WN *pwn = pragma_wn;
01392 while (pwn) {
01393 WN_PRAGMA_ID p_id = (WN_PRAGMA_ID) WN_pragma(pwn);
01394
01395 if ((p_id == WN_PRAGMA_LOCAL ||
01396 p_id == WN_PRAGMA_LASTLOCAL ||
01397 p_id == WN_PRAGMA_FIRSTPRIVATE) &&
01398 WN_st(pwn) == st &&
01399 WN_offset(pwn) == ofst) {
01400
01401 Is_True (FALSE,
01402 ("Add_Pragma: Conflict trying to add SHARED(%s) pragma",
01403 ST_name(st)));
01404
01405 }
01406 pwn = WN_next(pwn);
01407 }
01408 }
01409 #endif
01410
01411 WN_INSERT_BlockBefore (WN_region_pragmas(region_wn), NULL, shared_pwn);
01412
01413 if (parent_map) {
01414 WN_MAP_Set(parent_map,
01415 shared_pwn, (void*)WN_region_pragmas(region_wn));
01416 }
01417 }
01418 }
01419 break;
01420 }
01421 case WN_PRAGMA_LOCAL: {
01422
01423 BOOL need_pragma = TRUE;
01424
01425 for (WN_VECTOR::iterator wni = wnv->begin();
01426 wni != wnv->end();
01427 wni++) {
01428
01429
01430
01431
01432
01433 WN *region_wn = *wni;
01434
01435 #ifdef BACK_END
01436 Is_True (WN_opcode(region_wn) == OPC_REGION &&
01437 REGION_is_mp(region_wn),
01438 ("Add_Pragma: expected an MP WHIRL region"));
01439 #endif
01440 WN *pragma_wn = WN_first(WN_region_pragmas(region_wn));
01441
01442 Is_True (WN_opcode(pragma_wn) == OPC_PRAGMA,
01443 ("Add_Pragma: Expected a pragma node"));
01444 WN_PRAGMA_ID pragma = (WN_PRAGMA_ID) WN_pragma(pragma_wn);
01445
01446 if (need_pragma == TRUE &&
01447 (Pragma_is_Parallel_Region(pragma) ||
01448 Pragma_is_Work_Sharing(pragma))) {
01449
01450 WN *local_pwn = WN_CreatePragma (pragma_id, st, ofst, 0);
01451 if (make_compiler_generated) {
01452 WN_set_pragma_compiler_generated(local_pwn);
01453 }
01454
01455 WN_INSERT_BlockBefore (WN_region_pragmas(region_wn), NULL, local_pwn);
01456
01457 if (parent_map) {
01458 WN_MAP_Set(parent_map,local_pwn,(void*)WN_region_pragmas(region_wn));
01459 }
01460 need_pragma = FALSE;
01461 }
01462
01463 if (Pragma_is_Parallel_Region(pragma)) {
01464
01465
01466
01467
01468 need_pragma = TRUE;
01469 }
01470 }
01471 break;
01472 }
01473 default:
01474 Is_True (FALSE, ("Add_Pragma: trying to add unsupported pragma"));
01475 }
01476 }
01477