Open64 (mfef90, whirl2f, and IR tools)  TAG: version-openad; SVN changeset: 916
wn_util.cxx
Go to the documentation of this file.
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 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines