Open64 (mfef90, whirl2f, and IR tools)
TAG: version-openad; SVN changeset: 916
|
00001 /* 00002 00003 Copyright (C) 2000, 2001 Silicon Graphics, Inc. All Rights Reserved. 00004 00005 This program is free software; you can redistribute it and/or modify it 00006 under the terms of version 2 of the GNU General Public License as 00007 published by the Free Software Foundation. 00008 00009 This program is distributed in the hope that it would be useful, but 00010 WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 00012 00013 Further, this software is distributed without any warranty that it is 00014 free of the rightful claim of any third person regarding infringement 00015 or the like. Any license provided herein, whether implied or 00016 otherwise, applies only to this software file. Patent licenses, if 00017 any, provided herein do not apply to combinations of this program with 00018 other software, or any other product whatsoever. 00019 00020 You should have received a copy of the GNU General Public License along 00021 with this program; if not, write the Free Software Foundation, Inc., 59 00022 Temple Place - Suite 330, Boston MA 02111-1307, USA. 00023 00024 Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pky, 00025 Mountain View, CA 94043, or: 00026 00027 http://www.sgi.com 00028 00029 For further information regarding this notice, see: 00030 00031 http://oss.sgi.com/projects/GenInfo/NoticeExplan 00032 00033 */ 00034 00035 00042 #ifdef USE_PCH 00043 #include "common_com_pch.h" 00044 #endif /* USE_PCH */ 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" /* needed to enable simplifier */ 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 /* initialize the stack, it contains tree nodes */ 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 /* note, must be a power of two since fast shift operations are used */ 00072 /* in push operation */ 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 /* pop an element */ 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 /* push an element */ 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 /* Ran out of stack-space, so double the size of the stack */ 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 /* free the stack */ 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 /* walk the tree wn */ 00123 /* initialize the tree iterator */ 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 /* initialize the structured control flow node iterator */ 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 /* walk the statements in the tree node wn */ 00163 /* initialize the statement iterator */ 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 /* walk statements is a valid operation only for scf and 00175 statment tree nodes 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; /* opcode is not a valid one */ 00186 00187 } 00188 00189 00190 /*-------------------------------------------------------------*/ 00191 /* return the next tree node */ 00192 /*-------------------------------------------------------------*/ 00193 extern WN_ITER * 00194 WN_WALK_TreeNext(WN_ITER *wni) 00195 { 00196 INT i; 00197 WN *wn1; 00198 00199 /* wn may be null if the user has deleted a particular node 00200 while walking the tree, in that case it must also set 00201 the current node in the iterator as NULL 00202 */ 00203 00204 if (WN_ITER_wn(wni) != NULL) { 00205 /* handle a BLOCK */ 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 /* the rest are handled by simply pushing their kids on the stack */ 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 /* return the next statement node */ 00231 /*-------------------------------------------------------------*/ 00232 extern WN_ITER *WN_WALK_StmtNext(WN_ITER *wni) 00233 { 00234 INT i; 00235 WN *wn1; 00236 00237 /* WN may be null if the user has deleted a particular node 00238 while walking the tree, in that case it must also set 00239 the current node in the iterator as NULL 00240 */ 00241 00242 if (WN_ITER_wn(wni) != NULL) 00243 { 00244 00245 /* handle a BLOCK */ 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 /* check for other structured control flow */ 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 /* return the next structured control flow node */ 00278 /*-------------------------------------------------------------*/ 00279 extern WN_ITER *WN_WALK_SCFNext(WN_ITER *wni) 00280 { 00281 INT i; 00282 WN *wn1; 00283 00284 /* WN may be null if the user has deleted a particular node 00285 while walking the tree, in that case it must also set 00286 the current node in the iterator as NULL 00287 */ 00288 00289 if (WN_ITER_wn(wni) != NULL) 00290 { 00291 00292 /* handle a BLOCK */ 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 /* check for other structured control flow */ 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 /* Abort a walk, i.e. stop walking and clean up the temporary */ 00330 /* structures that were constructed for the walk */ 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 /* Insert node "in" into a BLOCK and before node "wn" */ 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 /* make sure it is a tree node */ 00352 FmtAssert((in != 0), ("Bad tree node")); 00353 00354 /* make sure the operators are legal */ 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 /* locate the tree node "wn", node "in" must be 00362 inserted before it */ 00363 00364 if (wn != NULL) 00365 { 00366 /* this check since often it is the case that an insert is done after the 00367 last node, just an optimization based on the behavior of insert 00368 operations */ 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 /* if it is the first element in the list, adjust the block pointers */ 00388 if (WN_opcode(in) != OPC_BLOCK ) 00389 { 00390 if ((WN_prev(wn) == NULL)) 00391 WN_first(blck) = in; 00392 00393 /* adjust previous and next pointers */ 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 /* opcode is a block */ 00401 { 00402 if (WN_first(in)) /* check if there are any elements in the block */ 00403 { 00404 first = WN_first(in); 00405 last = WN_last(in); 00406 if ((WN_prev(wn) == NULL)) 00407 WN_first(blck) = first; 00408 00409 /* adjust previous and next pointers */ 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 /* inserting into a block, at the end, wn is null */ 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 /* opcode is a block */ 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 /* Insert node "in" into a BLOCK and after node "wn" */ 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 /* make sure it is a tree node */ 00475 FmtAssert(in != 0, ("Bad tree node")); 00476 00477 /* make sure the operators are legal */ 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 /* locate the tree node "wn", node "in" must be 00486 inserted before it */ 00487 00488 if (wn != NULL) 00489 { 00490 /* this check since often it is the case that an insert is done after the 00491 last node, just an optimization based on the behavior of insert 00492 operations 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 /* if it is the last element in the list, adjust the block pointers */ 00511 if (WN_opcode(in) != OPC_BLOCK) 00512 { 00513 if (WN_next(wn) == NULL) 00514 WN_last(blck) = in; 00515 00516 /* adjust previous and next pointers */ 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 /* opcode is a block */ 00526 { 00527 if (WN_first(in)) /* check if there are any elements in the block */ 00528 { 00529 first = WN_first(in); 00530 last = WN_last(in); 00531 if (WN_next(wn) == NULL) 00532 WN_last(blck) = last; 00533 00534 /* adjust previous and next pointers */ 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 /* inserting into the beginning of a block, wn is null */ 00547 else 00548 { 00549 if (WN_opcode(in) != OPC_BLOCK ) 00550 { 00551 /* if the block to be inserted into is not null */ 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 /* opcode is BLOCK */ 00567 { 00568 first = WN_first(in); 00569 last = WN_last(in); 00570 if (WN_first(in)) /* empty inserted block ? */ 00571 { 00572 if (WN_first(blck) != NULL) /* empty block ? */ 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 /* copy a node, recursive copy */ 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 } /* WN_COPY_Tree */ 00654 00655 00656 #ifdef MONGOOSE_BE 00657 /*-------------------------------------------------------------*/ 00658 /* copy all maps of a WN */ 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 /* copy a node and its maps, recursive copy */ 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 } /* WN_COPY_Tree_With_Map */ 00733 #endif /* MONGOOSE_BE */ 00734 00735 00736 /*-------------------------------------------------------------*/ 00737 /* recursive delete */ 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 /* delete node "wn" from the block, adjust the next, previous */ 00762 /* and block first and last pointers */ 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 /* Is_True_On */ 00771 00772 /* make sure it is a tree node */ 00773 if (wn == NULL) 00774 return; 00775 00776 /* make sure the operators are legal */ 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 /* make sure node "wn" is in the block */ 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 /* Is_True_On */ 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 /* adjust previous and next pointers */ 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 /* remove the item from the parent block */ 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 /* remove the items between first and last from the parent block */ 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 /* WN_LOOP routines */ 00883 /*=============================================================*/ 00884 00885 00886 /*-------------------------------------------------------------*/ 00887 /* Given an IDNAME or LDID, get the st and offset */ 00888 /* If unable to determine them, return var_st = NULL */ 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 /* Determine if the WN reference (IDNAME, LDID) matches the */ 00917 /* var_st and var_ofst exactly. */ 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 /* Given a comparison operator, return the opposite comparison */ 00931 /* as if the operands are swapped. */ 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 /* Determine the loop's induction variable. Returns either an */ 00955 /* IDNAME or LDID */ 00956 /* If unable to determine it, returns NULL. */ 00957 /*-------------------------------------------------------------*/ 00958 extern WN *WN_LOOP_InductionVariable(const WN *loop) 00959 { 00960 /* if this isn't a do_loop, we don't have a clue what the 00961 * induction variable may be. (unless we later get some 00962 * kind of help from someone) 00963 */ 00964 if ( WN_opcode(loop) != OPC_DO_LOOP ) 00965 return NULL; 00966 00967 return WN_index(loop); 00968 } 00969 00970 /*-------------------------------------------------------------*/ 00971 /* Determine the lower bound of the loop, which is basically */ 00972 /* the value stored to the induction variable to initialize */ 00973 /* the loop. */ 00974 /* If unable to determine it, returns NULL. */ 00975 /*-------------------------------------------------------------*/ 00976 00977 extern WN *WN_LOOP_LowerBound( const WN *loop ) 00978 { 00979 WN *iv; /* induction variable */ 00980 ST_IDX iv_st; /* it's symbol table entry */ 00981 WN_OFFSET iv_ofst; /* it's offset from st */ 00982 WN *start; /* initialization */ 00983 OPERATOR start_opr; /* it's operator */ 00984 00985 /* what is the induction variable? needed to know if the init 00986 * code initializes it. 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 /* make sure we're storing to the induction variable */ 00999 if ( WN_st_idx(start) == iv_st && WN_store_offset(start) == iv_ofst ) 01000 return WN_kid0(start); 01001 } 01002 01003 /* todo: handle other kinds of stores? */ 01004 return NULL; 01005 } 01006 01007 /*-------------------------------------------------------------*/ 01008 /* Determine the upper bound of the loop, which is basically */ 01009 /* the value which can not be exceeded (going in either */ 01010 /* direction (positive dir if increment is positive, or */ 01011 /* negative direction is increment is negative */ 01012 /* Also returns the comparison operator to know how the iv is */ 01013 /* related to this upper bound. We canonicalize it so the iv */ 01014 /* is always on the lhs of the comparison, and the upper bound */ 01015 /* is always on the rhs: iv <,<=,==,!=,>=,> upper bound */ 01016 /* If unable to determine it, returns NULL. */ 01017 /*-------------------------------------------------------------*/ 01018 01019 extern WN *WN_LOOP_UpperBound( const WN *loop, OPCODE *compare ) 01020 { 01021 WN *iv; /* induction variable */ 01022 ST_IDX iv_st; /* it's symbol table entry */ 01023 WN_OFFSET iv_ofst; /* it's offset from st */ 01024 WN *end; /* ending condition */ 01025 OPCODE end_opc; /* and its opcode */ 01026 01027 /* what is the induction variable? needed to know if the end 01028 * condition compares against it 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 /* find out if we have a comparison operator for an ending condition 01038 * which we end up returning. 01039 */ 01040 end = WN_end(loop); 01041 end_opc = WN_opcode(end); 01042 if ( ! OPCODE_is_compare(end_opc) ) 01043 return NULL; 01044 01045 /* which kid is the comparing to the iv? */ 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 /* if we get here, we must not have figured out the upper bound */ 01056 *compare = OPCODE_UNKNOWN; 01057 return NULL; 01058 } 01059 01060 /*-------------------------------------------------------------*/ 01061 /* Determine the increment (if is_incr = TRUE) value */ 01062 /* the value which can not be exceeded (going in either */ 01063 /* direction (positive dir if is_incr is true, or negative */ 01064 /* direction if is_incr is false (actually decrements iv) */ 01065 /* If unable to determine it, returns NULL. */ 01066 /*-------------------------------------------------------------*/ 01067 extern WN *WN_LOOP_Increment( const WN *loop, BOOL *is_incr ) 01068 { 01069 WN *iv; /* induction variable */ 01070 ST_IDX iv_st; /* it's symbol table entry */ 01071 WN_OFFSET iv_ofst; /* it's offset from st */ 01072 WN *step; /* increment */ 01073 OPERATOR step_opr; /* and its operator */ 01074 WN *store_val; /* value stored to iv to incr/decr it */ 01075 OPERATOR store_opr; /* and its operator */ 01076 01077 /* what is the induction variable? needed to know if the end 01078 * condition compares against it 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 /* make sure the increment is to the iv */ 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 /* todo: handle more kinds of stores? */ 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 /* at this point, we know the incr/decr is a binary op (add/sub) */ 01111 /* which kid, if any is being added to or subtracted from the iv */ 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 /* if the 2nd kid is the iv, it can only be an add for us to 01117 * recognize it. 01118 */ 01119 if ( store_opr == OPR_ADD ) 01120 return WN_kid0(store_val); 01121 else 01122 return NULL; 01123 } 01124 else { 01125 /* if we get here, must not have a clue */ 01126 return NULL; 01127 } 01128 } 01129 01130 /*-------------------------------------------------------------*/ 01131 /* Determine the trip count, which may be a LDID, or INTCONST */ 01132 /* If unable to determine it, returns NULL. */ 01133 /*-------------------------------------------------------------*/ 01134 extern WN *WN_LOOP_TripCount(const WN *loop) 01135 { 01136 WN *lb; /* lower bound of loop */ 01137 WN *ub; /* upper bound of loop */ 01138 OPCODE ub_compare; /* and comparison op for ub */ 01139 WN *incr; /* loop increment */ 01140 BOOL is_incr; /* and is it increment or decrement */ 01141 WN *trip_cnt; /* calculated trip count tree */ 01142 BOOL saved_fold_enable; /* saved state of simplifier */ 01143 TYPE_ID trip_mtype; /* mtype of tripcount expression */ 01144 01145 /* if this isn't a do_loop, we don't have a clue what the 01146 * tripcount may be. (unless we later get some kind of help 01147 * from someone) 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 /* if we're using floating point, we don't try to figure out the 01165 * trip count. 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 /* force simplification to be enabled */ 01175 saved_fold_enable = WN_Simplifier_Enable(TRUE); 01176 01177 /* calculate trip_cnt = ((ub - lb) + incr) / incr 01178 * (but leave out "+ incr" if comparison is GT or LT) 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 /* reset simplification */ 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 /* Obtain the high-level type of item being accessed. 01210 * It is the WN_ty() for all loads 01211 * It is the WN_ty() for STID 01212 * It is the type pointed to by WN_ty() for ISTORE. 01213 * If field_id is non-zero, it's the FLD_type of the corresponding field 01214 * in WN_ty(). 01215 * See the WHIRL document. 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 /* Obtain the size in bytes of object being accessed. 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 * Given a pragma_id, return true if the pragma is for a parallel 01282 * region, FALSE otherwise. 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 * Given a pragma_id, return true if the pragma is for a work-sharing 01301 * construct, FALSE otherwise. 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 * Given a vector of WHIRL-MP regions innermost to outermost 01323 * (i.e. the innermost MP region is first, outermost is last) 01324 * add a pragma of the given type for the given ST *as required* 01325 * to the MP regions. (The ofst may be needed if we add pregs, 01326 * but should currently be always 0). 01327 * 01328 * The algorithm for adding pragmas 01329 * currently works for LOCAL and SHARED pragmas only. 01330 * Also, if the parent_map is non-NULL, then update the 01331 * parent-map when inserting. 01332 * 01333 * The last argument determines whether the compiler_generated bit 01334 * is set on the pragma. This bit is set to TRUE only when doing 01335 * automatic parallelization using -pfa. 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 /* We currently only handle LOCAL and SHARED pragmas; 01346 * the following algorithm may be different for other pragmas. 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 // Since the default is SHARED (except for pregs), 01355 // an explicit SHARED pragma is needed if 01356 // - we have a preg 01357 // - the user had a DEFAULT(PRIVATE) clause 01358 // 01359 // We basically walk up the WHIRL-MP regions, and for PARALLEL 01360 // regions add an explicit SHARED clause. And do some 01361 // error-checking to boot. 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 // Check that there is no conflict (e.g. LOCAL clause) 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 // iterate over all the elements, first to last 01430 // (i.e. from inner-most enclosing WHIRL-MP-REGION to outermost 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 // reset, since we need to repeat this for outer enclosing 01466 // parallel regions. 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