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
00055 #ifdef USE_PCH
00056 #include "common_com_pch.h"
00057 #endif
00058 #pragma hdrstop
00059 #include <stdio.h>
00060 #include <stdlib.h>
00061 #include <assert.h>
00062 #include <bstring.h>
00063 #include "defs.h"
00064 #include "stab.h"
00065 #include "wn.h"
00066 #include "wn_simp.h"
00067 #include "opcode.h"
00068 #include "wn_util.h"
00069 #include "ir_reader.h"
00070
00071 #ifdef BACK_END
00072 #include "region_util.h"
00073 #endif
00074 #ifdef KEY
00075 #include "config_opt.h"
00076 #endif
00077
00078
00079
00080 static WN_STACK *
00081 WN_InitStack (void)
00082 {
00083 WN_STACK *wns;
00084 wns = (WN_STACK *) MEM_POOL_Alloc (Malloc_Mem_Pool, sizeof(WN_STACK));
00085
00086
00087
00088 WN_STACK_size(wns) = 128;
00089 WN_STACK_stack(wns) = (WN **) MEM_POOL_Alloc (Malloc_Mem_Pool,
00090 sizeof(WN *) * 128);
00091
00092 WN_STACK_sp(wns) = WN_STACK_stack(wns);
00093 return wns;
00094 }
00095
00096
00097
00098
00099 inline WN *
00100 WN_Pop (WN_STACK *wns)
00101 {
00102 if (WN_STACK_sp(wns) == WN_STACK_stack(wns))
00103 return NULL;
00104 else
00105 return *(--WN_STACK_sp(wns));
00106 }
00107
00108
00109
00110
00111 inline void
00112 WN_Push (WN* wn, WN_STACK *wns)
00113 {
00114 *(WN_STACK_sp(wns)++) = wn;
00115 if ((WN_STACK_sp(wns) - WN_STACK_stack(wns)) == WN_STACK_size(wns)) {
00116
00117 INT size = WN_STACK_size(wns) * sizeof(WN *);
00118 WN_STACK_stack(wns) = (WN **)
00119 MEM_POOL_Realloc (Malloc_Mem_Pool, WN_STACK_stack(wns),
00120 size, size * 2);
00121 WN_STACK_sp(wns) = WN_STACK_stack(wns) + WN_STACK_size(wns);
00122 WN_STACK_size(wns) *= 2;
00123 }
00124 }
00125
00126
00127
00128
00129 static void
00130 WN_FreeStack (WN_STACK *wns)
00131 {
00132 MEM_POOL_FREE (Malloc_Mem_Pool, WN_STACK_stack(wns));
00133 MEM_POOL_FREE (Malloc_Mem_Pool, wns);
00134 }
00135
00136
00137
00138
00139
00140 extern WN_ITER* WN_WALK_TreeIter(WN *wn)
00141 {
00142 WN_ITER *wni;
00143
00144 FmtAssert(wn != 0, ("Bad tree node"));
00145 FmtAssert(WN_operator(wn) >= OPERATOR_FIRST &&
00146 WN_operator(wn) <= OPERATOR_LAST,
00147 ("Bad OPERATOR %d", WN_operator(wn)));
00148
00149 wni = (WN_ITER*)MEM_POOL_Alloc (Malloc_Mem_Pool,sizeof(WN_ITER));
00150 WN_ITER_wn(wni) = wn;
00151 WN_ITER_stack(wni) = WN_InitStack();
00152
00153 return wni;
00154 }
00155
00156
00157
00158
00159 extern WN_ITER* WN_WALK_SCFIter(WN *wn)
00160 {
00161 WN_ITER *wni;
00162
00163 FmtAssert(wn != 0, ("Bad tree node"));
00164 FmtAssert(WN_operator(wn) >= OPERATOR_FIRST &&
00165 WN_operator(wn) <= OPERATOR_LAST,
00166 ("Bad OPERATOR %d", WN_operator(wn)));
00167 FmtAssert(OPCODE_is_scf(WN_opcode(wn)), ("Expecting a Structured Control Flow tree node"));
00168
00169 wni = (WN_ITER*) MEM_POOL_Alloc (Malloc_Mem_Pool,sizeof(WN_ITER));
00170 WN_ITER_wn(wni) = wn;
00171 WN_ITER_stack(wni) = WN_InitStack();
00172
00173 return wni;
00174 }
00175
00176
00177
00178
00179
00180 extern WN_ITER* WN_WALK_StmtIter(WN *wn)
00181 {
00182 WN_ITER *wni;
00183
00184 FmtAssert(wn != 0, ("Bad tree node"));
00185 FmtAssert(WN_operator(wn) >= OPERATOR_FIRST &&
00186 WN_operator(wn) <= OPERATOR_LAST,
00187 ("Bad OPERATOR %d", WN_operator(wn)));
00188
00189
00190
00191
00192 if (OPCODE_is_scf(WN_opcode(wn)) || OPCODE_is_stmt(WN_opcode(wn)))
00193 {
00194 wni = (WN_ITER*) MEM_POOL_Alloc (Malloc_Mem_Pool,sizeof(WN_ITER));
00195 WN_ITER_wn(wni) = wn;
00196 WN_ITER_stack(wni) = WN_InitStack();
00197 return wni;
00198 }
00199
00200 return 0;
00201
00202 }
00203
00204
00205
00206
00207
00208 extern WN_ITER *
00209 WN_WALK_TreeNext(WN_ITER *wni)
00210 {
00211 INT i;
00212 WN *wn1;
00213
00214
00215
00216
00217
00218
00219 if (WN_ITER_wn(wni) != NULL) {
00220
00221 if (WN_operator(WN_ITER_wn(wni)) == OPR_BLOCK) {
00222 wn1 = WN_last(WN_ITER_wn(wni));
00223 while (wn1) {
00224 WN_Push(wn1, WN_ITER_stack(wni));
00225 wn1 = WN_prev(wn1);
00226 }
00227 } else {
00228
00229 for (i= WN_kid_count(WN_ITER_wn(wni))-1; i >= 0; --i) {
00230 if (WN_kid(WN_ITER_wn(wni), i) != NULL)
00231 WN_Push(WN_kid(WN_ITER_wn(wni), i), WN_ITER_stack(wni));
00232 }
00233 }
00234 }
00235 if ((WN_ITER_wn(wni) = WN_Pop(WN_ITER_stack(wni))) == NULL) {
00236 WN_FreeStack(WN_ITER_stack(wni));
00237 free(wni);
00238 return NULL;
00239 }
00240
00241 return wni;
00242 }
00243
00244
00245
00246
00247 extern WN_ITER *WN_WALK_StmtNext(WN_ITER *wni)
00248 {
00249 INT i;
00250 WN *wn1;
00251
00252
00253
00254
00255
00256
00257 if (WN_ITER_wn(wni) != NULL)
00258 {
00259
00260
00261 if (WN_operator(WN_ITER_wn(wni)) == OPR_BLOCK)
00262 {
00263 wn1 = WN_last(WN_ITER_wn(wni));
00264 while (wn1)
00265 {
00266 WN_Push(wn1, WN_ITER_stack(wni));
00267 wn1 = WN_prev(wn1);
00268 }
00269 }
00270
00271
00272 else if (OPCODE_is_scf(WN_opcode(WN_ITER_wn(wni))))
00273 {
00274 for (i= WN_kid_count(WN_ITER_wn(wni))-1; i >= 0; --i)
00275 {
00276 if (WN_kid(WN_ITER_wn(wni), i) != NULL)
00277 WN_Push(WN_kid(WN_ITER_wn(wni), i), WN_ITER_stack(wni));
00278 }
00279 }
00280 }
00281
00282 if ((WN_ITER_wn(wni) = WN_Pop(WN_ITER_stack(wni))) == NULL)
00283 {
00284 WN_FreeStack(WN_ITER_stack(wni));
00285 free(wni);
00286 return NULL;
00287 }
00288 return wni;
00289 }
00290
00291
00292
00293
00294 extern WN_ITER *WN_WALK_SCFNext(WN_ITER *wni)
00295 {
00296 INT i;
00297 WN *wn1;
00298
00299
00300
00301
00302
00303
00304 if (WN_ITER_wn(wni) != NULL)
00305 {
00306
00307
00308 if (WN_operator(WN_ITER_wn(wni)) == OPR_BLOCK)
00309 {
00310 wn1 = WN_last(WN_ITER_wn(wni));
00311 while (wn1)
00312 {
00313 if (OPCODE_is_scf(WN_opcode(wn1)))
00314 WN_Push(wn1, WN_ITER_stack(wni));
00315 wn1 = WN_prev(wn1);
00316 }
00317 }
00318
00319
00320 else if (OPCODE_is_scf(WN_opcode(WN_ITER_wn(wni))))
00321 {
00322 for (i= WN_kid_count(WN_ITER_wn(wni))-1; i >= 0; --i)
00323 {
00324 if (WN_kid(WN_ITER_wn(wni),i) != NULL) {
00325 if (OPCODE_is_scf(WN_opcode(WN_kid(WN_ITER_wn(wni), i))))
00326 {
00327 WN_Push(WN_kid(WN_ITER_wn(wni), i), WN_ITER_stack(wni));
00328 }
00329 }
00330 }
00331 }
00332 }
00333
00334 if ((WN_ITER_wn(wni) = WN_Pop(WN_ITER_stack(wni))) == NULL)
00335 {
00336 WN_FreeStack(WN_ITER_stack(wni));
00337 free(wni);
00338 return NULL;
00339 }
00340 return wni;
00341 }
00342
00343
00344
00345
00346
00347 extern void WN_WALK_Abort(WN_ITER *wni)
00348 {
00349 FmtAssert(wni != 0, ("Bad stack iterator"));
00350 if (WN_ITER_stack(wni) != NULL)
00351 {
00352 WN_FreeStack(WN_ITER_stack(wni));
00353 free(wni);
00354 }
00355 }
00356
00357
00358
00359
00360
00361 extern void WN_INSERT_BlockBefore(WN *blck, WN *wn, WN *in)
00362 {
00363 WN *node, *first, *last;
00364 BOOL done = FALSE;
00365
00366
00367 FmtAssert((in != 0), ("Bad tree node"));
00368
00369
00370 FmtAssert(OPCODE_is_stmt(WN_opcode(in)) || OPCODE_is_scf(WN_opcode(in)),
00371 ("Expecting a structured control flow node or a statement node"));
00372
00373 FmtAssert(WN_operator(blck) == OPR_BLOCK,
00374 ("Expecting a BLOCK operator"));
00375
00376
00377
00378
00379 if (wn != NULL)
00380 {
00381
00382
00383
00384
00385 if (wn != WN_last(blck))
00386 {
00387 node = WN_first(blck);
00388 if (node != wn)
00389 {
00390 while (!done && (node != NULL))
00391 {
00392 if (node == wn)
00393 done = TRUE;
00394 else
00395 node = WN_next(node);
00396 }
00397 }
00398 FmtAssert(node != NULL, ("Illegal insert block operation"));
00399 }
00400
00401
00402
00403 if (WN_opcode(in) != OPC_BLOCK)
00404 {
00405 if ((WN_prev(wn) == NULL))
00406 WN_first(blck) = in;
00407
00408
00409 WN_prev(in) = WN_prev(wn);
00410 WN_prev(wn) = in;
00411 WN_next(in) = wn;
00412 if (WN_prev(in)) WN_next(WN_prev(in)) = in;
00413 }
00414
00415 else
00416 {
00417 if (WN_first(in))
00418 {
00419 first = WN_first(in);
00420 last = WN_last(in);
00421 if ((WN_prev(wn) == NULL))
00422 WN_first(blck) = first;
00423
00424
00425 WN_prev(first) = WN_prev(wn);
00426 WN_prev(wn) = last;
00427 WN_next(last) = wn;
00428 if (WN_prev(first)) WN_next(WN_prev(first)) = first;
00429 }
00430 WN_first(in) = WN_last(in) = NULL;
00431 WN_Delete(in);
00432 }
00433 }
00434
00435
00436 else
00437 {
00438 if (WN_opcode(in) != OPC_BLOCK)
00439 {
00440 if (WN_first(blck) != NULL)
00441 {
00442 WN_prev(in) = WN_last(blck);
00443 WN_next(WN_last(blck)) = in;
00444 WN_last(blck) = in;
00445 WN_next(in) = NULL;
00446 }
00447 else
00448 {
00449 WN_last(blck) = in;
00450 WN_first(blck) = in;
00451 WN_prev(in) = WN_next(in) = NULL;
00452 }
00453 }
00454
00455 else
00456 {
00457 first = WN_first(in);
00458 last = WN_last(in);
00459 if (WN_first(in))
00460 {
00461 if (WN_first(blck) != NULL)
00462 {
00463 WN_prev(first) = WN_last(blck);
00464 WN_next(WN_last(blck)) = first;
00465 WN_last(blck) = last;
00466 WN_next(last) = NULL;
00467 }
00468 else
00469 {
00470 WN_last(blck) = last;
00471 WN_first(blck) = first;
00472 WN_prev(first) = WN_next(last) = NULL;
00473 }
00474 }
00475 WN_first(in) = WN_last(in) = NULL;
00476 WN_Delete(in);
00477 }
00478 }
00479 }
00480
00481
00482
00483
00484 extern void WN_INSERT_BlockAfter(WN *blck, WN *wn, WN *in)
00485 {
00486 WN *node, *first, *last;
00487 BOOL done = FALSE;
00488
00489
00490 FmtAssert(in != 0, ("Bad tree node"));
00491
00492
00493 FmtAssert(OPCODE_is_stmt(WN_opcode(in)) || OPCODE_is_scf(WN_opcode(in)),
00494 ("Expecting a structured control flow node or a statement node"));
00495
00496 FmtAssert(WN_operator(blck) == OPR_BLOCK,
00497 ("Expecting a BLOCK"));
00498
00499
00500
00501
00502 if (wn != NULL)
00503 {
00504
00505
00506
00507
00508 if (wn != WN_last(blck))
00509 {
00510 node = WN_first(blck);
00511 if (node != wn)
00512 {
00513 while (!done && (node != NULL))
00514 {
00515 if (node == wn)
00516 done = TRUE;
00517 else
00518 node = WN_next(node);
00519 }
00520 }
00521 FmtAssert(node != NULL, ("Illegal insert block operation"));
00522 }
00523
00524
00525 if (WN_opcode(in) != OPC_BLOCK)
00526 {
00527 if (WN_next(wn) == NULL)
00528 WN_last(blck) = in;
00529
00530
00531 WN_prev(in) = wn;
00532 WN_next(in) = WN_next(wn);
00533 WN_next(wn) = in;
00534 if (WN_next(in)) WN_prev(WN_next(in)) = in;
00535 }
00536
00537 else
00538 {
00539 if (WN_first(in))
00540 {
00541 first = WN_first(in);
00542 last = WN_last(in);
00543 if (WN_next(wn) == NULL)
00544 WN_last(blck) = last;
00545
00546
00547 WN_prev(first) = wn;
00548 WN_next(last) = WN_next(wn);
00549 WN_next(wn) = first;
00550 if (WN_next(last)) WN_prev(WN_next(last)) = last;
00551 }
00552 WN_first(in) = WN_last(in) = NULL;
00553 WN_Delete(in);
00554 }
00555 }
00556
00557
00558 else
00559 {
00560 if (WN_opcode(in) != OPC_BLOCK)
00561 {
00562
00563 if (WN_last(blck) != NULL)
00564 {
00565 WN_next(in) = WN_first(blck);
00566 WN_prev(in) = NULL;
00567 WN_prev(WN_first(blck)) = in;
00568 WN_first(blck) = in;
00569 }
00570 else
00571 {
00572 WN_last(blck) = in;
00573 WN_first(blck) = in;
00574 WN_prev(in) = WN_next(in) = NULL;
00575 }
00576 }
00577 else
00578 {
00579 first = WN_first(in);
00580 last = WN_last(in);
00581 if (WN_first(in))
00582 {
00583 if (WN_first(blck) != NULL)
00584 {
00585 WN_next(last) = WN_first(blck);
00586 WN_prev(first) = NULL;
00587 WN_prev(WN_first(blck)) = last;
00588 WN_first(blck) = first;
00589 }
00590 else
00591 {
00592 WN_last(blck) = last;
00593 WN_first(blck) = first;
00594 WN_prev(first) = WN_next(last) = NULL;
00595 }
00596 }
00597 WN_first(in) = WN_last(in) = NULL;
00598 WN_Delete(in);
00599 }
00600 }
00601 }
00602
00603
00604
00605
00606
00607 WN *
00608 WN_COPY_Tree (WN *wn)
00609 {
00610 WN *new_wn;
00611 WN *kid;
00612 OPCODE op;
00613
00614 if (wn == NULL)
00615 return NULL;
00616
00617 new_wn = WN_CopyNode (wn);
00618
00619 op = WN_opcode(wn);
00620 Is_True (OPCODE_operator(op) >= OPERATOR_FIRST &&
00621 OPCODE_operator(op) <= OPERATOR_LAST,
00622 ("Bad OPERATOR %d", OPCODE_operator(op)));
00623
00624 if (op == OPC_BLOCK) {
00625 WN *prev_kid, *new_kid;
00626
00627 new_kid = NULL;
00628 kid = WN_first(wn);
00629 if (kid) {
00630 new_kid = WN_COPY_Tree (kid);
00631 WN_prev(new_kid) = NULL;
00632 WN_first(new_wn) = new_kid;
00633 kid = WN_next(kid);
00634 prev_kid = new_kid;
00635
00636 while (kid) {
00637 new_kid = WN_COPY_Tree (kid);
00638 WN_next(prev_kid) = new_kid;
00639 WN_prev(new_kid) = prev_kid;
00640
00641 prev_kid = new_kid;
00642 kid = WN_next(kid);
00643 }
00644
00645 WN_next(new_kid) = NULL;
00646
00647 } else
00648 WN_first(new_wn) = NULL;
00649
00650 WN_last(new_wn) = new_kid;
00651
00652 } else {
00653 INT kidno;
00654 for (kidno = 0; kidno < WN_kid_count(wn); kidno++) {
00655 kid = WN_kid(wn, kidno);
00656 if (kid)
00657 WN_kid(new_wn, kidno) = WN_COPY_Tree (kid);
00658 else
00659 WN_kid(new_wn, kidno) = NULL;
00660 }
00661 }
00662
00663 return new_wn;
00664 }
00665
00666
00667 #ifdef MONGOOSE_BE
00668
00669
00670
00671 void
00672 WN_COPY_All_Maps(WN *dst, WN *src)
00673 {
00674 INT32 i;
00675 for (i = 0; i < WN_MAP_MAX; i++) {
00676 if (Current_Map_Tab->_is_used[i])
00677 WN_CopyMap(dst, i, src);
00678 }
00679 }
00680
00681
00682
00683
00684
00685 WN *
00686 WN_COPY_Tree_With_Map (WN *wn)
00687 {
00688 WN *new_wn;
00689 WN *kid;
00690 OPCODE op;
00691
00692 if (wn == NULL)
00693 return NULL;
00694
00695 new_wn = WN_CopyNode (wn);
00696 WN_COPY_All_Maps(new_wn, wn);
00697
00698 op = WN_opcode(wn);
00699 Is_True (OPCODE_operator(op) >= OPERATOR_FIRST &&
00700 OPCODE_operator(op) <= OPERATOR_LAST,
00701 ("Bad OPERATOR %d", OPCODE_operator(op)));
00702
00703 if (op == OPC_BLOCK) {
00704 WN *prev_kid, *new_kid;
00705
00706 new_kid = NULL;
00707 kid = WN_first(wn);
00708 if (kid) {
00709 new_kid = WN_COPY_Tree_With_Map (kid);
00710 WN_prev(new_kid) = NULL;
00711 WN_first(new_wn) = new_kid;
00712 kid = WN_next(kid);
00713 prev_kid = new_kid;
00714
00715 while (kid) {
00716 new_kid = WN_COPY_Tree_With_Map (kid);
00717 WN_next(prev_kid) = new_kid;
00718 WN_prev(new_kid) = prev_kid;
00719
00720 prev_kid = new_kid;
00721 kid = WN_next(kid);
00722 }
00723
00724 WN_next(new_kid) = NULL;
00725
00726 } else
00727 WN_first(new_wn) = NULL;
00728
00729 WN_last(new_wn) = new_kid;
00730
00731 } else {
00732 INT kidno;
00733 for (kidno = 0; kidno < WN_kid_count(wn); kidno++) {
00734 kid = WN_kid(wn, kidno);
00735 if (kid)
00736 WN_kid(new_wn, kidno) = WN_COPY_Tree_With_Map (kid);
00737 else
00738 WN_kid(new_wn, kidno) = NULL;
00739 }
00740 }
00741
00742 return new_wn;
00743 }
00744 #endif
00745
00746
00747
00748
00749
00750 extern void WN_DELETE_Tree(WN* tree)
00751 {
00752 WN *node;
00753 INT i;
00754
00755 if (tree) {
00756 if (WN_opcode(tree) == OPC_BLOCK) {
00757 node = WN_first(tree);
00758 while (node != NULL) {
00759 WN *next = WN_next(node);
00760 WN_DELETE_Tree (node);
00761 node = next;
00762 }
00763 } else
00764 for (i = 0; i< WN_kid_count(tree); i++)
00765 WN_DELETE_Tree(WN_kid(tree,i));
00766
00767 WN_Delete(tree);
00768 }
00769 }
00770
00771
00772
00773
00774
00775 void
00776 WN_DELETE_FromBlock (WN *blck, WN* wn)
00777 {
00778 #ifdef Is_True_On
00779 WN *node;
00780 BOOL done = FALSE;
00781 #endif
00782
00783
00784 if (wn == NULL)
00785 return;
00786
00787
00788 Is_True (OPCODE_is_stmt(WN_opcode(wn)) || OPCODE_is_scf(WN_opcode(wn)),
00789 ("Expecting a structured control flow node or a statement node"));
00790
00791 #ifdef Is_True_On
00792
00793 node = WN_first(blck);
00794 while (!done && (node != NULL)) {
00795 if (node == wn)
00796 done = TRUE;
00797 else
00798 node = WN_next(node);
00799 }
00800
00801 Is_True (node != NULL, ("Illegal delete operation"));
00802 #endif
00803
00804 if (WN_first(blck) == wn)
00805 WN_first(blck) = WN_next(wn);
00806
00807 if (WN_last(blck) == wn)
00808 WN_last(blck) = WN_prev(wn);
00809
00810
00811 if (WN_prev(wn) != NULL)
00812 WN_next(WN_prev(wn)) = WN_next(wn);
00813
00814 if (WN_next(wn) != NULL)
00815 WN_prev(WN_next(wn)) = WN_prev(wn);
00816
00817 WN_DELETE_Tree(wn);
00818 }
00819
00820
00821
00822
00823
00824 WN *WN_EXTRACT_FromBlock(WN *parent, WN *item)
00825 {
00826 Is_True(parent && WN_opcode(parent) == OPC_BLOCK,
00827 ("WN_Extract_FromBlock: parent not a block"));
00828 Is_True(item, ("WN_Extract_FromBlock: null item"));
00829
00830 #ifdef Is_True_On
00831 {
00832 WN *tmp;
00833 for (tmp = WN_first(parent); tmp && tmp != item; tmp = WN_next(tmp))
00834 ;
00835 Is_True(tmp == item, ("WN_Extract_FromBlock: item not on parent's list"));
00836 }
00837 #endif
00838
00839 if (WN_first(parent) == item)
00840 WN_first(parent) = WN_next(item);
00841 else
00842 WN_next(WN_prev(item)) = WN_next(item);
00843
00844 if (WN_last(parent) == item)
00845 WN_last(parent) = WN_prev(item);
00846 else
00847 WN_prev(WN_next(item)) = WN_prev(item);
00848
00849 WN_prev(item) = NULL;
00850 WN_next(item) = NULL;
00851 return item;
00852 }
00853
00854
00855
00856
00857 WN *WN_EXTRACT_ItemsFromBlock(WN *parent, WN *first_item, WN *last_item)
00858 {
00859 Is_True(parent && WN_opcode(parent) == OPC_BLOCK,
00860 ("WN_Extract_FromBlock: parent not a block"));
00861 Is_True(first_item, ("WN_Extract_FromBlock: null item"));
00862 Is_True(last_item, ("WN_Extract_FromBlock: null item"));
00863
00864 if (first_item == last_item)
00865 return WN_EXTRACT_FromBlock (parent, first_item);
00866
00867 #ifdef Is_True_On
00868 {
00869 WN *tmp;
00870 for (tmp = WN_first(parent); tmp && tmp != first_item; tmp = WN_next(tmp))
00871 ;
00872 Is_True(tmp == first_item, ("WN_Extract_ItemsFromBlock: item not on parent's list"));
00873 }
00874 #endif
00875
00876 if (WN_first(parent) == first_item)
00877 WN_first(parent) = WN_next(last_item);
00878 else
00879 WN_next(WN_prev(first_item)) = WN_next(last_item);
00880
00881 if (WN_last(parent) == last_item)
00882 WN_last(parent) = WN_prev(first_item);
00883 else
00884 WN_prev(WN_next(last_item)) = WN_prev(first_item);
00885
00886 WN_prev(first_item) = NULL;
00887 WN_next(last_item) = NULL;
00888
00889 return first_item;
00890 }
00891
00892
00893
00894
00895
00896
00897
00898
00899
00900
00901 static void
00902 wn_loop_get_st_ofst (const WN *var, ST_IDX& var_st, WN_OFFSET& var_offset)
00903 {
00904 if ( WN_opcode(var) == OPC_IDNAME ) {
00905 var_st = WN_st_idx(var);
00906 var_offset = WN_idname_offset(var);
00907 return;
00908 } else {
00909 const OPERATOR var_opr = WN_operator(var);
00910 if ( var_opr == OPR_LDID ) {
00911 var_st = WN_st_idx(var);
00912 var_offset = WN_load_offset(var);
00913 return;
00914 }
00915 if ( var_opr == OPR_STID ) {
00916 var_st = WN_st_idx(var);
00917 var_offset = WN_store_offset(var);
00918 return;
00919 }
00920 }
00921
00922 var_st = 0;
00923 var_offset = 0;
00924 }
00925
00926
00927
00928
00929
00930 static BOOL
00931 wn_loop_ref_matches_var (const WN *ref, ST_IDX st, WN_OFFSET ofst)
00932 {
00933 ST_IDX ref_st;
00934 WN_OFFSET ref_ofst;
00935
00936 wn_loop_get_st_ofst( ref, ref_st, ref_ofst );
00937 return ( ref_st == st && ref_ofst == ofst );
00938 }
00939
00940
00941
00942
00943
00944 static OPCODE wn_loop_reverse_compare( OPCODE comparison )
00945 {
00946 OPERATOR compare_opr = OPCODE_operator(comparison);
00947 TYPE_ID compare_desc = OPCODE_desc(comparison);
00948 TYPE_ID compare_rtype = OPCODE_rtype(comparison);
00949
00950 switch ( compare_opr ) {
00951 case OPR_LT : return OPCODE_make_op(OPR_GT,compare_rtype,compare_desc);
00952 case OPR_LE : return OPCODE_make_op(OPR_GE,compare_rtype,compare_desc);
00953 case OPR_EQ : return OPCODE_make_op(OPR_EQ,compare_rtype,compare_desc);
00954 case OPR_NE : return OPCODE_make_op(OPR_NE,compare_rtype,compare_desc);
00955 case OPR_GE : return OPCODE_make_op(OPR_LE,compare_rtype,compare_desc);
00956 case OPR_GT : return OPCODE_make_op(OPR_LT,compare_rtype,compare_desc);
00957 default:
00958 FmtAssert( FALSE,
00959 ("wn_loop_reverse_compare: not a comparison operator") );
00960 return (OPCODE)0;
00961 }
00962 }
00963
00964
00965
00966
00967
00968
00969 extern WN *WN_LOOP_InductionVariable(const WN *loop)
00970 {
00971
00972
00973
00974
00975 if ( WN_opcode(loop) != OPC_DO_LOOP )
00976 return NULL;
00977
00978 return WN_index(loop);
00979 }
00980
00981
00982
00983
00984
00985
00986
00987
00988 extern WN *WN_LOOP_LowerBound( const WN *loop )
00989 {
00990 WN *iv;
00991 ST_IDX iv_st;
00992 WN_OFFSET iv_ofst;
00993 WN *start;
00994 OPERATOR start_opr;
00995
00996
00997
00998
00999 iv = WN_LOOP_InductionVariable( loop );
01000 if ( iv == NULL )
01001 return NULL;
01002 wn_loop_get_st_ofst( iv, iv_st, iv_ofst );
01003 if ( iv_st == 0 )
01004 return NULL;
01005
01006 start = WN_start(loop);
01007 start_opr = WN_operator(start);
01008 if ( start_opr == OPR_STID ) {
01009
01010 if ( WN_st_idx(start) == iv_st && WN_store_offset(start) == iv_ofst )
01011 return WN_kid0(start);
01012 }
01013
01014
01015 return NULL;
01016 }
01017 #ifdef KEY
01018 static WN *WN_CreateDivceil(TYPE_ID type, WN *kid0, WN *kid1)
01019 {
01020 OPCODE op = OPCODE_make_op(OPR_INTRINSIC_OP, type, MTYPE_V);
01021 INT i;
01022 WN *kids[2];
01023 kids[0] = kid0;
01024 kids[1] = kid1;
01025 INT nkids = 2;
01026
01027 for (i = 0; i < nkids; i++) {
01028 if (WN_operator(kids[i]) != OPR_PARM) {
01029 TYPE_ID type = WN_rtype(kids[i]);
01030 kids[i] = WN_CreateParm(type, kids[i], Be_Type_Tbl(type),
01031 WN_PARM_BY_VALUE);
01032 }
01033 }
01034
01035 INTRINSIC intrinsic;
01036 switch (type) {
01037 case MTYPE_I4:
01038 intrinsic = INTRN_I4DIVCEIL;
01039 break;
01040 case MTYPE_I8:
01041 intrinsic = INTRN_I8DIVCEIL;
01042 break;
01043 case MTYPE_U4:
01044 intrinsic = INTRN_U4DIVCEIL;
01045 break;
01046 case MTYPE_U8:
01047 intrinsic = INTRN_U8DIVCEIL;
01048 break;
01049 default:
01050 FmtAssert(FALSE,
01051 ("Cannot create DIVCEIL intrinsic of type %d\n", type));
01052 }
01053
01054 WN *wn = WN_Create_Intrinsic(op, intrinsic, 2, kids);
01055
01056 return (wn);
01057 }
01058
01059 static WN *WN_CreateDivfloor(TYPE_ID type, WN *kid0, WN *kid1)
01060 {
01061 OPCODE op = OPCODE_make_op(OPR_INTRINSIC_OP, type, MTYPE_V);
01062 INT i;
01063 WN *kids[2];
01064 kids[0] = kid0;
01065 kids[1] = kid1;
01066 INT nkids = 2;
01067
01068 for (i = 0; i < nkids; i++) {
01069 if (WN_operator(kids[i]) != OPR_PARM) {
01070 TYPE_ID type = WN_rtype(kids[i]);
01071 kids[i] = WN_CreateParm(type, kids[i], Be_Type_Tbl(type),
01072 WN_PARM_BY_VALUE);
01073 }
01074 }
01075
01076 INTRINSIC intrinsic;
01077 switch (type) {
01078 case MTYPE_I4:
01079 intrinsic = INTRN_I4DIVFLOOR;
01080 break;
01081 case MTYPE_I8:
01082 intrinsic = INTRN_I8DIVFLOOR;
01083 break;
01084 case MTYPE_U4:
01085 intrinsic = INTRN_U4DIVFLOOR;
01086 break;
01087 case MTYPE_U8:
01088 intrinsic = INTRN_U8DIVFLOOR;
01089 break;
01090 default:
01091 FmtAssert(FALSE,
01092 ("Cannot create DIVFLOOR intrinsic of type %d\n", type));
01093 }
01094
01095 WN *wn = WN_Create_Intrinsic(op, intrinsic, 2, kids);
01096
01097 return (wn);
01098 }
01099
01100 static void Flip_Le_And_Ge(WN* wn)
01101 {
01102 OPCODE opc = WN_opcode(wn);
01103 OPERATOR opr = OPCODE_operator(opc);
01104 switch (opr) {
01105 case OPR_GE: opr = OPR_LE; break;
01106 case OPR_LE: opr = OPR_GE; break;
01107 case OPR_GT: opr = OPR_LT; break;
01108 case OPR_LT: opr = OPR_GT; break;
01109 default: FmtAssert(0, ("Bad call to Flip_Le_And_Ge")); break;
01110 }
01111 WN_set_opcode(wn, OPCODE_make_op(opr, OPCODE_rtype(opc), OPCODE_desc(opc)));
01112 }
01113
01114 static INT WN_Symbol_Count(WN* wn, const ST_IDX sym, const WN_OFFSET ofst)
01115 {
01116 INT rval = (WN_operator(wn) == OPR_LDID
01117 && sym == WN_st_idx(wn)
01118 && ofst == WN_load_offset(wn))
01119 ? 1 : 0;
01120 for (INT k = 0; k < WN_kid_count(wn); k++)
01121 rval += WN_Symbol_Count(WN_kid(wn,k), sym, ofst);
01122 return rval;
01123 }
01124
01125 static BOOL WN_Solve_For(WN* wn_top, const ST_IDX sym, const WN_OFFSET ofst)
01126 {
01127 BOOL ok = FALSE;
01128 INT lcount = WN_Symbol_Count(WN_kid0(wn_top), sym, ofst);
01129 INT rcount = WN_Symbol_Count(WN_kid1(wn_top), sym, ofst);
01130 OPERATOR opr_base = WN_operator(wn_top);
01131 FmtAssert(opr_base == OPR_GT || opr_base == OPR_LT || opr_base == OPR_LE
01132 || opr_base == OPR_GE, ("Solve_For() called with bad RELOP"));
01133 if (!(lcount == 1 && rcount == 0) && !(lcount == 0 && rcount == 1)) {
01134 return FALSE;
01135 }
01136
01137
01138 if (rcount) {
01139 Flip_Le_And_Ge(wn_top);
01140 WN* wn0 = WN_kid0(wn_top);
01141 WN_kid0(wn_top) = WN_kid1(wn_top);
01142 WN_kid1(wn_top) = wn0;
01143 }
01144 WN* l = WN_kid0(wn_top);
01145 WN* r = WN_kid1(wn_top);
01146 while (1) {
01147
01148
01149 OPCODE lopc = WN_opcode(l);
01150 OPERATOR lopr = OPCODE_operator(lopc);
01151
01152 if (OPCODE_is_load(lopc)) {
01153 ok = TRUE;
01154 break;
01155 }
01156 if (lopr == OPR_NEG) {
01157 Flip_Le_And_Ge(wn_top);
01158 TYPE_ID type = WN_rtype(r);
01159 OPCODE negop = OPCODE_make_op(OPR_NEG, type, MTYPE_V);
01160 r = WN_CreateExp1(negop, r);
01161 l = WN_kid0(l);
01162 continue;
01163 }
01164
01165
01166 if (lopr == OPR_CVT || WN_kid_count(l) == 1)
01167 return FALSE;
01168 lcount = WN_Symbol_Count(WN_kid0(l), sym, ofst);
01169 rcount = WN_Symbol_Count(WN_kid1(l), sym, ofst);
01170 Is_True((lcount == 1 && rcount == 0) ||
01171 (lcount == 0 && rcount == 1),
01172 ("Impossible: Counts messed up %d %d", lcount, rcount));
01173 if (rcount) {
01174 if (lopr == OPR_SUB) {
01175
01176
01177 Flip_Le_And_Ge(wn_top);
01178 TYPE_ID type = WN_rtype(r);
01179 #ifdef TARG_X8664
01180
01181
01182
01183 if (MTYPE_is_unsigned(type)) type = MTYPE_complement(type);
01184 #endif
01185 OPCODE negop = OPCODE_make_op(OPR_NEG, type, MTYPE_V);
01186 r = WN_CreateExp1(negop, r);
01187 }
01188 else if (lopr != OPR_ADD && lopr != OPR_MPY)
01189 break;
01190 WN* wn0 = WN_kid0(l);
01191 WN_kid0(l) = WN_kid1(l);
01192 WN_kid1(l) = wn0;
01193 }
01194 WN* ll = WN_kid0(l);
01195 WN* lr = WN_kid1(l);
01196 if (lopr == OPR_MPY) {
01197 TYPE_ID type = OPCODE_rtype(lopc);
01198 switch (type) {
01199 case MTYPE_I4:
01200 case MTYPE_I8:
01201 case MTYPE_U8:
01202 break;
01203 default:
01204 goto out;
01205 }
01206
01207
01208
01209 OPCODE lropc = WN_opcode(lr);
01210 if (OPCODE_operator(lropc) != OPR_INTCONST)
01211 break;
01212 INT v = WN_const_val(lr);
01213 if (v < 0) {
01214 Flip_Le_And_Ge(wn_top);
01215 WN_const_val(lr) = -v;
01216 OPCODE negop = OPCODE_make_op(OPR_NEG, OPCODE_rtype(lropc), MTYPE_V);
01217 r = WN_CreateExp1(negop, r);
01218 }
01219 BOOL use_ceil = WN_operator(wn_top) == OPR_GE
01220 || WN_operator(wn_top) == OPR_LT;
01221 if (use_ceil)
01222 r = WN_CreateDivceil(type, r, lr);
01223 else
01224 r = WN_CreateDivfloor(type, r, lr);
01225 WN_Delete(l);
01226 l = ll;
01227 }
01228 else if (lopr == OPR_ADD || lopr == OPR_SUB) {
01229 WN_kid0(l) = r;
01230 WN_kid1(l) = lr;
01231 r = l;
01232 l = ll;
01233 WN_set_opcode(r, OPCODE_make_op(lopr == OPR_ADD ? OPR_SUB : OPR_ADD,
01234 OPCODE_rtype(lopc), OPCODE_desc(lopc)));
01235 }
01236 else
01237 return FALSE;
01238 }
01239 out:
01240 WN_kid0(wn_top) = l;
01241 WN_kid1(wn_top) = r;
01242 return ok;
01243 }
01244 #endif
01245
01246
01247
01248
01249
01250
01251
01252
01253
01254
01255
01256 #ifdef KEY
01257 extern WN *WN_LOOP_UpperBound( const WN *loop, OPCODE *compare,
01258 BOOL enhanced)
01259 #else
01260 extern WN *WN_LOOP_UpperBound( const WN *loop, OPCODE *compare )
01261 #endif
01262 {
01263 WN *iv;
01264 ST_IDX iv_st;
01265 WN_OFFSET iv_ofst;
01266 WN *end;
01267 WN *new_end;
01268 OPCODE end_opc;
01269
01270
01271
01272
01273
01274 iv = WN_LOOP_InductionVariable( loop );
01275 if ( iv == NULL )
01276 return NULL;
01277 wn_loop_get_st_ofst( iv, iv_st, iv_ofst );
01278 if ( iv_st == 0 )
01279 return NULL;
01280
01281
01282
01283
01284 end = WN_end(loop);
01285 end_opc = WN_opcode(end);
01286 if ( ! OPCODE_is_compare(end_opc) )
01287 return NULL;
01288
01289
01290 if ( wn_loop_ref_matches_var( WN_kid0(end), iv_st, iv_ofst ) ) {
01291 *compare = end_opc;
01292 return WN_kid1(end);
01293 }
01294 else if ( wn_loop_ref_matches_var( WN_kid1(end), iv_st, iv_ofst ) ) {
01295 *compare = wn_loop_reverse_compare( end_opc );
01296 return WN_kid0(end);
01297 }
01298 #ifdef KEY
01299 if (enhanced){
01300 new_end = WN_COPY_Tree_With_Map(end);
01301 if (WN_Solve_For(new_end, iv_st, iv_ofst) &&
01302 wn_loop_ref_matches_var( WN_kid0(new_end), iv_st, iv_ofst ) ) {
01303 *compare = end_opc;
01304 return WN_kid1(new_end);
01305 }
01306 }
01307 #endif
01308
01309 *compare = OPCODE_UNKNOWN;
01310 return NULL;
01311 }
01312
01313
01314
01315
01316
01317
01318
01319
01320 extern WN *WN_LOOP_Increment( const WN *loop, BOOL *is_incr )
01321 {
01322 WN *iv;
01323 ST_IDX iv_st;
01324 WN_OFFSET iv_ofst;
01325 WN *step;
01326 OPERATOR step_opr;
01327 WN *store_val;
01328 OPERATOR store_opr;
01329
01330
01331
01332
01333 iv = WN_LOOP_InductionVariable( loop );
01334 if ( iv == NULL )
01335 return NULL;
01336 wn_loop_get_st_ofst( iv, iv_st, iv_ofst );
01337 if ( iv_st == 0 )
01338 return NULL;
01339
01340 step = WN_step(loop);
01341 step_opr = WN_operator(step);
01342
01343 if ( step_opr == OPR_STID ) {
01344
01345 if ( iv_st != WN_st_idx(step) || iv_ofst != WN_store_offset(step) )
01346 return NULL;
01347
01348 store_val = WN_kid0(step);
01349 store_opr = WN_operator(store_val);
01350 }
01351 else {
01352
01353 return NULL;
01354 }
01355
01356 if ( store_opr == OPR_ADD )
01357 *is_incr = TRUE;
01358 else if ( store_opr == OPR_SUB )
01359 *is_incr = FALSE;
01360 else
01361 return NULL;
01362
01363
01364
01365 if ( wn_loop_ref_matches_var( WN_kid0(store_val), iv_st, iv_ofst ) ) {
01366 return WN_kid1(store_val);
01367 }
01368 else if ( wn_loop_ref_matches_var(WN_kid1(store_val),iv_st,iv_ofst) ){
01369
01370
01371
01372 if ( store_opr == OPR_ADD )
01373 return WN_kid0(store_val);
01374 else
01375 return NULL;
01376 }
01377 else {
01378
01379 return NULL;
01380 }
01381 }
01382
01383
01384
01385
01386
01387 #ifdef KEY
01388 extern WN *WN_LOOP_TripCount(const WN *loop, BOOL enhanced)
01389 #else
01390 extern WN *WN_LOOP_TripCount(const WN *loop)
01391 #endif
01392 {
01393 WN *lb;
01394 WN *ub;
01395 OPCODE ub_compare;
01396 WN *incr;
01397 BOOL is_incr;
01398 WN *trip_cnt;
01399 BOOL saved_fold_enable;
01400 TYPE_ID trip_mtype;
01401
01402
01403
01404
01405
01406 if ( WN_opcode(loop) != OPC_DO_LOOP )
01407 return NULL;
01408
01409 lb = WN_LOOP_LowerBound( loop );
01410 if ( lb == NULL )
01411 return NULL;
01412
01413 ub = WN_LOOP_UpperBound( loop, &ub_compare, enhanced );
01414 if ( ub == NULL )
01415 return NULL;
01416
01417 incr = WN_LOOP_Increment( loop, &is_incr );
01418 if ( incr == NULL )
01419 return NULL;
01420
01421
01422
01423
01424 trip_mtype = OPCODE_desc(ub_compare);
01425 if ( ! MTYPE_is_integral(WN_rtype(lb)) ||
01426 ! MTYPE_is_integral(WN_rtype(ub)) ||
01427 ! MTYPE_is_integral(WN_rtype(incr)) ||
01428 ! MTYPE_is_integral(trip_mtype) )
01429 return NULL;
01430
01431
01432 saved_fold_enable = WN_Simplifier_Enable(TRUE);
01433
01434
01435
01436
01437
01438 trip_cnt = WN_CreateExp2( OPCODE_make_op(OPR_SUB,trip_mtype,MTYPE_V),
01439 WN_COPY_Tree(ub), WN_COPY_Tree(lb) );
01440 if (OPCODE_operator(ub_compare) != OPR_GT &&
01441 OPCODE_operator(ub_compare) != OPR_LT)
01442 trip_cnt = WN_CreateExp2( OPCODE_make_op(OPR_ADD,trip_mtype,MTYPE_V),
01443 trip_cnt, WN_COPY_Tree(incr) );
01444 #ifdef TARG_NVISA_TODO
01445
01446
01447
01448
01449
01450 if (MTYPE_is_unsigned(trip_mtype)
01451 && WN_operator(trip_cnt) == OPR_INTCONST
01452 && WN_const_val(trip_cnt) < 0
01453 && WN_operator(incr) == OPR_INTCONST)
01454 {
01455 INT64 incrval = WN_const_val(incr);
01456 if (trip_mtype == MTYPE_U4) {
01457
01458 incrval = (INT64)(INT32)(UINT32)incrval;
01459 }
01460 if (incrval < 0) {
01461 incr = WN_Abs(MTYPE_complement(trip_mtype), WN_COPY_Tree(incr));
01462 trip_cnt = WN_Abs(MTYPE_complement(trip_mtype), trip_cnt);
01463 }
01464 }
01465 #endif
01466
01467 trip_cnt = WN_CreateExp2( OPCODE_make_op(OPR_DIV,trip_mtype,MTYPE_V),
01468 trip_cnt, WN_COPY_Tree(incr) );
01469
01470
01471 (void) WN_Simplifier_Enable(saved_fold_enable);
01472
01473 return trip_cnt;
01474 }
01475
01476 #ifdef KEY
01477
01478 static BOOL
01479 type_ok (const TY_IDX ty)
01480 {
01481 INT fld_count = 0;
01482 Is_True (TY_kind(ty) == KIND_STRUCT, ("type_ok: struct type expected"));
01483
01484 if (TY_size (ty) != 60) return TRUE;
01485
01486 FLD_ITER fld_iter = Make_fld_iter (TY_fld (ty));
01487
01488 {
01489 FLD_HANDLE fld(fld_iter);
01490 TY_IDX field = FLD_type (fld);
01491 if (TY_kind (field) != KIND_POINTER ||
01492 TY_mtype (TY_pointed (field)) != MTYPE_F8)
01493 return TRUE;
01494 }
01495
01496 fld_count++;
01497
01498 while (!FLD_last_field(fld_iter++))
01499 {
01500 FLD_HANDLE fld(fld_iter);
01501 TY_IDX field = FLD_type (fld);
01502
01503 if (TY_kind (field) != KIND_SCALAR || TY_mtype (field) != MTYPE_F8)
01504 return TRUE;
01505
01506 fld_count++;
01507 }
01508
01509 if (fld_count != 8) return TRUE;
01510
01511 return FALSE;
01512 }
01513 #endif
01514
01515 #ifdef TARG_IA64
01516 static TY_IDX
01517 field_type (const TY_IDX ty_idx, UINT field_id)
01518 {
01519 UINT cur_field_id = 0;
01520 FLD_HANDLE fld = FLD_get_to_field (ty_idx, field_id, cur_field_id);
01521 Is_True (! fld.Is_Null(), ("Invalid field id %d for type 0x%x",
01522 field_id, ty_idx));
01523 return FLD_type (fld);
01524 }
01525 #else
01526 static TY_IDX
01527 field_type (const WN* wn)
01528 {
01529 UINT cur_field_id = 0;
01530 #ifdef KEY
01531 TY_IDX ty;
01532
01533
01534 if (WN_operator(wn) == OPR_ISTORE)
01535 {
01536 TY_IDX ptr = WN_ty(wn);
01537 Is_True (TY_kind(ptr) == KIND_POINTER,
01538 ("field_type: Addr TY of ISTORE is not KIND_POINTER."));
01539 ty = TY_pointed(ptr);
01540 }
01541 else
01542 ty = WN_ty(wn);
01543
01544 Is_True (TY_kind(ty) == KIND_STRUCT,
01545 ("field_type: cannot get to field of a non-struct type"));
01546 FLD_HANDLE fld = FLD_get_to_field (ty, WN_field_id(wn), cur_field_id);
01547 #else
01548 FLD_HANDLE fld = FLD_get_to_field (WN_ty(wn), WN_field_id(wn),
01549 cur_field_id);
01550 #endif
01551 Is_True (! fld.Is_Null(), ("Invalid field id %d for type 0x%x",
01552 WN_field_id(wn), WN_ty(wn)));
01553 return FLD_type (fld);
01554 }
01555 #endif // TARG_IA64
01556
01557
01558
01559
01560
01561
01562
01563
01564
01565 #ifdef TARG_IA64
01566
01567
01568
01569 TY_IDX
01570 WN_object_ty (const WN *wn)
01571 {
01572 if (OPCODE_is_load(WN_opcode(wn))) {
01573
01574 if (WN_operator(wn) == OPR_MLOAD) {
01575 TY_IDX ptr_ty = WN_ty(wn);
01576 Is_True (TY_kind(ptr_ty) == KIND_POINTER, ("TY of ISTORE is not KIND_POINTER."));
01577 return TY_pointer(ptr_ty);
01578 }
01579
01580 if ((WN_operator(wn) == OPR_LDID ||
01581 WN_operator(wn) == OPR_ILOAD
01582 #ifndef KEY
01583 || WN_operator(wn) == OPR_LDBITS
01584 #endif
01585 ) && WN_field_id(wn) != 0 &&
01586 TY_kind(WN_ty(wn)) == KIND_STRUCT)
01587 return field_type (WN_ty(wn), WN_field_id(wn));
01588 if ((WN_operator(wn) == OPR_ILOAD || WN_operator(wn) == OPR_ILDBITS)) {
01589 Is_True (TY_kind(WN_load_addr_ty(wn)) == KIND_POINTER,
01590 ("TY of ILOAD is not KIND_POINTER."));
01591 TY_IDX ty_idx = TY_pointed(WN_load_addr_ty(wn));
01592 return ty_idx;
01593 }
01594 return WN_ty(wn);
01595 } else if (OPCODE_is_store(WN_opcode(wn))) {
01596 TY_IDX ty_idx = WN_ty(wn);
01597 if (!(WN_operator(wn) == OPR_STID || WN_operator(wn) == OPR_STBITS)) {
01598 Is_True(TY_kind(WN_ty(wn)) == KIND_POINTER,
01599 ("TY of ISTORE is not KIND_POINTER."));
01600 ty_idx = TY_pointed(WN_ty(wn));
01601 }
01602 if (WN_field_id(wn) != 0 && TY_kind(ty_idx) == KIND_STRUCT) {
01603 return field_type (ty_idx, WN_field_id(wn));
01604 }
01605 return ty_idx;
01606 } else {
01607 return (TY_IDX) 0;
01608 }
01609 }
01610 #else // TARG_IA64
01611 TY_IDX
01612 WN_object_ty (const WN *wn)
01613 {
01614 if (OPCODE_is_load(WN_opcode(wn))) {
01615 if (WN_operator(wn) == OPR_MLOAD) {
01616 TY_IDX ptr_ty = WN_ty(wn);
01617 Is_True (TY_kind(ptr_ty) == KIND_POINTER, ("TY of ISTORE is not KIND_POINTER."));
01618 return TY_pointer(ptr_ty);
01619 }
01620
01621 if ((WN_operator(wn) == OPR_LDID
01622 #ifdef KEY
01623 || WN_operator(wn) == OPR_ILOAD
01624 #else
01625 || WN_operator(wn) == OPR_LDBITS
01626 #endif
01627 ) &&
01628 WN_field_id(wn) != 0 &&
01629 TY_kind(WN_ty(wn)) == KIND_STRUCT)
01630 return field_type (wn);
01631 #ifdef KEY
01632 if (WN_operator(wn) == OPR_ILOAD) {
01633 const TY& ty = Ty_Table[WN_load_addr_ty (wn)];
01634 Is_True (TY_kind(ty) == KIND_POINTER,
01635 ("Addr TY of ILOAD is not KIND_POINTER."));
01636 return TY_pointed(ty);
01637 }
01638 #endif
01639 return WN_ty(wn);
01640 } else if (OPCODE_is_store(WN_opcode(wn))) {
01641 if (WN_operator(wn) == OPR_STID || WN_operator(wn) == OPR_STBITS) {
01642 if (WN_field_id(wn) != 0 && TY_kind(WN_ty(wn)) == KIND_STRUCT
01643 #ifdef KEY
01644 && WN_operator(wn) == OPR_STID
01645 #endif
01646 )
01647 return field_type (wn);
01648 return WN_ty(wn);
01649 } else {
01650 const TY& ty = Ty_Table[WN_ty (wn)];
01651 Is_True(TY_kind(ty) == KIND_POINTER,
01652 ("TY of ISTORE is not KIND_POINTER."));
01653 TY_IDX pointed = TY_pointed (ty);
01654 #ifdef KEY
01655 if (WN_operator(wn) == OPR_ISTORE &&
01656 WN_field_id(wn) != 0 &&
01657 TY_kind(pointed) == KIND_STRUCT &&
01658 !TY_is_union(pointed) &&
01659 type_ok (pointed))
01660 return field_type (wn);
01661 #endif
01662 return pointed;
01663 }
01664 } else {
01665 return (TY_IDX) 0;
01666 }
01667 }
01668 #endif // TARG_IA64
01669
01670 void
01671 WN_hl_object_ty (const WN *wn, TY_IDX& ty, UINT32& fld_id)
01672 {
01673 ty = (TY_IDX)0;
01674 fld_id = 0;
01675
01676 if (OPCODE_is_load(WN_opcode(wn))) {
01677 if (WN_operator(wn) == OPR_MLOAD) {
01678 TY_IDX ptr_ty = WN_ty(wn);
01679 Is_True (TY_kind(ptr_ty) == KIND_POINTER, ("TY of ISTORE is not KIND_POINTER."));
01680 ty = TY_pointer(ptr_ty);
01681 } else if ((WN_operator(wn) == OPR_LDID ||
01682 WN_operator(wn) == OPR_ILOAD ||
01683 WN_operator(wn) == OPR_LDBITS) &&
01684 WN_field_id(wn) != 0 && TY_kind(WN_ty(wn)) == KIND_STRUCT) {
01685 ty = WN_ty(wn);
01686 fld_id = WN_field_id(wn);
01687 } else if ((WN_operator(wn) == OPR_ILOAD ||
01688 WN_operator(wn) == OPR_ILDBITS)) {
01689 Is_True (TY_kind(WN_load_addr_ty(wn)) == KIND_POINTER,
01690 ("TY of ILOAD is not KIND_POINTER."));
01691 ty = TY_pointed(WN_load_addr_ty(wn));
01692 }
01693 } else if (OPCODE_is_store(WN_opcode(wn))) {
01694 ty = WN_ty(wn);
01695 if (!(WN_operator(wn) == OPR_STID || WN_operator(wn) == OPR_STBITS)) {
01696 Is_True(TY_kind(WN_ty(wn)) == KIND_POINTER,
01697 ("TY of ISTORE is not KIND_POINTER."));
01698 ty = TY_pointed(WN_ty(wn));
01699 }
01700 if (WN_field_id(wn) != 0 && TY_kind(ty) == KIND_STRUCT) {
01701 fld_id = WN_field_id(wn);
01702 }
01703 }
01704 }
01705
01706
01707
01708 INT32 WN_object_size(const WN *wn)
01709 {
01710 OPERATOR opr = WN_operator(wn);
01711 switch (opr) {
01712 case OPR_ISTORE:
01713 case OPR_ILOAD:
01714 case OPR_ISTOREX:
01715 case OPR_ILOADX:
01716 case OPR_LDID:
01717 case OPR_STID:
01718 case OPR_LDBITS:
01719 case OPR_STBITS:
01720 case OPR_ILDBITS:
01721 case OPR_ISTBITS:
01722 if (WN_desc(wn) != MTYPE_M)
01723 return (MTYPE_size_min(WN_desc(wn)) >> 3);
01724 else {
01725 TY_IDX ty = WN_object_ty (wn);
01726 return (ty != (TY_IDX)0) ? TY_size(ty) : 0;
01727 }
01728 case OPR_MLOAD:
01729 if (WN_operator(WN_kid1(wn)) == OPR_INTCONST)
01730 return WN_const_val(WN_kid1(wn));
01731 return 0;
01732 case OPR_MSTORE:
01733 if (WN_operator(WN_kid2(wn)) == OPR_INTCONST)
01734 return WN_const_val(WN_kid2(wn));
01735 return 0;
01736 case OPR_PARM:
01737 return (MTYPE_size_min(WN_rtype(wn)) >> 3);
01738 default:
01739 FmtAssert(FALSE, ("opcode not expected in WN_object_size."));
01740 return 0;
01741 }
01742 }
01743
01744
01745
01746
01747
01748
01749
01750
01751 static inline BOOL Pragma_is_Parallel_Region (WN_PRAGMA_ID pragma) {
01752
01753 switch (pragma) {
01754 case WN_PRAGMA_PARALLEL_BEGIN:
01755 case WN_PRAGMA_PARALLEL_SECTIONS:
01756 case WN_PRAGMA_PARALLEL_DO:
01757 case WN_PRAGMA_PARALLEL_WORKSHARE:
01758 case WN_PRAGMA_DOACROSS:
01759 return TRUE;
01760 default:
01761 return FALSE;
01762 }
01763 }
01764
01765
01766
01767
01768
01769
01770
01771 static inline BOOL Pragma_is_Work_Sharing (WN_PRAGMA_ID pragma) {
01772
01773 switch (pragma) {
01774 case WN_PRAGMA_PARALLEL_SECTIONS:
01775 case WN_PRAGMA_PARALLEL_DO:
01776 case WN_PRAGMA_PARALLEL_WORKSHARE:
01777 case WN_PRAGMA_DOACROSS:
01778 case WN_PRAGMA_PDO_BEGIN:
01779 case WN_PRAGMA_PSECTION_BEGIN:
01780 case WN_PRAGMA_SINGLE_PROCESS_BEGIN:
01781 case WN_PRAGMA_PWORKSHARE_BEGIN:
01782 return TRUE;
01783 default:
01784 return FALSE;
01785 }
01786 }
01787
01788
01789
01790
01791
01792
01793
01794
01795
01796
01797
01798
01799
01800
01801
01802
01803
01804
01805
01806
01807 extern void Add_Pragma_To_MP_Regions (WN_VECTOR *wnv,
01808 WN_PRAGMA_ID pragma_id,
01809 ST *st, WN_OFFSET ofst,
01810 WN_MAP parent_map,
01811 BOOL make_compiler_generated) {
01812
01813
01814
01815
01816
01817 FmtAssert (pragma_id == WN_PRAGMA_LOCAL || pragma_id == WN_PRAGMA_SHARED,
01818 ("Add_Pragma: can only handle LOCAL or SHARED pragmas"));
01819
01820 switch (pragma_id) {
01821 case WN_PRAGMA_SHARED: {
01822
01823
01824
01825
01826
01827
01828
01829
01830
01831
01832 for (WN_VECTOR::iterator wni = wnv->begin();
01833 wni != wnv->end();
01834 wni++) {
01835
01836 WN *region_wn = *wni;
01837
01838 #ifdef BACK_END
01839 Is_True (WN_opcode(region_wn) == OPC_REGION &&
01840 REGION_is_mp(region_wn),
01841 ("Add_Pragma: expected an MP WHIRL region"));
01842 #endif
01843 WN *pragma_wn = WN_first(WN_region_pragmas(region_wn));
01844
01845 Is_True (WN_opcode(pragma_wn) == OPC_PRAGMA,
01846 ("Add_Pragma: Expected a pragma node"));
01847 WN_PRAGMA_ID pragma = (WN_PRAGMA_ID) WN_pragma(pragma_wn);
01848
01849 if (Pragma_is_Parallel_Region(pragma)) {
01850 #ifdef KEY
01851
01852
01853
01854
01855 {
01856 WN * pwn = pragma_wn;
01857 BOOL match = FALSE;
01858 while (pwn)
01859 {
01860 if (WN_st_idx (pwn) == ST_st_idx (st) &&
01861 (WN_PRAGMA_ID) WN_pragma (pwn) == pragma_id)
01862 {
01863 match = TRUE;
01864 break;
01865 }
01866 pwn = WN_next (pwn);
01867 }
01868 if (match)
01869 continue;
01870 }
01871 #endif // KEY
01872 WN *shared_pwn = WN_CreatePragma (pragma_id, st, ofst, 0);
01873 if (make_compiler_generated) {
01874 WN_set_pragma_compiler_generated(shared_pwn);
01875 }
01876
01877 #ifdef Is_True_On
01878 {
01879
01880
01881
01882 WN *pwn = pragma_wn;
01883 while (pwn) {
01884 WN_PRAGMA_ID p_id = (WN_PRAGMA_ID) WN_pragma(pwn);
01885
01886 if ((p_id == WN_PRAGMA_LOCAL ||
01887 p_id == WN_PRAGMA_LASTLOCAL ||
01888 p_id == WN_PRAGMA_FIRSTPRIVATE) &&
01889 WN_st(pwn) == st &&
01890 WN_offset(pwn) == ofst) {
01891
01892 Is_True (FALSE,
01893 ("Add_Pragma: Conflict trying to add SHARED(%s) pragma",
01894 ST_name(st)));
01895
01896 }
01897 pwn = WN_next(pwn);
01898 }
01899 }
01900 #endif
01901
01902 WN_INSERT_BlockBefore (WN_region_pragmas(region_wn), NULL, shared_pwn);
01903
01904 #ifdef KEY
01905 if (parent_map != WN_MAP_UNDEFINED)
01906 #else
01907 if (parent_map)
01908 #endif
01909 {
01910 WN_MAP_Set(parent_map,
01911 shared_pwn, (void*)WN_region_pragmas(region_wn));
01912 }
01913 }
01914 }
01915 break;
01916 }
01917 case WN_PRAGMA_LOCAL: {
01918
01919 BOOL need_pragma = TRUE;
01920
01921 for (WN_VECTOR::iterator wni = wnv->begin();
01922 wni != wnv->end();
01923 wni++) {
01924
01925
01926
01927
01928
01929 WN *region_wn = *wni;
01930
01931 #ifdef BACK_END
01932 Is_True (WN_opcode(region_wn) == OPC_REGION &&
01933 REGION_is_mp(region_wn),
01934 ("Add_Pragma: expected an MP WHIRL region"));
01935 #endif
01936 WN *pragma_wn = WN_first(WN_region_pragmas(region_wn));
01937
01938 Is_True (WN_opcode(pragma_wn) == OPC_PRAGMA,
01939 ("Add_Pragma: Expected a pragma node"));
01940 WN_PRAGMA_ID pragma = (WN_PRAGMA_ID) WN_pragma(pragma_wn);
01941
01942 if (need_pragma == TRUE &&
01943 (Pragma_is_Parallel_Region(pragma) ||
01944 Pragma_is_Work_Sharing(pragma))) {
01945
01946 WN *local_pwn = WN_CreatePragma (pragma_id, st, ofst, 0);
01947 if (make_compiler_generated) {
01948 WN_set_pragma_compiler_generated(local_pwn);
01949 }
01950 #ifdef KEY
01951 WN *last = WN_last(WN_region_pragmas(region_wn));
01952 if (last &&
01953 WN_opcode(last) == OPC_PRAGMA &&
01954 WN_pragma(last) == WN_PRAGMA_END_MARKER)
01955 WN_INSERT_BlockBefore (WN_region_pragmas(region_wn), last, local_pwn);
01956 else
01957 #endif
01958 WN_INSERT_BlockBefore (WN_region_pragmas(region_wn), NULL, local_pwn);
01959
01960 #ifdef KEY
01961 if (parent_map != WN_MAP_UNDEFINED)
01962 #else
01963 if (parent_map)
01964 #endif
01965 {
01966 WN_MAP_Set(parent_map,local_pwn,(void*)WN_region_pragmas(region_wn));
01967 }
01968 need_pragma = FALSE;
01969 }
01970
01971 if (Pragma_is_Parallel_Region(pragma)) {
01972
01973
01974
01975
01976 need_pragma = TRUE;
01977 }
01978 }
01979 break;
01980 }
01981 default:
01982 Is_True (FALSE, ("Add_Pragma: trying to add unsupported pragma"));
01983 }
01984 }
01985