wn_lower.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 
00036 //-*-c++-*-
00037 
00038 #ifdef USE_PCH
00039 #include "be_com_pch.h"
00040 #endif /* USE_PCH */
00041 #pragma hdrstop
00042 #include <isam.h>
00043 #include <alloca.h>
00044 #include <sys/signal.h>
00045 #include <elf.h>
00046 #include <map>
00047 
00048 #if defined(__GNUC__) && (__GNUC__ == 3) 
00049 # define USING_HASH_SET 1
00050 # include <ext/hash_set>
00051   using namespace __gnu_cxx;
00052 #elif defined(__sgi) && !defined(__GNUC__)
00053 # define USING_HASH_SET 1
00054 # include <hash_set>
00055 #else
00056 # include <set>
00057 #endif
00058 
00059 #include "defs.h"
00060 #include "config.h"
00061 #include "config_asm.h"
00062 #include "config_debug.h"
00063 #include "config_opt.h"
00064 #include "config_targ2.h"
00065 #include "errors.h"
00066 #include "erglob.h"
00067 #include "tracing.h"
00068 #include "glob.h"
00069 #include "timing.h"
00070 #include "stab.h"
00071 #include "strtab.h"
00072 #include "util.h"
00073 #include "wn.h"
00074 #include "wn_util.h"
00075 #include "stblock.h"
00076 #include "data_layout.h"
00077 #include "ir_reader.h"
00078 #include "targ_sim.h"
00079 #include "targ_const.h"
00080 #include "const.h"
00081 #include "ttype.h"
00082 #include "wio.h"
00083 #include "wn_mp.h"
00084 #include "wn_pragmas.h"
00085 #include "wn_simp.h"
00086 #include "opt_alias_interface.h"
00087 #include "wn_lower.h"
00088 #include "region_util.h"
00089 #include "wutil.h"
00090 #include "wn_map.h"
00091 #include "wn_fio.h"
00092 #include "wn_trap.h"
00093 #include "pu_info.h"
00094 #include "w2op.h"
00095 #include "be_symtab.h"
00096 #include "betarget.h"
00097 #include "be_util.h"
00098 #include "opt_cvtl_rule.h"
00099 #include "fb_whirl.h"
00100 #include "intrn_info.h"
00101 #include "upc_symtab_utils.h"
00102 #include "upc_wn_util.h"
00103 
00104 /* My changes are a hack till blessed by Steve. (suneel) */
00105 #define SHORTCIRCUIT_HACK 1
00106 
00107 /* this next header should be after the external declarations in the others */
00108 #include "pragma_weak.h"        /* Alias routines defined in wopt.so */
00109 
00110 /* ====================================================================
00111  *                       Exported Functions
00112  * ====================================================================
00113  */
00114 extern PREG_NUM AssignExpr(WN *, WN *, TYPE_ID);
00115 
00116 extern BOOL lower_is_aliased(WN *, WN *, INT64 size, BOOL defalt);
00117 
00118 extern INT32 compute_copy_alignment(TY_IDX, TY_IDX, INT32 offset);
00119 
00120 extern TYPE_ID compute_copy_quantum(INT32 );
00121 
00122 extern WN *WN_I1const(TYPE_ID, INT64 con);
00123 
00124 /*
00125  * defined in config.c (should be in config.h)
00126  */
00127 extern INT32    MinStructCopyLoopSize;
00128 extern INT32    MinStructCopyMemIntrSize;
00129 
00130 /* ====================================================================
00131  *                       Imported Declarations
00132  * ====================================================================
00133  */
00134 extern WN *emulate(WN *, WN *);
00135 
00136 extern WN *intrinsic_runtime(WN *, WN *);
00137 
00138 extern WN *make_pointer_to_node(WN *, WN *);
00139 
00140 extern char *INTR_intrinsic_name( WN *);
00141 
00142 extern void fdump_dep_tree(FILE *, WN *, struct ALIAS_MANAGER *);
00143 
00144 extern void InitParityMaps(void);
00145 
00146 extern "C" void LNOPreserveMapPair(WN *, WN *, WN *);
00147 
00148 extern "C" void LNOPruneMapsUsingParity(void);
00149 
00150 extern "C" void LNOPrintDepGraph(FILE *);
00151 
00152 extern void enable_tree_freq_display(void);
00153 
00154 extern TYPE_ID INTR_return_mtype(INTRINSIC id);
00155 
00156 extern BE_ST_TAB   Be_st_tab;
00157 
00158 
00159 /* ====================================================================
00160  *                       Forward Declarations
00161  * ====================================================================
00162  */
00163 
00164 static WN *lower_scf(WN *, WN *, LOWER_ACTIONS);
00165 static WN *lower_expr(WN *, WN *, LOWER_ACTIONS);
00166 static WN *lower_store(WN *, WN *, LOWER_ACTIONS);
00167 static WN *lower_call(WN *, WN *, LOWER_ACTIONS);
00168 static WN *lower_intrinsic(WN *, WN *, LOWER_ACTIONS);
00169 static WN *lower_intrinsic_call(WN *, WN *, LOWER_ACTIONS);
00170 static WN *lower_intrinsic_op(WN *, WN *, LOWER_ACTIONS);
00171 static WN *lower_if(WN *, WN *, LOWER_ACTIONS);
00172 static WN *lower_stmt(WN *, WN *, LOWER_ACTIONS);
00173 static WN *lower_entry(WN *, LOWER_ACTIONS);
00174 static WN *lower_eval(WN *, WN *, LOWER_ACTIONS);
00175 static WN *lower_copy_tree(WN *, LOWER_ACTIONS);
00176 static WN *lower_emulation(WN *, WN *, LOWER_ACTIONS, BOOL &intrinsic_lowered);
00177 static WN *lower_mstore(WN *, WN *, LOWER_ACTIONS);
00178 static WN *lower_nary_madd(WN *, WN *, LOWER_ACTIONS);
00179 static WN *lower_madd(WN *, WN *, LOWER_ACTIONS);
00180 static WN *lower_assert(WN *, WN *, LOWER_ACTIONS);
00181 static WN *lower_trapuv(WN *, WN *, LOWER_ACTIONS);
00182 static WN *lower_base_reference(WN *, ST *, INT64, LOWER_ACTIONS);
00183 static WN *lower_base_register(WN *, ST *, INT64, LOWER_ACTIONS);
00184 static WN *lower_dereference(WN *, INT64, ST *, PREG_NUM, LOWER_ACTIONS);
00185 static WN *lower_split_sym_addrs(WN *, INT64, LOWER_ACTIONS);
00186 static WN *improve_Malignment(WN *, WN *, WN *, INT64);
00187 static WN *lower_branch(WN *, WN *, LOWER_ACTIONS);
00188 static WN *lower_branch_condition(BOOL, LABEL_IDX, WN *, WN **, LOWER_ACTIONS);
00189 static WN *lower_conditional(WN *, WN *, LABEL_IDX, LABEL_IDX, BOOL,
00190                              LOWER_ACTIONS);
00191 static WN *lower_tree_height(WN *, WN *, LOWER_ACTIONS);
00192 
00193 
00194 static TY_IDX coerceTY(TY_IDX, TYPE_ID);
00195 static ST *coerceST(const ST *, TYPE_ID);
00196 static ST *coerceST(const ST &, TYPE_ID);
00197 static WN_OFFSET coerceOFFSET(WN *, TYPE_ID, WN_OFFSET);
00198 
00199 
00200 static WN *lower_mload(WN *, WN *, LOWER_ACTIONS);
00201 static void lower_mload_formal(WN *, WN *, PLOC, LOWER_ACTIONS);
00202 static void lower_mload_actual (WN *, WN *, PLOC, LOWER_ACTIONS);
00203 static void lower_complex_emulation(WN *, WN *, LOWER_ACTIONS, WN **, WN **);
00204 static void lower_complex_expr(WN *, WN *, LOWER_ACTIONS, WN **, WN **);
00205 
00206 
00207 static void lower_copy_maps(WN *, WN *, LOWER_ACTIONS);
00208 static void lower_tree_copy_maps(WN *, WN *, LOWER_ACTIONS);
00209 
00210 static INT32 compute_alignment(WN *, INT64);
00211 static TYPE_ID compute_next_copy_quantum(TYPE_ID , INT32);
00212 
00213 static WN* lower_TLD(WN*, WN*, LOWER_ACTIONS);
00214 static WN* lower_TLD_lda(WN*, WN*, LOWER_ACTIONS);
00215 
00216 static TY_IDX struct_addr_ty(WN* tree);
00217 static int find_field_from_offset(TY_IDX ty, unsigned int offset);
00218 
00219 /* ====================================================================
00220  *                       private variables
00221  * ====================================================================
00222  */
00223 static INT   max_region;
00224 static char *current_preg_name;
00225 static UINT16 loop_nest_depth;
00226 static BOOL contains_a_loop;
00227 static struct ALIAS_MANAGER *alias_manager;
00228 #define PARITY_MAP_ARRAY_SIZE 32
00229 static WN_MAP parity_map_array[PARITY_MAP_ARRAY_SIZE];
00230 static WN_MAP lowering_parity_map = 0;
00231 static INT32 parity_map_index = -1;
00232 static LOWER_ACTIONS lowering_actions= 0;
00233 static BOOL save_Div_Split_Allowed ;
00234 
00235 static BOOL traceIO              = FALSE;
00236 static BOOL traceSpeculate       = FALSE;
00237 static BOOL traceAlignment       = FALSE;
00238 static BOOL traceTreeHeight      = FALSE;
00239 static BOOL traceSplitSymOff     = FALSE;
00240 static BOOL traceWoptFinishedOpt = FALSE;
00241 static BOOL traceMload           = FALSE;
00242 // static BOOL traceUplevel = FALSE;
00243 
00244 typedef struct CURRENT_STATE
00245 {
00246   SRCPOS        srcpos;
00247   WN            *stmt;
00248   WN            *function;
00249   LOWER_ACTIONS actions;
00250 } CURRENT_STATE, *CURRENT_STATEp;
00251 
00252 CURRENT_STATE   current_state;
00253 
00254 #define current_srcpos          current_state.srcpos
00255 #define current_stmt            current_state.stmt
00256 #define current_actions         current_state.actions
00257 #define current_function        current_state.function
00258 
00259 typedef enum MSTORE_ACTIONS
00260 {
00261   MSTORE_aggregate,
00262   MSTORE_loop,
00263   MSTORE_intrinsic_bzero,
00264   MSTORE_intrinsic_memset,
00265   MSTORE_intrinsic_bcopy
00266 } MSTORE_ACTIONS;
00267 
00268 static const char * MSTORE_ACTIONS_name(MSTORE_ACTIONS);
00269 
00270 static TYPE_ID Promoted_Mtype[MTYPE_LAST + 1] = {
00271   MTYPE_UNKNOWN,  /* MTYPE_UNKNOWN */
00272   MTYPE_UNKNOWN,  /* MTYPE_B */
00273   MTYPE_I4,       /* MTYPE_I1 */
00274   MTYPE_I4,       /* MTYPE_I2 */
00275   MTYPE_I4,       /* MTYPE_I4 */
00276   MTYPE_I8,       /* MTYPE_I8 */
00277   MTYPE_U4,       /* MTYPE_U1 */
00278   MTYPE_U4,       /* MTYPE_U2 */
00279   MTYPE_U4,       /* MTYPE_U4 */
00280   MTYPE_U8,       /* MTYPE_U8 */
00281   MTYPE_F4,       /* MTYPE_F4 */
00282   MTYPE_F8,       /* MTYPE_F8 */
00283   MTYPE_UNKNOWN,  /* MTYPE_F10 */
00284   MTYPE_UNKNOWN,  /* MTYPE_F16 */
00285   MTYPE_UNKNOWN,  /* MTYPE_STR */
00286   MTYPE_FQ,       /* MTYPE_FQ */
00287   MTYPE_M,        /* MTYPE_M */
00288   MTYPE_C4,       /* MTYPE_C4 */
00289   MTYPE_C8,       /* MTYPE_C8 */
00290   MTYPE_CQ,       /* MTYPE_CQ */
00291   MTYPE_V         /* MTYPE_V */
00292 };
00293 
00294 /* ====================================================================
00295  *                      Private macros
00296  * ====================================================================
00297  */
00298 
00299 #define OPCODE_is_intrinsic(op)                                         \
00300                 ((OPCODE_operator((op)) == OPR_INTRINSIC_CALL) ||       \
00301                 (OPCODE_operator((op)) == OPR_INTRINSIC_OP))
00302 
00303 #define Action(x)                       (actions & (x))
00304 #define NotAction(x)                    (Action(x)==0)
00305 #define RemoveScfAction(x)              (x & ~(LOWER_SCF))
00306 #define RemoveShortCircuitAction(x)     (x & ~(LOWER_SHORTCIRCUIT))
00307 
00308 
00309 #define WN_has_alias_info(x)    (OPCODE_is_load(WN_opcode(x))   ||      \
00310                                  OPCODE_is_store(WN_opcode(x))  ||      \
00311                                  WN_operator_is(x, OPR_PARM))
00312 #define WN_has_offset(x)        (OPCODE_has_offset(WN_opcode(x)))
00313 
00314 #define WN_nary_intrinsic(x)    (WN_operator_is(x, OPR_INTRINSIC_OP) && \
00315                                 ((WN_intrinsic(x)== INTRN_NARY_ADD) ||  \
00316                                  (WN_intrinsic(x)== INTRN_NARY_MPY)))
00317 #define WN_nary_add(x)          (WN_operator_is(x, OPR_INTRINSIC_OP) && \
00318                                  (WN_intrinsic(x)== INTRN_NARY_ADD))
00319 #define WN_nary_mpy(x)          (WN_operator_is(x, OPR_INTRINSIC_OP) && \
00320                                  (WN_intrinsic(x)== INTRN_NARY_MPY))
00321 
00322 #define WN_is_block(x)          (WN_opcode(x) == OPC_BLOCK)
00323 
00324 #define INTRN_is_nary(x)        (((x)==INTRN_NARY_ADD) || ((x)==INTRN_NARY_MPY))
00325 
00326 #define WN_is_commutative(x)    (WN_opcode(x) == OPCODE_commutative_op(WN_opcode(x)))
00327 
00328 #define TY_is_pointer(x)        (TY_kind(x) == KIND_POINTER)
00329 
00330 #define lower_truebr(l,c,b,a)   lower_branch_condition(TRUE,l,c,b,a)
00331 #define lower_falsebr(l,c,b,a)  lower_branch_condition(FALSE,l,c,b,a)
00332 
00333 /* ====================================================================
00334  *
00335  * BOOL mem_offset_must_be_split(WN_OFFSET offset)
00336  * WN_OFFSET mem_offset_hi(WN_OFFSET offset)
00337  * WN_OFFSET mem_offset_lo(WN_OFFSET offset)
00338  *
00339  * Returns TRUE iff <offset> must be split for a target-machine memory
00340  * reference.  If so, mem_offset_hi(offset) returns the high part of
00341  * the split offset, and mem_offset_lo(offset) returns the low part of
00342  * the split offset.
00343  * 
00344  * ==================================================================== */
00345 
00346 #define mem_offset_hi(offset) ((offset) & ~0x7fff)
00347 #define mem_offset_lo(offset) ((offset) & 0x7fff)
00348 
00349 #define mem_offset_must_be_split(offset)                \
00350         (!(-32768 <= (offset) && (offset) < 32768))
00351 
00352 #define mem_offset_2GB(offset)                          \
00353         (!(INT32_MIN <= offset && offset <= INT32_MAX))
00354 
00355 #define PIC_SHARED              (Gen_PIC_Shared || Gen_PIC_Call_Shared)
00356 #define PIC_NONSHARED           (!PIC_SHARED)
00357 
00358 #define ABS(x)                  (((x)<0) ? -(x) : (x))
00359 #define IS_POWER_OF_2(val)      ((val != 0) && ((val & (val-1)) == 0))
00360 
00361 
00362 
00363 
00364 /* ====================================================================
00365  *
00366  * UINT32 compute_offset_alignment(INT32 offset, UINT32 align)
00367  *
00368  * return gcd of offset,align;
00369  * Used for alignment reasons;
00370  * For maximum efficiency, offset should be >= align
00371  *
00372  * ==================================================================== */
00373 UINT32 compute_offset_alignment(INT32 offset, UINT32 align)
00374 {
00375   UINT32 m = ABS(offset);
00376   UINT32 n = align;
00377   while (n != 0) {
00378     INT32 new_n = m % n;
00379     m = n;
00380     n = new_n;
00381   }
00382   return m;
00383 }
00384 
00385 
00386 /* ====================================================================
00387  *
00388  *  The semantics of memset require replicating the byte constant
00389  *  so replicate the constant into a I8/U8 depending on WN_rtype(con)
00390  *
00391  * ==================================================================== */
00392 extern WN *WN_I1const(TYPE_ID type, INT64 con)
00393 {
00394   // assume con is a byte constant, so clear the other bits
00395   // (otherwise replicate will "or" with sign bits).
00396   INT64 n=        con & 0xff;
00397   INT64 maxAlign= MTYPE_alignment(Max_Uint_Mtype);
00398 
00399   if (con)
00400   {
00401     INT64 i;
00402     for(i=1; i<maxAlign; i++)
00403     {
00404       n |=      (n << 8);
00405     }
00406   }
00407 
00408   return WN_Intconst(Mtype_AlignmentClass(maxAlign,
00409                                           MTYPE_type_class(type)), n);
00410 }
00411 
00412 
00413 /* ====================================================================
00414  *
00415  * void push_current_state(WN *tree, STATE *state)
00416  *
00417  * return and set current state
00418  *
00419  * ==================================================================== */
00420 static void setCurrentState(WN *tree, LOWER_ACTIONS actions)
00421 {
00422   if (tree) {
00423     current_stmt =      tree;
00424     current_srcpos =    WN_Get_Linenum(tree);
00425     current_actions =   actions;
00426 
00427     if (WN_opcode(tree) == OPC_FUNC_ENTRY)
00428       current_function = tree;
00429   }
00430 }
00431 
00432 static void setCurrentStateBlockFirst(WN *tree, LOWER_ACTIONS actions)
00433 {
00434   Is_True(WN_opcode(tree) == OPC_BLOCK, ("expected BLOCK node"));
00435 
00436   setCurrentState(WN_first(tree), actions);
00437 }
00438 
00439 static void setCurrentStateBlockLast(WN *tree, LOWER_ACTIONS actions)
00440 {
00441   Is_True(WN_opcode(tree) == OPC_BLOCK, ("expected BLOCK node"));
00442 
00443   setCurrentState(WN_last(tree), actions);
00444 }
00445 
00446 
00447 static CURRENT_STATE pushCurrentState(WN *tree, LOWER_ACTIONS actions)
00448 {
00449   CURRENT_STATE saveState = current_state;
00450 
00451   setCurrentState(tree, actions);
00452 
00453   return saveState;
00454 }
00455 
00456 static void popCurrentState(CURRENT_STATE state)
00457 {
00458   current_state = state;
00459 }
00460     
00461 
00462 /* ====================================================================
00463  *
00464  * BOOL foldConstOffset(WN *con, INT64 offset)
00465  *
00466  * BOOL foldLdaOffset(WN *lda, INT64 offset)
00467  *
00468  * can con and offset be folded to "fit" into a WN_OFFSET (INT32?)
00469  *
00470  * ==================================================================== */
00471 
00472 static BOOL foldConstOffset(WN *con, INT64 offset)
00473 {
00474   if (WN_operator_is(con, OPR_INTCONST))
00475   {
00476     INT64 sum= offset + WN_const_val(con);
00477 
00478     if (INT32_MIN <= sum && sum <= INT32_MAX)
00479       return TRUE;
00480   }
00481   return FALSE;
00482 }
00483 
00484 static BOOL foldLdaOffset(WN *lda, INT64 offset)
00485 {
00486   if (WN_operator_is(lda, OPR_LDA))
00487   {
00488     INT64 sum= offset + WN_lda_offset(lda);
00489 
00490     Is_True((WN_class(lda) != CLASS_PREG), ("lda class is PREG!!!"));
00491 
00492     if (INT32_MIN <= sum && sum <= INT32_MAX)
00493     {
00494       ST  *sym= WN_st(lda);
00495 
00496      /*
00497       * if the offset is greater than the symbol size, we may generate
00498       * a relocation that is out of bounds (ex LFTR). See pv 482353 for
00499       * this rare condition
00500       */
00501       if (ST_class(sym) == CLASS_BLOCK && STB_size(sym) < sum)
00502         return FALSE;
00503 
00504       return TRUE;
00505     }
00506   }
00507   return FALSE;
00508 }
00509 
00510 
00511 
00512 
00513 
00514 
00515 
00516 
00517 /* ====================================================================
00518  *
00519  * WN_OFFSET coerceOFFSET(WN *tree, TYPE_ID realTY, WN_OFFSET offset)
00520  *
00521  * The offset may either be an offset or preg number.
00522  *
00523  * There is an amazing kludge for complex return values where we
00524  * return F0, F2
00525  *
00526  * ==================================================================== */
00527 static WN_OFFSET coerceOFFSET(WN *tree, TYPE_ID realTY, WN_OFFSET offset)
00528 {
00529 
00530   switch (WN_operator(tree))
00531   {
00532   case OPR_ILOAD:
00533   case OPR_ILOADX:
00534   case OPR_ISTORE:
00535   case OPR_ISTOREX:
00536     return offset + MTYPE_RegisterSize(realTY);
00537 
00538   case OPR_LDID:
00539   case OPR_STID:
00540     if (WN_class(tree) == CLASS_PREG)
00541     {
00542      /*
00543       *  amazing kludge
00544       *  for dedicated return register (F0) the ABI defines [F0,F2]
00545       *  as the return values
00546       */
00547       if (Preg_Is_Dedicated(offset) && offset == Float_Preg_Min_Offset)
00548       {
00549           return Float_Preg_Min_Offset + 2;
00550       }
00551       else
00552       {
00553         return offset + Preg_Increment(realTY);
00554       }
00555     }
00556     return offset + MTYPE_RegisterSize(realTY);
00557   }
00558   Fail_FmtAssertion("unexpected complex op (%s)",
00559                     OPCODE_name(WN_opcode(tree)));
00560   /*NOTREACHED*/
00561 }
00562 
00563 /* ====================================================================
00564  *
00565  *
00566  * ==================================================================== */
00567 
00568 static void rename_preg(char *f, char *preg_class)
00569 {
00570   static char name[41];
00571 
00572   name[0] = '\0';
00573   
00574   strncat(name, f, 30);
00575 
00576   if (preg_class)
00577   {
00578     strncat(name, preg_class, 10);
00579   }
00580   current_preg_name = name;
00581 }
00582 
00583 static void rename_reset(void)
00584 {
00585   current_preg_name = NULL;
00586 }
00587 
00588 
00589 static void WN_Set_Flags(WN *src, WN *dst)
00590 {
00591   if (OPCODE_has_flags(WN_opcode(src)))
00592   {
00593     Is_True(OPCODE_has_flags(WN_opcode(dst)), ("expected wn with flags"));
00594     WN_set_flag(dst, WN_flag(src));
00595   }
00596 }
00597 
00598 extern void WN_annotate_intrinsic_flags(INTRINSIC id, ST *sym)
00599 {
00600   if (INTRN_is_pure(id)) {
00601     Set_PU_is_pure(Get_Current_PU());
00602   }
00603   if (INTRN_has_no_side_effects(id)) {
00604     Set_PU_no_side_effects(Get_Current_PU());
00605   }
00606 }
00607 
00608 extern void WN_annotate_call_flags(WN *call, ST *sym)
00609 {
00610   WN_Set_Call_Default_Flags(call);
00611 
00612   if (PU_no_side_effects(Pu_Table[ST_pu(sym)]))
00613   {   
00614     WN_Reset_Call_Non_Data_Mod(call);
00615     WN_Reset_Call_Non_Parm_Mod(call);
00616     WN_Reset_Call_Parm_Mod(call);
00617 
00618   }
00619   if (PU_is_pure(Pu_Table[ST_pu(sym)]))
00620   {
00621     WN_Reset_Call_Non_Data_Mod(call);
00622     WN_Reset_Call_Non_Parm_Mod(call);
00623     WN_Reset_Call_Parm_Mod(call);
00624 
00625     WN_Reset_Call_Non_Data_Ref(call);
00626     WN_Reset_Call_Non_Parm_Ref(call);
00627   }
00628 }
00629 
00630 /* ====================================================================
00631  *
00632  *
00633  * Create a new label with linenum info
00634  *
00635  * ==================================================================== */
00636 static LABEL_IDX NewLabel(void)
00637 {
00638   LABEL_IDX label;
00639   LABEL& lab = New_LABEL(CURRENT_SYMTAB, label);
00640   // create label name
00641   char *name = (char *) alloca (strlen(".L..") + 8 + 8 + 1);
00642   sprintf(name, ".L%s%d%s%d", Label_Name_Separator, Current_PU_Count(), 
00643         Label_Name_Separator, label);
00644   LABEL_Init (lab, Save_Str(name), LKIND_DEFAULT);
00645   return label;
00646 }
00647 
00648 static WN *WN_Label(LABEL_IDX l)
00649 {
00650   WN *label = WN_CreateLabel(ST_IDX_ZERO, l, 0, NULL);
00651   WN_Set_Linenum(label, current_srcpos);
00652   return label;
00653 }
00654 
00655 static WN *WN_NewLabel(void)
00656 {
00657   LABEL_IDX label;
00658   label = NewLabel();
00659   return WN_Label(label);
00660 }
00661 
00662 
00663 
00664 /* ====================================================================
00665  *
00666  *
00667  * Create false/true branch with line info
00668  *
00669  * ==================================================================== */
00670 static WN *WN_Falsebr(LABEL_IDX label, WN *cond)
00671 {
00672   WN *branch = WN_CreateFalsebr(label, cond);
00673   WN_Set_Linenum(branch, current_srcpos);
00674   return branch;
00675 }
00676 
00677 static WN *WN_Truebr(LABEL_IDX label, WN *cond)
00678 {
00679   WN *branch = WN_CreateTruebr(label, cond);
00680   WN_Set_Linenum(branch, current_srcpos);
00681   return branch;
00682 }
00683 
00684 static WN *WN_Goto(LABEL_IDX label)
00685 {
00686   WN *branch =  WN_CreateGoto((ST_IDX) 0, label);
00687   WN_Set_Linenum(branch, current_srcpos);
00688   return branch;
00689 }
00690 
00691 static BOOL expr_is_speculative(WN *tree)
00692 {
00693   if (OPT_Lower_Speculate)
00694   {
00695     BOOL  speculate;
00696 
00697     speculate = WN_Expr_Can_Be_Speculative(tree, alias_manager);
00698     if (traceSpeculate && speculate)
00699     {
00700       DevWarn("WN_lower: found speculative expression: line %d",
00701               Srcpos_To_Line(current_srcpos));
00702     }
00703     return speculate;
00704   }
00705   return FALSE;
00706 }
00707 
00708 /* ====================================================================
00709  *
00710  *
00711  * Create a Nary representation of the expression passed  
00712  *
00713  * ==================================================================== */
00714 
00715 static WN *WN_Nary(WN *tree, WN *x0, WN *x1, WN *x2, WN *x3)
00716 {
00717   TYPE_ID       type = WN_rtype(tree);
00718   OPCODE        op;
00719   INTRINSIC     id;
00720 
00721   op = OPCODE_make_op (OPR_INTRINSIC_OP, type, MTYPE_V);
00722  /*
00723   *  figure out id from tree
00724   */
00725   switch(WN_operator(tree))
00726   {
00727   case OPR_ADD:
00728   case OPR_SUB:
00729     id = INTRN_NARY_ADD;
00730     break;
00731   case OPR_MPY:
00732     id = INTRN_NARY_MPY;
00733     break;
00734   default:      
00735     Is_True(FALSE,("unexpected nary op"));
00736   }
00737 
00738   {
00739     WN          *args[4], **kids;
00740     INT16       i, n, argN;
00741 
00742    /*
00743     *  if the child is a nary op of the same type, integrate it
00744     */
00745     n= argN = 0;
00746     if (x0)
00747       args[n++] = x0;
00748     if (x1)
00749       args[n++] = x1;
00750     if (x2)
00751       args[n++] = x2;
00752     if (x3)
00753       args[n++] = x3;
00754 
00755     for(i=0; i<n; i++)
00756     {
00757       WN *wn = (WN *) args[i];
00758 
00759       if (WN_opcode(wn) == op && WN_intrinsic(wn) == id)
00760         argN += WN_kid_count(wn);
00761       else
00762         argN++;
00763     }
00764 
00765     kids = (WN **) alloca(argN * sizeof(WN *));
00766 
00767     for(i= argN= 0; i<n; i++)
00768     {
00769       WN *wn = args[i];
00770 
00771       if (WN_opcode(wn) == op && WN_intrinsic(wn) == id)
00772       {
00773         INT16  j;
00774 
00775         for(j=0; j< WN_kid_count(wn); j++)
00776           kids[argN++] = WN_kid(wn, j);
00777 
00778         WN_Delete(wn);
00779       }
00780       else
00781       {
00782         kids[argN++] = wn;
00783       }
00784     }
00785 
00786     WN_Delete(tree);
00787     tree = WN_Create_Intrinsic(op, id, argN, kids);
00788   }
00789   return tree;
00790 }
00791 
00792 
00793 
00794 
00795 
00796 /* ====================================================================
00797  *
00798  * WN *WN_ExprToNary(WN *tree, TYPE_ID type)
00799  *
00800  * Create a Nary representation of the expression passed  
00801  *
00802  * The nary representation looks like an INTRINSIC_OP    
00803  * with an id = INTRN_NARY_ADD | INTRN_NARY_MPY         
00804  *
00805  * ==================================================================== */
00806 extern WN *WN_ExprToNaryType(WN *tree, TYPE_ID type, INT count)
00807 {
00808   WN    *l, *r;
00809 
00810   if (count > 16) {
00811         Lmt_DevWarn(1,("WN_ExprToNaryType more than 16 deep, so stop"));
00812         return tree;
00813   }
00814   switch(WN_operator(tree))
00815   {
00816   case OPR_ADD:
00817   case OPR_MPY:
00818     l = WN_kid0(tree);
00819     r = WN_kid1(tree);
00820 
00821     if ((WN_opcode(tree) == WN_opcode(l)) &&
00822         (WN_opcode(tree) == WN_opcode(r)))
00823     {
00824       WN_kid0(l) = WN_ExprToNaryType(WN_kid0(l), type, count+1);
00825       WN_kid1(l) = WN_ExprToNaryType(WN_kid1(l), type, count+1);
00826       WN_kid0(r) = WN_ExprToNaryType(WN_kid0(r), type, count+1);
00827       WN_kid1(r) = WN_ExprToNaryType(WN_kid1(r), type, count+1);
00828 
00829       tree = WN_Nary(tree, WN_kid0(l), WN_kid1(l), WN_kid0(r), WN_kid1(r));
00830       WN_Delete(l);
00831       WN_Delete(r);
00832     }
00833     else if (WN_opcode(tree) == WN_opcode(l))
00834     {
00835       WN_kid0(l) = WN_ExprToNaryType(WN_kid0(l), type, count+1);
00836       WN_kid1(l) = WN_ExprToNaryType(WN_kid1(l), type, count+1);
00837 
00838       tree = WN_Nary(tree, WN_kid0(l), WN_kid1(l), r, NULL);
00839       WN_Delete(l);
00840     }
00841     else if (WN_opcode(tree) == WN_opcode(r))
00842     {
00843       WN_kid0(r) = WN_ExprToNaryType(WN_kid0(r), type, count+1);
00844       WN_kid1(r) = WN_ExprToNaryType(WN_kid1(r), type, count+1);
00845 
00846       tree = WN_Nary(tree, WN_kid0(r), WN_kid1(r), l, NULL);
00847       WN_Delete(r);
00848     }
00849     break;
00850 
00851   case OPR_SUB:
00852     {
00853       l = WN_kid0(tree);
00854       r = WN_kid1(tree);
00855 
00856       if (WN_operator_is(l, OPR_ADD))
00857       {
00858         TYPE_ID rtype = WN_rtype(tree);
00859 
00860         WN  *neg = WN_Neg(rtype, r);
00861 
00862         WN_kid0(l) = WN_ExprToNaryType(WN_kid0(l), type, count+1);
00863         WN_kid1(l) = WN_ExprToNaryType(WN_kid1(l), type, count+1);
00864 
00865         tree = WN_Nary(tree, WN_kid0(l), WN_kid1(l), neg, NULL);
00866         WN_Delete(l);
00867       }
00868     }
00869     break;
00870   }
00871   return tree;
00872 }
00873 
00874 
00875 
00876 /* ====================================================================
00877  *
00878  * WN *WN_NaryToExpr(WN *tree)
00879  *
00880  * The nary representation looks like an INTRINSIC_OP    
00881  * with an id = INTRN_NARY_ADD | INTRN_NARY_MPY         
00882  *
00883  * ==================================================================== */
00884 extern WN *WN_NaryToExpr(WN *tree)
00885 {
00886   if (WN_nary_intrinsic(tree))
00887   {
00888     INT16       i;
00889     WN          *wn = WN_kid0(tree);
00890     INTRINSIC   id = (INTRINSIC) WN_intrinsic(tree);
00891     TYPE_ID     rtype = WN_rtype(tree);
00892     INT         num_parms = WN_kid_count(tree);
00893 
00894     for (i = 1; i < num_parms; i++)
00895     {
00896       WN *actual = WN_kid(tree, i);
00897 
00898       actual = WN_NaryToExpr(actual);
00899 
00900       switch(id)
00901       {
00902       case INTRN_NARY_ADD:
00903         if (WN_operator_is(actual, OPR_NEG))
00904         {
00905           wn = WN_Sub(rtype, wn, WN_kid0(actual));
00906           WN_Delete(actual);
00907         }
00908         else
00909         {
00910           wn = WN_Add(rtype, wn, actual);
00911         }
00912         break;
00913       case INTRN_NARY_MPY:
00914         wn = WN_Mpy(rtype, wn, actual);
00915         break;
00916       }
00917     }
00918     return wn;
00919   }
00920 
00921   return tree;
00922 }
00923 
00924 
00925 
00926 /* ====================================================================
00927  *
00928  * WN *WN_NaryDelete(WN *tree, INT32 n)
00929  *
00930  * Delete the nth kid of a nary intrinsic op
00931  * The rest of the children get moved and the num_kids are updated
00932  *
00933  * ==================================================================== */
00934 
00935 static WN *WN_NaryDelete(WN *tree, INT32 n)
00936 {
00937   INT32 i;
00938   INT32 num_kids= WN_kid_count(tree);
00939 
00940   Is_True((n<num_kids),("cannot delete nth kid"));
00941   Is_True(WN_nary_intrinsic(tree),("expected nary op"));
00942 
00943   for(i=n+1; i<num_kids; i++)
00944   {
00945     WN_actual(tree, i-1) = WN_actual(tree, i);
00946   }
00947   WN_set_kid_count(tree, WN_kid_count(tree)-1);
00948 
00949   return tree;
00950 }
00951 
00952 /* ====================================================================
00953  *
00954  * Get offset field (avoid preg offsets)
00955  * amazing I cannot find anything like this
00956  *
00957  * ==================================================================== */
00958 
00959 extern INT64 lower_offset(WN *tree, INT64 offset)
00960 {
00961   if (WN_has_offset(tree))
00962   {
00963     switch(WN_operator(tree))
00964     {
00965     case OPR_LDA:
00966       offset += WN_lda_offset(tree);
00967       break;
00968     case OPR_MSTORE:
00969     case OPR_ISTORE:
00970     case OPR_ISTOREX:
00971       offset += WN_store_offset(tree);
00972       break;
00973     case OPR_STID:
00974       if (WN_class(tree) != CLASS_PREG)
00975         offset +=       WN_store_offset(tree);
00976       break;
00977     case OPR_LDID:
00978       if (WN_class(tree) != CLASS_PREG)
00979         offset +=       WN_load_offset(tree);
00980       break;
00981     case OPR_MLOAD:
00982     case OPR_ILOAD:
00983     case OPR_ILOADX:
00984       offset += WN_load_offset(tree);
00985       break;
00986     }
00987   }
00988   return offset;
00989 }
00990 
00991 
00992 /* ====================================================================
00993  *
00994  * Compute alignment consistent with address and offset
00995  *
00996  * The new alignment may be improved (or not. see pv [559228])
00997  *
00998  * ==================================================================== */
00999 extern TY_IDX compute_alignment_type(WN *tree, TY_IDX type, INT64 offset)
01000 {
01001   INT32 newAlign;
01002 
01003   newAlign=     compute_alignment(tree, lower_offset(tree, 0));
01004 
01005   newAlign=     compute_offset_alignment(offset, newAlign);
01006 
01007   if (TY_align(type) != newAlign)
01008     Set_TY_align(type, newAlign);
01009 
01010   return type;
01011 }
01012 
01013 static INT32 compute_alignment(WN *tree, INT64 offset)
01014 {
01015   WN      *addr;
01016   TY_IDX   type;
01017   INT32    align, align0, align1;
01018 
01019   switch(WN_operator(tree))
01020   {
01021   case OPR_MSTORE:
01022     type = TY_pointed(Ty_Table[WN_ty(tree)]);
01023     addr = WN_kid1(tree);
01024 
01025     if (WN_has_sym(addr) && WN_ty(addr))
01026     {
01027       return compute_alignment(addr, offset+WN_lda_offset(addr));
01028     }
01029     align = TY_align(type);
01030     break;
01031 
01032   case OPR_MLOAD:
01033     type = TY_pointed(Ty_Table[WN_ty(tree)]);
01034     addr = WN_kid0(tree);
01035 
01036     if (WN_has_sym(addr) && WN_ty(addr))
01037     {
01038       return compute_alignment(addr, offset+WN_lda_offset(addr));
01039     }
01040     align = TY_align(type);
01041     break;
01042 
01043   case OPR_ILOAD:
01044   case OPR_ILOADX:
01045   case OPR_LDA:
01046   case OPR_LDID:
01047     type = WN_ty(tree);
01048     if (TY_is_pointer(Ty_Table[type]))
01049     {
01050       type = TY_pointed(Ty_Table[type]);
01051     }
01052     else
01053     {
01054       return 1;
01055     }
01056     align = TY_align(type);
01057     break;
01058 
01059   case OPR_ARRAY:
01060     align=      compute_alignment(WN_array_base(tree), offset);
01061     offset=     WN_element_size(tree);
01062     break;
01063 
01064   case OPR_ADD:
01065   case OPR_SUB:
01066     align0=     compute_alignment(WN_kid0(tree), 0);
01067     align1=     compute_alignment(WN_kid1(tree), 0);
01068     align=      MIN(align0, align1);
01069     break;
01070 
01071   case OPR_INTCONST:
01072     offset=     WN_const_val(tree);
01073     align=      MTYPE_alignment(Max_Uint_Mtype);
01074     break;
01075 
01076   default:
01077     if (traceAlignment)
01078     {
01079       DevWarn("compute_alignment(): unrecognized WN returning alignment of 1");
01080     }
01081     return 1;
01082   }
01083 
01084   align=        compute_offset_alignment(offset, MAX(1, align));
01085 
01086   if (WN_has_sym(tree))
01087   {
01088     INT32       newAlign = align;
01089     ST          *sym = WN_st(tree);
01090 
01091     if (WN_operator_is(tree, OPR_LDA))
01092     {
01093       newAlign= ST_alignment(sym);
01094     }
01095     else if (WN_operator_is(tree, OPR_LDID)     &&
01096              ST_type(sym)                       &&
01097              TY_is_pointer(Ty_Table[ST_type(sym)]))
01098     {
01099       newAlign = TY_align( TY_pointed(Ty_Table[ST_type(sym)]));
01100     }
01101 
01102     align = compute_offset_alignment(offset, MAX(newAlign, align));
01103   }
01104   return align;
01105 }
01106 
01107 
01108 /* ====================================================================
01109  *
01110  * BOOL lower_is_aliased(WN *wn1, WN *wn2, INT64 size)
01111  *
01112  * Are these addresses aliased? (used in bcopy/memcpy/memmove)
01113  *
01114  * ==================================================================== */
01115 extern BOOL lower_is_aliased(WN *wn1, WN *wn2, INT64 size)
01116 {
01117   if (alias_manager &&
01118       Valid_alias(alias_manager, wn1) &&
01119       Valid_alias(alias_manager, wn2) &&
01120       (Aliased(alias_manager, wn1, wn2) == NOT_ALIASED))
01121   {
01122     return FALSE;
01123   }
01124 
01125   if (WN_operator_is(wn1, OPR_LDA) && WN_operator_is(wn2, OPR_LDA)) {
01126     ST  *sym1 = WN_st(wn1);
01127     ST  *sym2 = WN_st(wn2);
01128     ST  *base1, *base2;
01129     INT64 newoffset1, newoffset2;
01130 
01131     if (sym1 != sym2) return FALSE;
01132 
01133     Base_Symbol_And_Offset_For_Addressing(
01134                     sym1, WN_lda_offset(wn1), &base1, &newoffset1);
01135     Base_Symbol_And_Offset_For_Addressing(
01136                     sym2, WN_lda_offset(wn2), &base2, &newoffset2);
01137 
01138     if (ABS(newoffset1 - newoffset2) >= size) return FALSE;
01139   }
01140 
01141   return TRUE;
01142 }
01143 
01144 
01145 
01146 /* ====================================================================
01147  *
01148  * WN *lower_copy_tree(WN *tree, INT32 n)
01149  *
01150  * Copy the tree and duplicate the maps
01151  *
01152  * ==================================================================== */
01153 
01154 static void lower_tree_copy_maps(WN *tree, WN *dup, LOWER_ACTIONS actions)
01155 {
01156   if (tree == NULL)
01157   {
01158     Is_True((dup == NULL),("inconsistency while copying trees"));
01159   }
01160   Is_True((WN_opcode(tree) == WN_opcode(dup)),
01161           ("inconsistency while copying trees"));
01162 
01163   if (WN_has_map_id(tree) && WN_has_alias_info(tree))
01164   {
01165     lower_copy_maps(tree, dup, actions);
01166   }
01167         
01168   if (WN_opcode(tree) == OPC_BLOCK)
01169   {
01170     WN  *treeStmt = WN_first(tree);
01171     WN  *dupStmt  = WN_first(dup);
01172 
01173     while(treeStmt)
01174     {
01175       lower_tree_copy_maps(treeStmt, dupStmt, actions);
01176       treeStmt = WN_next(treeStmt);
01177       dupStmt  = WN_next(dupStmt);
01178     }
01179   }
01180   else
01181   {
01182     INT n;
01183     for(n = 0; n < WN_kid_count(tree); n++)
01184     {
01185       if (WN_kid(tree, n))
01186       {
01187         lower_tree_copy_maps(WN_kid(tree,n), WN_kid(dup,n), actions);
01188       }
01189     }
01190   }
01191 }
01192 
01193 static WN *lower_copy_tree(WN *tree, LOWER_ACTIONS actions)
01194 {
01195   WN  *dup;
01196 
01197   dup = WN_COPY_Tree(tree);
01198 
01199   lower_tree_copy_maps(tree, dup, actions);
01200 
01201   return dup;
01202 }
01203 
01204 /* ====================================================================
01205  *
01206  * PREG_NUM AssignPregExprPos(WN *block, WN *tree, TY_IDX ty, SRCPOS srcpos,
01207  *                            LOWER_ACTIONS actions)
01208  *
01209  * PREG_NUM AssignExprPos(WN *block, WN *tree, TYPE_ID type, SRCPOS srcpos,
01210  *                        LOWER_ACTIONS)
01211  *
01212  * PREG_NUM AssignExpr(WN *block, WN *tree, TYPE_ID type)
01213  *
01214  * PREG_NUM AssignExprTY(WN *block, WN *tree, TY_IDX ty)
01215  *
01216  * Allocate a preg of type ST_type(preg) and assign expression tree to it
01217  * and attach it to block. 
01218  *
01219  * Assign srcpos (if not NULL)
01220  *
01221  * ==================================================================== */
01222 
01223 static PREG_NUM AssignPregExprPos(WN *block, WN *tree, TY_IDX ty,
01224                                   SRCPOS srcpos, LOWER_ACTIONS actions)
01225 {
01226   PREG_NUM      pregNo;
01227   TYPE_ID       type;
01228   ST            *preg = MTYPE_To_PREG(TY_mtype(Ty_Table[ty]));
01229 
01230   Is_True((WN_operator_is(tree, OPR_PARM)==FALSE),("bad parm"));
01231 
01232   type = TY_mtype(Ty_Table[ty]);
01233   pregNo = Create_Preg(type, current_preg_name);
01234 
01235   {
01236     WN  *stBlock, *stid;
01237 
01238     stid = WN_Stid(type, pregNo, preg, ty, tree);
01239 
01240     if (srcpos)
01241       WN_Set_Linenum (stid, srcpos);
01242 
01243     stBlock = WN_CreateBlock();
01244 
01245    /*
01246     *   This lowering may leed to infinite regress if the
01247     *   children cannot be lowered (and are allocated a temp, for example) 
01248     */
01249     if (actions)
01250       stid = lower_store(stBlock, stid, actions);
01251 
01252     WN_INSERT_BlockLast(stBlock, stid);
01253 
01254     WN_INSERT_BlockLast(block, stBlock);
01255   }
01256 
01257   return pregNo;
01258 }
01259 
01260 
01261 extern PREG_NUM AssignExprTY(WN *block, WN *tree, TY_IDX type)
01262 {
01263   return AssignPregExprPos(block, tree, type, current_srcpos,
01264                            current_actions);
01265 }
01266 
01267 extern PREG_NUM AssignExpr(WN *block, WN *tree, TYPE_ID type)
01268 {
01269   return AssignPregExprPos(block, tree, MTYPE_To_TY(type), current_srcpos,
01270                            current_actions);
01271 }
01272 
01273 
01274 
01275 static BOOL WN_unconditional_goto(WN *tree)
01276 {
01277   switch(WN_operator(tree))
01278   {
01279   case OPR_GOTO:
01280   case OPR_REGION_EXIT:
01281   case OPR_RETURN:
01282   case OPR_RETURN_VAL:
01283     return TRUE;
01284   }
01285   return FALSE;
01286 }
01287 
01288 
01289 
01290 
01291 /* ====================================================================
01292  *
01293  * PARITY WN_parity(WN *tree)
01294  *
01295  * return the PARITY associated with a tree.
01296  *
01297  * Parity encapsulates dependence information, like complex real, imag
01298  * ==================================================================== */
01299 
01300 PARITY WN_parity(WN *tree)
01301 {
01302   if (WN_map_id(tree) != -1)
01303   {
01304     INT32       map;
01305 
01306     Is_True((lowering_parity_map != 0), ("parity map not initialized"));
01307     map = WN_MAP32_Get(lowering_parity_map, tree);
01308    
01309     if (map!=0)
01310       return (PARITY) map;
01311   }
01312   return PARITY_UNKNOWN;
01313 }
01314 
01315 BOOL WN_parity_independent(WN *wn1, WN *wn2)
01316 {
01317 
01318   if (wn1 == NULL               ||
01319       wn2 == NULL               ||
01320       WN_map_id(wn1) == -1      ||
01321       WN_map_id(wn2) == -1)
01322     return FALSE;
01323 
01324   {
01325     PARITY p1 = WN_parity(wn1);
01326     PARITY p2 = WN_parity(wn2);
01327 
01328    return (p1 & p2) ? FALSE : TRUE;
01329   }
01330 }
01331 
01332 
01333 
01334 
01335 /* ====================================================================
01336  *
01337  *      MAP PRESERVATION
01338  *
01339  *
01340  * void lower_copy_maps(WN *orig, WN *tree, LOWER_ACTIONS action)
01341  *
01342  * void lower_complex_maps(WN *orig, WN *real, WN *imag, LOWER_ACTIONS action)
01343  *
01344  * void lower_quad_maps(WN *orig, WN *hipart, WN *lopart, LOWER_ACTIONS action)
01345  *
01346  *
01347  *  copy alias information to tree
01348  *
01349  * ==================================================================== */
01350 
01351 static void lower_maps_init(LOWER_ACTIONS actions)
01352 {
01353 
01354 }
01355 
01356 static void lower_maps_reset(LOWER_ACTIONS actions)
01357 {
01358   if (Action(LOWER_DEPGRAPH_MAPS))
01359   {
01360     LNOPruneMapsUsingParity();
01361   }
01362 }
01363 
01364 static void lower_map(WN *tree, LOWER_ACTIONS actions)
01365 {
01366   if (Action(LOWER_ALIAS_MAPS))
01367   {
01368     if (alias_manager)
01369     {
01370       if (Valid_alias(alias_manager, tree) == FALSE)
01371         Create_alias(alias_manager, tree);
01372     }
01373   }
01374 }
01375 
01376 static void lower_copy_maps(WN *orig, WN *tree, LOWER_ACTIONS actions)
01377 {
01378   if (orig == NULL)
01379     return;
01380 
01381  /*
01382   *     The tree may no longer be valid at the point of call
01383   *     (ie. may be deleted) so we must check validity
01384   */
01385   if (WN_has_map_id(orig))
01386   {
01387     if (WN_has_alias_info(orig) &&
01388         WN_has_alias_info(tree))
01389     {
01390       if (Action(LOWER_PREFETCH_MAPS))
01391       {
01392         WN_CopyMap(tree, WN_MAP_PREFETCH, orig);
01393       }
01394       if (Action(LOWER_ALIAS_MAPS))
01395       {
01396         if (alias_manager)
01397           Copy_alias_info(alias_manager, orig, tree);
01398       }
01399     }
01400   }
01401   WN_Set_Flags(orig, tree);
01402 }
01403 
01404 
01405 /*
01406  * If an original node has a TY with an f90_pointer attribute on it, copy it
01407  * to the TYs of the new nodes. node2 might be NULL (for cases in which we
01408  * only produce one new node)
01409  */
01410 static void lower_copy_tys (WN *orig, WN *node1, WN *node2) 
01411 {
01412   TY_IDX  ty;
01413 
01414   if (WN_operator_is(orig, OPR_ILOAD))
01415   {
01416     ty =        WN_load_addr_ty(orig);
01417 
01418     if (TY_is_f90_pointer(Ty_Table[ty]))
01419     {
01420       if (node1 && WN_operator_is(node1, OPR_ILOAD))
01421         WN_set_load_addr_ty(node1, ty);
01422 
01423       if (node2 && WN_operator_is(node2, OPR_ILOAD))
01424         WN_set_load_addr_ty(node2, ty);
01425     }
01426   }
01427   else if (WN_operator_is(orig, OPR_ISTORE))
01428   {
01429     ty =        WN_ty(orig);
01430     if (TY_is_f90_pointer(Ty_Table[ty]))
01431     {
01432       if (node1 && WN_operator_is(node1, OPR_ISTORE))
01433         WN_set_ty(node1, ty);
01434       if (node2 && WN_operator_is(node2, OPR_ISTORE))
01435         WN_set_ty(node2, ty);
01436     }
01437   }
01438 }
01439 
01440 
01441 static void lower_quad_maps(WN *orig, WN *hipart, WN *lopart,
01442                             LOWER_ACTIONS actions)
01443 {
01444   lower_copy_maps(orig, hipart, actions);
01445   lower_copy_maps(orig, lopart, actions);
01446   lower_copy_tys(orig,hipart,lopart);
01447 
01448   if (Action(LOWER_DEPGRAPH_MAPS))
01449   {
01450     LNOPreserveMapPair(orig, hipart, lopart);
01451   }
01452 
01453   if (Action(LOWER_PARITY_MAPS))
01454   {
01455     WN_MAP32_Set(lowering_parity_map, hipart, PARITY_QUAD_HI);
01456     WN_MAP32_Set(lowering_parity_map, lopart, PARITY_QUAD_LO);
01457   }
01458 }
01459 
01460 static void lower_complex_maps(WN *orig, WN *real, WN *imag,
01461                                LOWER_ACTIONS actions)
01462 {
01463   lower_copy_maps(orig, real, actions);
01464   lower_copy_maps(orig, imag, actions);
01465   lower_copy_tys(orig,real,imag);
01466 
01467   if (Action(LOWER_DEPGRAPH_MAPS))
01468   {
01469     LNOPreserveMapPair(orig, real, imag);
01470   }
01471 
01472   if (Action(LOWER_PARITY_MAPS))
01473   {
01474     WN_MAP32_Set(lowering_parity_map, real, PARITY_COMPLEX_REAL);
01475     WN_MAP32_Set(lowering_parity_map, imag, PARITY_COMPLEX_IMAG);
01476   }
01477 
01478 }
01479 
01480 static WN *add_to_base(WN **base, WN *tree)
01481 {
01482   if (*base)
01483   {
01484     return WN_Add(Pointer_type, *base, tree);
01485   }
01486   return tree;
01487 }
01488 
01489 static WN *sub_from_base(WN **base, WN *tree)
01490 {
01491   if (*base)
01492   {
01493     return WN_Sub(Pointer_type, *base, tree);
01494   }
01495   return tree;
01496 }
01497 
01498 static BOOL baseAddress(WN *tree)
01499 {
01500   switch(WN_operator(tree))
01501   {
01502   case OPR_LDA:
01503   case OPR_LDID:
01504   case OPR_ILOAD:
01505   case OPR_ILOADX:
01506     return TRUE;
01507   }
01508   return FALSE;
01509 }
01510 
01511 
01512 /* ====================================================================
01513  *
01514  * void lower_to_base_index(WN *addr, WN **base, WN **index) 
01515  *
01516  * Pattern match an address and create a bad/index for it
01517  *
01518  * Before this routine we would store the address in a preg
01519  * and use it (twice).  This would require the ST being marked
01520  * addr_taken_stored (very bad)
01521  *
01522  * This is getting worse and worse. Now the routine is recursive
01523  * for OPR_ADD.
01524  * 
01525  * 17 Dec 1998, R. Shapiro - Add a default case so that this routine never 
01526  *   fails. At worst, the trees get a little bigger. 
01527  *
01528  * ==================================================================== */
01529 
01530 static void lower_to_base_index(WN *addr, WN **base, WN **index) 
01531 {
01532   WN    *l, *r;
01533 
01534   switch (WN_operator(addr))
01535   {
01536   case OPR_ARRAY:
01537     *base  = add_to_base(base, WN_array_base(addr));
01538     *index = add_to_base(index, addr);
01539     WN_array_base(addr) = WN_Zerocon(WN_rtype(addr));
01540     break;
01541 
01542   case OPR_ADD:
01543     l = WN_kid0(addr);
01544     r = WN_kid1(addr);
01545 
01546     if (baseAddress(l))
01547     {
01548       *base  = add_to_base(base, l);
01549       *index = add_to_base(index, r);
01550     }
01551     else if (baseAddress(r))
01552     {
01553       *base  = add_to_base(base, r);
01554       *index = add_to_base(index, l);
01555     }
01556     else if (WN_operator_is(r, OPR_ARRAY))
01557     {
01558       *base  = add_to_base(base, WN_array_base(r));
01559       WN_array_base(r) = WN_Zerocon(WN_rtype(r));
01560       *index = add_to_base(index, addr);
01561     }
01562     else if (WN_operator_is(l, OPR_ARRAY))
01563     {
01564       *base  = add_to_base(base, WN_array_base(l));
01565       WN_array_base(l) = WN_Zerocon(WN_rtype(l));
01566       *index = add_to_base(index, addr);
01567     }
01568     else if ((WN_operator_is(r, OPR_ADD)  ||  WN_operator_is(r, OPR_SUB))
01569              && WN_operator_is(l, OPR_INTCONST))
01570     {
01571       lower_to_base_index(r, base, index);
01572       *index = add_to_base(index, l);
01573     }
01574     else if ((WN_operator_is(l, OPR_ADD)  ||  WN_operator_is(l, OPR_SUB)) 
01575              && WN_operator_is(r, OPR_INTCONST))
01576     {
01577       lower_to_base_index(l, base, index);
01578       *index = add_to_base(index, r);
01579     }
01580     else
01581     {
01582       // Give up
01583       *base  = add_to_base(base, addr);
01584       *index = add_to_base(index, WN_Zerocon(WN_rtype(addr)));
01585     }
01586     break;
01587 
01588   case OPR_SUB:
01589     l = WN_kid0(addr);
01590     r = WN_kid1(addr);
01591 
01592     if (baseAddress(l))
01593     {
01594       *base  = add_to_base(base, l);
01595       *index = sub_from_base(index, r);
01596     }
01597     else if (baseAddress(r))
01598     {
01599       *base  = sub_from_base(base, r);
01600       *index = add_to_base(index, l);
01601     }
01602     else if (WN_operator_is(r, OPR_ARRAY))
01603     {
01604       *base  =  sub_from_base(base, WN_array_base(r));
01605       WN_array_base(r) = WN_Zerocon(WN_rtype(r));
01606       *index =  add_to_base(index, addr);
01607     }
01608     else if (WN_operator_is(l, OPR_ARRAY))
01609     {
01610       *base  = add_to_base(base, WN_array_base(l));
01611       WN_array_base(l) = WN_Zerocon(WN_rtype(l));
01612       *index = add_to_base(index, addr);
01613     }
01614     else if ((WN_operator_is(r, OPR_ADD) ||  WN_operator_is(r, OPR_SUB))
01615              && WN_operator_is(l, OPR_INTCONST))
01616     {
01617       lower_to_base_index(r, base, index);
01618       *base  = WN_Neg(WN_rtype(*base),*base);
01619       *index = sub_from_base(&l,*index);
01620     }
01621     else if ((WN_operator_is(l, OPR_ADD) || WN_operator_is(l, OPR_SUB)) 
01622              && WN_operator_is(r, OPR_INTCONST))
01623     {
01624       lower_to_base_index(l, base, index);
01625       *index = sub_from_base(index, r);
01626     }
01627     else
01628     {
01629       // Give up
01630       *base  = add_to_base(base, addr);
01631       *index = add_to_base(index, WN_Zerocon(WN_rtype(addr)));
01632     }
01633     break;
01634   default:
01635     // Give up
01636     *base  = add_to_base(base, addr);
01637     *index = add_to_base(index, WN_Zerocon(WN_rtype(addr)));
01638     break;
01639   }
01640 }
01641 
01642 
01643 /*
01644  * Describe a leaf expression (see Make_Leaf/Load_Leaf).
01645  */
01646 typedef enum {LEAF_IS_CONST, LEAF_IS_INTCONST, LEAF_IS_PREG} LEAF_KIND;
01647 typedef struct {
01648   LEAF_KIND kind;
01649   TYPE_ID type;
01650   union {
01651     PREG_NUM n;
01652     INT64 intval;
01653     TCON tc;
01654   } u;
01655 } LEAF;
01656 
01657 /* ====================================================================
01658  *
01659  * LEAF Make_Leaf(WN *block, WN *tree, TYPE_ID type)
01660  *
01661  * Make an aribtrary expression tree into a leaf.
01662  * If the expression is an integer or floating point constant
01663  * no transformation is made. However, other expressions are stored
01664  * into a PREG.
01665  *
01666  * Make_Leaf is used in place of AssignExpr when performing a sort
01667  * of "poor man's" CSE, and you want to avoid creating unnecessary
01668  * PREGs for constants (which can also thwart the simplifier).
01669  *
01670  * ==================================================================== */
01671 
01672 static LEAF Make_Leaf(WN *block, WN *tree, TYPE_ID type)
01673 {
01674   LEAF leaf;
01675   leaf.type = type;
01676   switch (WN_operator(tree)) {
01677   case OPR_CONST:
01678     leaf.kind = LEAF_IS_CONST;
01679     leaf.u.tc = Const_Val(tree);
01680     WN_Delete(tree);
01681     break;
01682   case OPR_INTCONST:
01683     leaf.kind = LEAF_IS_INTCONST;
01684     leaf.u.intval = WN_const_val(tree);
01685     WN_Delete(tree);
01686     break;
01687   default:
01688     leaf.kind = LEAF_IS_PREG;
01689     leaf.u.n = AssignExpr(block, tree, type);
01690     break;
01691   }
01692   return leaf;
01693 }
01694 
01695 /* ====================================================================
01696  *
01697  * WN *Load_Leaf(const LEAF &leaf)
01698  *
01699  * Generate whirl to load the value of a leaf expression created by
01700  * Make_Leaf().
01701  *
01702  * ==================================================================== */
01703 
01704 static WN *Load_Leaf(const LEAF &leaf)
01705 {
01706   switch (leaf.kind) {
01707   case LEAF_IS_CONST:
01708     return Make_Const(leaf.u.tc);
01709   case LEAF_IS_INTCONST:
01710     return WN_CreateIntconst(OPR_INTCONST, leaf.type, MTYPE_V, leaf.u.intval);
01711   case LEAF_IS_PREG:
01712     return WN_LdidPreg(leaf.type, leaf.u.n);
01713   }
01714   FmtAssert(FALSE, ("unhandled leaf kind in Load_Leaf"));
01715   /*NOTREACHED*/
01716 }
01717 
01718 /* ====================================================================
01719  *
01720  * void lower_complex_expr(WN *block, WN *tree, LOWER_ACTIONS actions,
01721  *                               WN **realpart, WN **imagpart)
01722  *
01723  * Split complex-type expression <tree> into its lowered real and
01724  * imaginary parts.  <actions> must include LOWER_COMPLEX.  Note that
01725  * like the other lowering functions, this one destroys <tree>.  Upon
01726  * return, *<realpart> points to the real part, and *<imagpart> points
01727  * to the imaginary part.
01728  *
01729  * ==================================================================== */
01730 
01731 static void lower_complex_expr(WN *block, WN *tree, LOWER_ACTIONS actions,
01732                                WN **realpart, WN **imagpart)
01733 {
01734   TYPE_ID       type;
01735 
01736 
01737   Is_True(OPCODE_is_expression(WN_opcode(tree)),
01738           ("expected expression node, not %s", OPCODE_name(WN_opcode(tree))));
01739   Is_True(Action(LOWER_COMPLEX), ("actions does not contain LOWER_COMPLEX"));
01740   Is_True((MTYPE_is_complex(WN_rtype(tree))),
01741           ("expected complex-type node, not %s",
01742            OPCODE_name(WN_opcode(tree))));
01743   type = Mtype_complex_to_real(WN_rtype(tree));
01744 
01745  /*
01746   *  Complex Arithmetic Notation
01747   *
01748   *  Let R(c) = real part of c
01749   *      I(c) = imaginary part of c
01750   *
01751   *  then, if z is complex it can be represented as follows
01752   *
01753   *      z= R(z) + I(z)i
01754   *
01755   */
01756   switch (WN_operator(tree))
01757   {
01758   case OPR_LDID:
01759     {
01760      /*
01761       *  we must create a new ST of type real
01762       *  we implicitly assume the storage of complex is
01763       *          z =  {  R(z) , I(z) }
01764       */
01765       TY_IDX    beTY   = MTYPE_To_TY(type);
01766       WN_OFFSET offset = WN_load_offset(tree);
01767 
01768       if (WN_class(tree) == CLASS_CONST && offset == 0)
01769       {
01770         TCON    val = WN_val(tree);
01771         TYPE_ID valType = WN_val_type(tree);
01772 
01773         if (WN_rtype(tree) == valType)
01774         {
01775           *realpart = Make_Const( Extract_Complex_Real(val));
01776           *imagpart = Make_Const( Extract_Complex_Imag(val));
01777           break;
01778         }
01779       }
01780 
01781       *realpart = WN_Ldid(type, offset,
01782                           coerceST(WN_st(tree), type),
01783                           beTY);
01784 
01785       *imagpart = WN_Ldid(type,
01786                           coerceOFFSET(tree, type, offset),
01787                           coerceST(WN_st(tree), type),
01788                           beTY);
01789     }
01790     break;
01791 
01792   case OPR_ILOAD:
01793     {
01794      /*
01795       *  we implicitly assume the storage of complex is
01796       *    z =  {  R(z) , I(z) }
01797       *
01798       *  The LOWER_BASE_INDEX will try to split the address into a
01799       *  base and index. The index is put in a preg (and reused) while
01800       *  the base is cloned.
01801       */
01802       WN_OFFSET offset = WN_load_offset(tree);
01803 
01804       if (Action(LOWER_BASE_INDEX))
01805       {
01806         WN      *addr, *base, *index;
01807         LEAF    indexN;
01808 
01809         base = index=   NULL;
01810         lower_to_base_index(WN_kid0(tree), &base, &index) ;
01811 
01812         base = lower_expr(block, base, actions);
01813         index = lower_expr(block, index, actions);
01814 
01815         indexN = Make_Leaf(block, index, Pointer_type);
01816         
01817         addr = WN_Add(Pointer_type,
01818                       Load_Leaf(indexN),
01819                       lower_copy_tree(base, actions)); 
01820 
01821         *realpart = WN_Iload(type,
01822                              offset,
01823                              coerceTY(WN_ty(tree), type),
01824                              addr);
01825 
01826         addr = WN_Add(Pointer_type, Load_Leaf(indexN), base);
01827 
01828         *imagpart = WN_Iload(type,
01829                              coerceOFFSET(tree, type, offset),
01830                              coerceTY(WN_ty(tree), type),
01831                              addr);
01832       }
01833       else
01834       {
01835         WN      *addr;
01836         LEAF    addrN;
01837         
01838         addr = lower_expr(block, WN_kid0(tree), actions);
01839         
01840         addrN = Make_Leaf(block, addr, Pointer_type);
01841         
01842         *realpart = WN_Iload(type,
01843                              offset,
01844                              coerceTY(WN_ty(tree), type),
01845                              Load_Leaf(addrN));
01846         
01847         *imagpart = WN_Iload(type,
01848                              coerceOFFSET(tree, type, offset),
01849                              coerceTY(WN_ty(tree), type),
01850                              Load_Leaf(addrN));
01851       }
01852       lower_complex_maps(tree, *realpart, *imagpart, actions);
01853     }
01854     break;
01855 
01856   case OPR_ILOADX:
01857     Is_True(FALSE, ("unexpected complex ILOADX"));
01858     break;
01859 
01860   case OPR_NEG:
01861     {
01862      /*
01863       *    -z  = -R(z) + -I(z)i
01864       */
01865       WN        *rz, *iz;
01866 
01867       lower_complex_expr(block, WN_kid0(tree), actions, &rz, &iz);
01868       *realpart = WN_Neg( type, rz);
01869       *imagpart = WN_Neg( type, iz);
01870 
01871     }
01872     break;
01873 
01874   case OPR_ADD:
01875     {
01876       WN        *rz, *rw, *iz, *iw;
01877      /*
01878       *    z + w = (R(z) + R(w)) + (I(z) + I(w))i
01879       */
01880 
01881       lower_complex_expr(block, WN_kid0(tree), actions, &rz, &iz);
01882       lower_complex_expr(block, WN_kid1(tree), actions, &rw, &iw);
01883  
01884       *realpart = WN_Add( type, rz, rw);
01885       *imagpart = WN_Add( type, iz, iw);
01886     }
01887     break;
01888 
01889   case OPR_SUB:
01890     {
01891      /*
01892       *    z - w = (R(z) - R(w)) + (I(z) - I(w))i
01893       */
01894       WN        *rz, *rw, *iz, *iw;
01895 
01896       lower_complex_expr(block, WN_kid0(tree), actions, &rz, &iz);
01897       lower_complex_expr(block, WN_kid1(tree), actions, &rw, &iw);
01898  
01899       *realpart = WN_Sub( type, rz, rw);
01900       *imagpart = WN_Sub( type, iz, iw);
01901     }
01902     break;
01903 
01904   case OPR_MPY:
01905     {
01906      /*
01907       *    z * w = (R(z)*R(w) - I(z)*I(w)) + (R(z)*I(w)+ R(w)*I(z))i
01908       *
01909       */
01910       WN        *rz, *rw, *iz, *iw;
01911       LEAF      rzN, rwN, izN, iwN;
01912 
01913       lower_complex_expr(block, WN_kid0(tree), actions, &rz, &iz);
01914       lower_complex_expr(block, WN_kid1(tree), actions, &rw, &iw);
01915 
01916       rzN = Make_Leaf(block, rz, type);
01917       rwN = Make_Leaf(block, rw, type);
01918       izN = Make_Leaf(block, iz, type);
01919       iwN = Make_Leaf(block, iw, type);
01920 
01921       *realpart = WN_Sub(type,
01922                          WN_Mpy(type, Load_Leaf(rzN), Load_Leaf(rwN)),
01923                          WN_Mpy(type, Load_Leaf(izN), Load_Leaf(iwN)));
01924 
01925       *imagpart = WN_Add(type,
01926                          WN_Mpy(type, Load_Leaf(rzN), Load_Leaf(iwN)),
01927                          WN_Mpy(type, Load_Leaf(rwN), Load_Leaf(izN)));
01928     }
01929     break;
01930 
01931   case OPR_COMPLEX:
01932     /*
01933      *  Create a complex number from two real children, ie.
01934      *    z = CMPLX(x,y)
01935      *    z = (x) + (y) i
01936      */
01937     *realpart = lower_expr(block, WN_kid0(tree), actions);
01938     *imagpart = lower_expr(block, WN_kid1(tree), actions);
01939     WN_Delete(tree);
01940     break;
01941 
01942   case OPR_MADD:
01943   case OPR_MSUB:
01944   case OPR_NMADD:
01945   case OPR_NMSUB:
01946     Is_True( FALSE, ("unexpected complex madd"));
01947     break;
01948 
01949   case OPR_CVT:
01950     {
01951       WN        *rz, *iz;
01952       TYPE_ID   desc = WN_desc(tree);
01953 
01954       lower_complex_expr(block, WN_kid0(tree), actions, &rz, &iz);
01955  
01956       *realpart = WN_Cvt( type, Mtype_complex_to_real(desc), rz);
01957       *imagpart = WN_Cvt( type, Mtype_complex_to_real(desc), iz);
01958     }
01959     break;
01960 
01961   case OPR_CONST:
01962     {
01963      /*
01964       * extract the real and imaginary parts of the complex number
01965       */
01966       TCON      val = Const_Val(tree);
01967 
01968       *realpart = Make_Const( Extract_Complex_Real(val));
01969       *imagpart = Make_Const( Extract_Complex_Imag(val));
01970 
01971       WN_Delete(tree);
01972     }
01973     break;
01974 
01975   case OPR_RSQRT:
01976     {
01977       TYPE_ID   desc = WN_desc(tree);
01978       WN        *div;
01979 
01980       div = WN_Div(desc,
01981                    WN_Floatconst(desc, 1.0),
01982                    WN_Sqrt(desc, WN_kid0(tree)));
01983 
01984       lower_complex_expr(block, div, actions, realpart, imagpart);
01985 
01986       WN_Delete(tree);
01987     }
01988     break;
01989 
01990   case OPR_SQRT:
01991     lower_complex_emulation(block, tree, actions, realpart, imagpart);
01992     break;
01993 
01994 
01995   case OPR_PAREN:
01996     {
01997       lower_complex_expr(block, WN_kid0(tree), actions, realpart, imagpart);
01998 
01999       *realpart = WN_Paren(type, *realpart);
02000       *imagpart = WN_Paren(type, *imagpart);
02001       WN_Delete(tree);
02002     }
02003     break;
02004 
02005   case OPR_ARRAY:
02006     break;
02007 
02008   case OPR_RECIP:
02009     {
02010       /* TODO_FEEDBACK: Get frequencies right, especially when we
02011        * create an IF statement. We have to assume half the frequency
02012        * goes to the then part and half goes to the else part; there's
02013        * no other information available, is there?
02014        */
02015 
02016       LEAF      rzN, izN;
02017       {
02018        /*
02019         *  assign pregs to their corresponding expressions
02020         *  Since the expressions will be reused, this avoids building a DAG
02021         */
02022         WN      *rz, *iz; 
02023     
02024         lower_complex_expr(block, WN_kid0(tree), actions, &rz, &iz);
02025       
02026         rzN = Make_Leaf(block, rz, type);
02027         izN = Make_Leaf(block, iz, type);
02028       }
02029     
02030       if (Fast_Complex_Allowed)
02031       {
02032        /*
02033         *   1 / z
02034         *    real =     (   R(z) ) /  ( R(z)**2 + I(z)**2 )
02035         *    imag =     ( - I(z) ) /  ( R(z)**2 + I(z)**2 )
02036         *
02037         */
02038         LEAF    denomN;
02039         WN      *rz2, *iz2, *add;
02040     
02041         rz2 = WN_Mpy(type, Load_Leaf(rzN), Load_Leaf(rzN));
02042         iz2 = WN_Mpy(type, Load_Leaf(izN), Load_Leaf(izN));
02043         add = WN_Add(type, rz2, iz2);
02044         denomN = Make_Leaf(block, add, type);
02045     
02046         *realpart = WN_Div(type, Load_Leaf(rzN), Load_Leaf(denomN));
02047         *imagpart = WN_Neg(type,
02048                            WN_Div(type, Load_Leaf(izN), Load_Leaf(denomN)));
02049       }
02050       else
02051       {
02052        /*
02053         *   1 / z
02054         *    real =     (   R(z) ) /  ( R(z)**2 + I(z)**2 )
02055         *    imag =     ( - I(z) ) /  ( R(z)**2 + I(z)**2 )
02056         *
02057         *    After factoring out max( |R(z)| , |I(z)| )
02058         *
02059         *       | R(z) | >  | I(z) |
02060         *
02061         *       Let x = I(z) / R(z)
02062         *       real = ( 1 )    /  ( R(z) + I(z)*x)
02063         *       imag = ( - x )  /  ( R(z) + I(z)*x)
02064         *
02065         *       | I(z) | >  | R(z) |
02066         *
02067         *       Let x = R(z) / I(z)
02068         *       real = ( x )   /  ( R(z)*x + I(z) )
02069         *       imag = (-1 )   /  ( R(z)*x + I(z) )
02070         *
02071         */
02072         WN              *if_then, *if_else, *IF;
02073         PREG_NUM        realpartN, imagpartN;
02074         LEAF            xN, arzN, aizN;
02075     
02076         {
02077           WN    *numer, *denom, *div;
02078     
02079           arzN = Make_Leaf(block,
02080                            WN_Abs(type, Load_Leaf(rzN)),
02081                            type);
02082     
02083           aizN = Make_Leaf(block,
02084                            WN_Abs(type, Load_Leaf(izN)),
02085                            type);
02086     
02087          /*
02088           *  numer =  | R(w) | >  | I(w) |  ?  I(w) : R(x)
02089           *  denom =  | R(w) | >  | I(w) |  ?  R(w) : I(x)
02090           *
02091           *  Let x = numer / denom
02092           */
02093           numer = WN_Select(type,
02094                             WN_GT(type, Load_Leaf(arzN), Load_Leaf(aizN)),
02095                             Load_Leaf(izN),
02096                             Load_Leaf(rzN));
02097           denom = WN_Select(type,
02098                             WN_GT(type, Load_Leaf(arzN), Load_Leaf(aizN)),
02099                             Load_Leaf(rzN),
02100                             Load_Leaf(izN));
02101 
02102           div = WN_Div(type, numer, denom);
02103 
02104           xN = Make_Leaf(block, div, type);
02105         }
02106 
02107         if_then = WN_CreateBlock();
02108         {
02109          /*
02110           *     scale = ( R(z) + I(z)*x )
02111           *     real = ( 1 )    /  scale
02112           *     imag = ( - x )  /  scale
02113           */
02114           WN    *scale, *div;
02115           LEAF  scaleN;
02116     
02117           scale = WN_Add(type,
02118                          Load_Leaf(rzN),
02119                          WN_Mpy(type, Load_Leaf(izN), Load_Leaf(xN)));
02120           scaleN = Make_Leaf(if_then, scale, type);
02121 
02122           div = WN_Inverse(type, Load_Leaf(scaleN));
02123 
02124           realpartN = AssignExpr(if_then, div, type);
02125 
02126           div =  WN_Div(type,
02127                         WN_Neg(type, Load_Leaf(xN)),
02128                         Load_Leaf(scaleN));
02129     
02130           imagpartN = AssignExpr(if_then, div, type);
02131         }
02132 
02133         if_else = WN_CreateBlock();
02134         {
02135          /*
02136           *     scale = ( R(z)*x + I(z) )
02137           *     real = ( x )   /  scale
02138           *     imag = ( 1 )   /  scale
02139           */
02140           WN    *scale, *div, *stid;
02141           LEAF  scaleN;
02142           ST    *preg = MTYPE_To_PREG(type);
02143     
02144           scale = WN_Add(type,
02145                          WN_Mpy(type, Load_Leaf(rzN), Load_Leaf(xN)),
02146                          Load_Leaf(izN));
02147           scaleN = Make_Leaf(if_else, scale, type);
02148 
02149           div =  WN_Div(type, Load_Leaf(xN), Load_Leaf(scaleN));
02150           stid = WN_StidIntoPreg(type, realpartN, preg, div);
02151           WN_INSERT_BlockLast(if_else, stid);
02152     
02153           div = WN_Neg(type,WN_Inverse(type, Load_Leaf(scaleN)));
02154           stid = WN_StidIntoPreg(type, imagpartN, preg, div);
02155           WN_INSERT_BlockLast(if_else, stid);
02156         }
02157     
02158         IF =  WN_CreateIf(WN_GT(type, Load_Leaf(arzN), Load_Leaf(aizN)),
02159                           if_then, if_else);
02160 
02161         if ( Cur_PU_Feedback ) {
02162           Cur_PU_Feedback->Annot( IF, FB_EDGE_BRANCH_TAKEN, FB_FREQ_UNKNOWN );
02163           Cur_PU_Feedback->Annot( IF, FB_EDGE_BRANCH_NOT_TAKEN,
02164                                   FB_FREQ_UNKNOWN );
02165         }
02166 
02167         WN_INSERT_BlockLast(block, lower_if(block, IF, actions));
02168     
02169         *realpart = WN_LdidPreg(type, realpartN);
02170         *imagpart = WN_LdidPreg(type, imagpartN);
02171       }
02172       WN_Delete(tree);
02173     }
02174     break;
02175 
02176   case OPR_DIV:
02177     {
02178      /*
02179       *  assign pregs to their corresponding expressions
02180       *  Since the expressions will be reused, this avoids building a DAG
02181       */
02182       WN        *rz, *rw, *iz, *iw; 
02183       LEAF      rzN, rwN, izN, iwN;
02184 
02185       lower_complex_expr(block, WN_kid0(tree), actions, &rz, &iz);
02186       lower_complex_expr(block, WN_kid1(tree), actions, &rw, &iw);
02187   
02188       rzN = Make_Leaf(block, rz, type);
02189       izN = Make_Leaf(block, iz, type);
02190       rwN = Make_Leaf(block, rw, type);
02191       iwN = Make_Leaf(block, iw, type);
02192 
02193       if (Fast_Complex_Allowed)
02194       {
02195        /*
02196         *   z / w
02197         *    real =     (R(z)*R(w) + I(z)*I(w) /  ( R(w)**2 + I(w)**2 )
02198         *    imag =     (I(z)*R(w) - R(z)*I(w) /  ( R(w)**2 + I(w)**2 )
02199         *
02200         */
02201         LEAF    denomN;
02202         {
02203           WN    *rw2, *iw2, *add;
02204     
02205           rw2 = WN_Mpy(type,Load_Leaf(rwN), Load_Leaf(rwN));
02206           iw2 = WN_Mpy(type, Load_Leaf(iwN), Load_Leaf(iwN));
02207           add = WN_Add(type, rw2, iw2);
02208           denomN = Make_Leaf(block, add, type);
02209         }
02210         {
02211           WN    *rzrw, *iziw;
02212     
02213           rzrw = WN_Mpy(type, Load_Leaf(rzN), Load_Leaf(rwN));
02214           iziw = WN_Mpy(type, Load_Leaf(izN), Load_Leaf(iwN));
02215           *realpart = WN_Div(type,
02216                          WN_Add(type, rzrw, iziw),
02217                          Load_Leaf(denomN));
02218         }
02219         {
02220           WN    *rziw, *izrw;
02221     
02222           izrw = WN_Mpy(type, Load_Leaf(izN), Load_Leaf(rwN));
02223           rziw = WN_Mpy(type, Load_Leaf(rzN), Load_Leaf(iwN));
02224           *imagpart = WN_Div(type,
02225                          WN_Sub(type, izrw, rziw),
02226                          Load_Leaf(denomN));
02227         }
02228       }
02229       else
02230       {
02231        /*
02232         *   z / w
02233         *    real =     (R(z)*R(w) + I(z)*I(w) /  ( R(w)**2 + I(w)**2 )
02234         *    imag =     (I(z)*R(w) - R(z)*I(w) /  ( R(w)**2 + I(w)**2 )
02235         *
02236         *    After factoring out max( |R(w)| , |I(w)| )
02237         *
02238         *       | R(w) | >  | I(w) |
02239         *
02240         *       Let x = I(w) / R(w)
02241         *         real = ( R(z) + I(z)*x ) /  ( R(w) + I(w)*x )
02242         *         imag = ( I(z) - R(z)*x ) /  ( R(w) + I(w)*x )
02243         *
02244         *       | I(w) | >  | R(w) |
02245         *
02246         *       Let x = R(w) / I(w)
02247         *         real = ( R(z)*x + I(z) ) /  ( R(w)*x + I(w) )
02248         *         imag = ( I(z)*x - R(z) ) /  ( R(w)*x + I(w) )
02249         *
02250         */
02251         WN              *if_then, *if_else, *IF;
02252         LEAF            xN, arwN, aiwN;
02253         PREG_NUM        realpartN, imagpartN;
02254         {
02255           WN    *numer, *denom, *div;
02256     
02257           arwN = Make_Leaf(block,
02258                            WN_Abs(type, Load_Leaf(rwN)),
02259                            type);
02260           aiwN = Make_Leaf(block,
02261                            WN_Abs(type, Load_Leaf(iwN)),
02262                            type);
02263     
02264          /*
02265           *  numer =  | R(w) | >  | I(w) |  ?  I(w) : R(x)
02266           *  denom =  | R(w) | >  | I(w) |  ?  R(w) : I(x)
02267           *
02268           *  Let x = numer / denom
02269           */
02270           numer = WN_Select(type,
02271                             WN_GT(type, Load_Leaf(arwN), Load_Leaf(aiwN)),
02272                             Load_Leaf(iwN),
02273                             Load_Leaf(rwN));
02274           denom = WN_Select(type,
02275                             WN_GT(type, Load_Leaf(arwN), Load_Leaf(aiwN)),
02276                             Load_Leaf(rwN),
02277                             Load_Leaf(iwN));
02278           div = WN_Div(type, numer, denom);
02279           xN = Make_Leaf(block, div, type);
02280         }
02281 
02282         if_then = WN_CreateBlock();
02283         {
02284           WN            *scale;
02285           LEAF  scaleN;
02286     
02287           scale = WN_Add(type,
02288                          Load_Leaf(rwN),
02289                          WN_Mpy(type, Load_Leaf(iwN), Load_Leaf(xN)));
02290           scaleN = Make_Leaf(if_then, scale, type);
02291           {
02292            /*
02293             *  real = ( R(z)   + I(z)*x )  / scale
02294             */
02295             WN  *numer, *div;
02296     
02297             numer = WN_Add(type,
02298                            Load_Leaf(rzN),
02299                            WN_Mpy(type, Load_Leaf(izN), Load_Leaf(xN)));
02300             div = WN_Div(type, numer, Load_Leaf(scaleN));
02301             realpartN = AssignExpr(if_then, div, type);
02302           }
02303           {
02304            /*
02305             *  imag = ( I(z) - R(z)*x ) /  scale
02306             */
02307             WN  *numer, *div;
02308     
02309             numer = WN_Sub(type,
02310                            Load_Leaf(izN),
02311                            WN_Mpy(type, Load_Leaf(rzN), Load_Leaf(xN)));
02312             div = WN_Div(type, numer, Load_Leaf(scaleN));
02313             imagpartN = AssignExpr(if_then, div, type);
02314           }
02315         }
02316     
02317         if_else = WN_CreateBlock();
02318         {
02319           WN    *scale;
02320           LEAF  scaleN;
02321           ST    *preg = MTYPE_To_PREG(type);
02322 
02323           scale = WN_Add(type,
02324                          WN_Mpy(type, Load_Leaf(rwN), Load_Leaf(xN)),
02325                          Load_Leaf(iwN));
02326           scaleN = Make_Leaf(if_else, scale, type);
02327           {
02328            /*
02329             *  real = ( R(z)*x + I(z) ) /  scale
02330             *  store away result in an already defined preg
02331             */
02332             WN  *numer, *div, *stid;
02333     
02334             numer =  WN_Add(type,
02335                             WN_Mpy(type, Load_Leaf(rzN), Load_Leaf(xN)),
02336                             Load_Leaf(izN));
02337             div = WN_Div(type, numer, Load_Leaf(scaleN));
02338             stid = WN_StidIntoPreg(type, realpartN, preg, div);
02339             WN_INSERT_BlockLast(if_else, stid);
02340           }
02341           {
02342            /*
02343             *  imag = ( I(z)*x - R(z) ) /  scale
02344             *  store away result in an already defined preg
02345             */
02346             WN  *numer, *div, *stid;
02347     
02348             numer = WN_Sub(type,
02349                            WN_Mpy(type, Load_Leaf(izN), Load_Leaf(xN)),
02350                            Load_Leaf(rzN));
02351             div = WN_Div(type, numer, Load_Leaf(scaleN));
02352             stid = WN_StidIntoPreg(type, imagpartN, preg, div);
02353             WN_INSERT_BlockLast(if_else, stid);
02354           }
02355         }
02356     
02357         IF =  WN_CreateIf(WN_GT(type, Load_Leaf(arwN), Load_Leaf(aiwN)),
02358                           if_then, if_else);
02359 
02360         if ( Cur_PU_Feedback ) {
02361           Cur_PU_Feedback->Annot( IF, FB_EDGE_BRANCH_TAKEN, FB_FREQ_UNKNOWN );
02362           Cur_PU_Feedback->Annot( IF, FB_EDGE_BRANCH_NOT_TAKEN,
02363                                   FB_FREQ_UNKNOWN );
02364         }
02365     
02366         WN_INSERT_BlockLast(block, lower_if(block, IF, actions));
02367     
02368         *realpart = WN_LdidPreg(type, realpartN);
02369         *imagpart = WN_LdidPreg(type, imagpartN);
02370       }
02371       WN_Delete(tree);
02372     }
02373     break;
02374 
02375   case OPR_RND:
02376   case OPR_TRUNC:
02377   case OPR_MOD:
02378   case OPR_REM:
02379   case OPR_ABS:
02380     Fail_FmtAssertion("unexpected complex op (%s)",
02381                       OPCODE_name(WN_opcode(tree)));
02382     /*NOTREACHED*/
02383 
02384   case OPR_INTRINSIC_OP:
02385     {
02386       INTRINSIC     id = (INTRINSIC) WN_intrinsic(tree);
02387 
02388       switch(id)
02389       {
02390       case INTRN_C4CONJG:
02391       case INTRN_C8CONJG:
02392       case INTRN_CQCONJG:
02393         {
02394           WN    *iz;
02395 
02396           lower_complex_expr(block, WN_actual(tree, 0), actions,
02397                              realpart, &iz);
02398 
02399           *imagpart = WN_Neg(type, iz);
02400 
02401           WN_Delete(tree);
02402         }
02403         break;
02404 
02405         //*****************************************************************
02406         //
02407         // N.B. Any complex intrinsic which does not have an emulation must
02408         // appear in the list below.
02409         //
02410 
02411         //       case INTRN_F4CIS:
02412         //case INTRN_F8CIS:
02413         //case INTRN_FQCIS:
02414         //  actions |= LOWER_INTRINSIC;
02415           /* Fall Through */
02416 
02417       default:
02418         if (INTRN_is_actual(WN_intrinsic(tree)))
02419         {
02420           tree = lower_intrinsic(block, tree, actions);
02421         }
02422         else
02423         {
02424           lower_complex_emulation(block, tree, actions, realpart, imagpart);
02425         }
02426         break;
02427       }
02428     }
02429     break;
02430 
02431   case OPR_SELECT:
02432     {
02433        WN *r1, *i1;
02434        WN *r2, *i2;
02435        LEAF cond;
02436        
02437        cond = Make_Leaf(block, WN_kid0(tree), WN_rtype(WN_kid0(tree)));
02438        
02439        lower_complex_expr(block, WN_kid1(tree), actions, &r1, &i1);
02440        lower_complex_expr(block, WN_kid2(tree), actions, &r2, &i2);
02441        
02442        *realpart = WN_Select(type, Load_Leaf(cond), r1, r2);
02443        *imagpart = WN_Select(type, Load_Leaf(cond), i1, i2);
02444     }
02445     break;
02446 
02447   case OPR_PARM:
02448     lower_complex_expr(block, WN_kid0(tree), actions, realpart, imagpart);
02449     break;
02450   }
02451 }
02452 
02453 
02454 
02455 
02456 /* ====================================================================
02457  *
02458  * void lower_quad_expr(WN *block, WN *tree, LOWER_ACTIONS actions,
02459  *                               WN **hipart, WN **lopart)
02460  *
02461  * ==================================================================== */
02462 
02463 static void lower_quad_expr(WN *block, WN *tree, LOWER_ACTIONS actions,
02464                                      WN **hipart, WN **lopart)
02465 {
02466   TYPE_ID       type =  MTYPE_F8;
02467 
02468 
02469   Is_True(OPCODE_is_expression(WN_opcode(tree)),
02470           ("expected expression node, not %s", OPCODE_name(WN_opcode(tree))));
02471   Is_True(actions & LOWER_QUAD, ("actions does not contain LOWER_QUAD"));
02472   Is_True((MTYPE_is_quad(WN_rtype(tree))),
02473           ("expected quad-type node, not %s", OPCODE_name(WN_opcode(tree))));
02474  /*
02475   *  first lower the quad as expressions.
02476   *
02477   *  This will create and serialize a call chain
02478   *  that should always return a leaf that can be decomposed
02479   */
02480   tree = lower_expr(block, tree, actions);
02481 
02482   switch (WN_operator(tree))
02483   {
02484   case OPR_LDID:
02485     {
02486      /*
02487       *  we must create a new ST of type real*8
02488       */
02489       TY_IDX    beTY   = MTYPE_To_TY(type);
02490       WN_OFFSET offset = WN_load_offset(tree);
02491 
02492       *hipart = WN_Ldid(type, offset,
02493                         coerceST(WN_st(tree), type), beTY);
02494 
02495       *lopart = WN_Ldid(type,
02496                         coerceOFFSET(tree, type, offset),
02497                         coerceST(WN_st(tree), type),
02498                         beTY);
02499 
02500       lower_quad_maps(tree, *hipart, *lopart, actions);
02501     }
02502     break;
02503 
02504   case OPR_ILOAD:
02505     {
02506       WN        *addr;
02507       WN_OFFSET offset = WN_load_offset(tree);
02508       LEAF      addrN;
02509 
02510       addr = lower_expr(block, WN_kid0(tree), actions);
02511 
02512       addrN = Make_Leaf(block, addr, Pointer_type);
02513 
02514       *hipart = WN_Iload(type,
02515                          offset,
02516                          coerceTY(WN_ty(tree), type),
02517                          Load_Leaf(addrN));
02518 
02519       *lopart = WN_Iload(type,
02520                          coerceOFFSET(tree, type, offset),
02521                          coerceTY(WN_ty(tree), type),
02522                          Load_Leaf(addrN));
02523 
02524       lower_quad_maps(tree, *hipart, *lopart, actions);
02525     }
02526     break;
02527 
02528   case OPR_CONST:
02529     {
02530       TCON      val = Const_Val(tree);
02531 
02532       *hipart = Make_Const( Extract_Quad_Hi(val));
02533       *lopart = Make_Const( Extract_Quad_Lo(val));
02534 
02535     }
02536     break;
02537 
02538   case OPR_PAREN:
02539     {
02540      /*
02541       * preserve the parens
02542       */
02543       lower_quad_expr(block, WN_kid0(tree), actions, hipart, lopart);
02544 
02545       *hipart = WN_Paren(type, *hipart);
02546       *lopart = WN_Paren(type, *lopart);
02547     }
02548     break;
02549 
02550   case OPR_PARM:
02551     lower_quad_expr(block, WN_kid0(tree), actions, hipart, lopart);
02552     break;
02553 
02554   case OPR_ILOADX:
02555     Is_True( FALSE, ("unexpected QUAD ILOADX"));
02556     break;
02557 
02558   default:
02559     Is_True((FALSE),
02560             ("lower_quad_expr didn't %s", OPCODE_name(WN_opcode(tree))));
02561   }
02562 }
02563 
02564 
02565 
02566 
02567 static WN *WN_Coerce(TYPE_ID dst, WN *expr)
02568 {
02569   TYPE_ID src= WN_rtype(expr);
02570 
02571   if (MTYPE_size_min(dst) == MTYPE_size_min(src))
02572     return expr;
02573 
02574   return WN_Cvt(src, dst, expr);
02575 }
02576 
02577 
02578 
02579 
02580 /* ====================================================================
02581  *
02582  * WN *lower_linearize_array_addr(WN *block, WN *tree, LOWER_ACTIONS actions)
02583  *
02584  * Perform lowering (see WN_Lower description) on ARRAY expr <tree>,
02585  * returning linearized address expression tree.  <actions> must
02586  * contain LOWER_ARRAY.
02587  *
02588  *  We are assuming that the index and array_dim information are unique
02589  *
02590  * Note: If the element size is < 0, it means that we have a non-contiguous F90
02591  *       array. These are linearized slightly differently. Instead of
02592  *       the extent children being extents, they are stride multiplier factors. 
02593  *       The sum of the products of the index and stride multiplier is scaled
02594  *       by -element_size to get the offset from the base.  
02595  * ==================================================================== */
02596 
02597 static WN *lower_linearize_array_addr(WN *block, WN *tree,
02598                                       LOWER_ACTIONS actions)
02599 {
02600   TYPE_ID rtype = WN_rtype(tree);
02601   WN            *result, *product;
02602   INT32         n, i;
02603   BOOL          is_non_contig=FALSE;
02604   WN_ESIZE      element_size;
02605 
02606   Is_True((WN_operator_is(tree,OPR_ARRAY)),
02607           ("expected ARRAY node, not %s", OPCODE_name(WN_opcode(tree))));
02608   Is_True(Action(LOWER_ARRAY), ("actions doesn't contain LOWER_ARRAY"));
02609   Is_True(WN_num_dim(tree) > 0, ("WN_num_dim of ARRAY node not > 0"));
02610 
02611   n = WN_num_dim(tree);
02612   element_size = WN_element_size(tree);
02613   if (element_size < 0) {
02614      is_non_contig = TRUE;
02615      element_size = -element_size;
02616   }
02617 
02618   if (is_non_contig)
02619   {
02620      WN *stride_mult;
02621      
02622      result = WN_Coerce(rtype, WN_array_index(tree, n-1));
02623      stride_mult = WN_Coerce(rtype, WN_array_dim(tree, n-1));
02624      result = WN_Mpy(rtype,result,stride_mult);
02625 
02626      for (i = n-2; i >= 0; i--) {
02627         product = WN_Coerce(rtype, WN_array_index(tree, i));
02628         stride_mult = WN_Coerce(rtype, WN_array_dim(tree, i));
02629         product = WN_Mpy(rtype,product,stride_mult);
02630         result = WN_Add(rtype,result,product);
02631      }
02632   }
02633   else
02634   {
02635    /*
02636     *  result <- index[n-1]
02637     */
02638     result = WN_Coerce(rtype, WN_array_index(tree, n-1));
02639      
02640    /*
02641     *  result <- result + index[i] * ( dim[n-1] * dim[n-2] ... dim[i+1] )
02642     */
02643     for (i = n-2; i >= 0; i--)
02644     {
02645       INT32     m;
02646       WN        *mpy;
02647              
02648       product = WN_Coerce(rtype, lower_copy_tree(WN_array_dim(tree, n-1),
02649                                                  actions));
02650       for (m=n-2; m>i; m--)
02651       {
02652         product = WN_Mpy(rtype,
02653                          product,
02654                          WN_Coerce(rtype, lower_copy_tree(WN_array_dim(tree, m),
02655                                                           actions)));
02656       }
02657 
02658       mpy = WN_Mpy(rtype,
02659                    WN_Coerce(rtype, WN_array_index(tree,i)),
02660                    product);
02661       result = WN_Add(rtype, result, mpy);
02662     }
02663   }  
02664   
02665 
02666   /*
02667    *  result <- base + result * elm_size
02668    */
02669   {
02670     WN  *elm_size;
02671     TY_IDX arr_ty = Get_Type_From_ArrayOp(WN_array_base(tree));
02672     elm_size = WN_Intconst(rtype, element_size);
02673     
02674     if (Type_Is_Shared_Ptr(arr_ty)) {
02675       SPTR_ACCUMULATION_STATE saved_acc_state = sptr_accumulation_state;
02676       SPTR_OFFSET_TERM_STACK *term_stack;
02677       if (sptr_accumulation_state !=  ARRAY_ACCUMULATION) {
02678         sptr_accumulation_state = ARRAY_ACCUMULATION;
02679         sptr_off_accumulation_stack.push(CXX_NEW(SPTR_OFFSET_TERM_STACK,Malloc_Mem_Pool));
02680       }
02681       
02682       term_stack = sptr_off_accumulation_stack.top();
02683       WN *base = lower_expr(block, WN_array_base(tree), actions);
02684       
02685       if (saved_acc_state == ARRAY_ACCUMULATION) {
02686         sptr_accumulation_state = NO_ACCUMULATION;
02687         result = lower_expr(block, result, actions);
02688         term_stack->push(result);
02689         // term_stack->push(WN_Mpy(rtype, result, elm_size));
02690         WN_Delete (tree);
02691         sptr_accumulation_state = saved_acc_state;
02692         return base;
02693       } else {
02694         sptr_accumulation_state = NO_ACCUMULATION;
02695         result = lower_expr(block, result, actions);
02696         term_stack->push(result);
02697         // term_stack->push(WN_Mpy(rtype, result, elm_size));
02698         result  = Combine_Offset_Terms(*term_stack);
02699         // if(result)
02700 //        fdump_tree(stderr, result);
02701         sptr_accumulation_state = saved_acc_state;
02702         sptr_off_accumulation_stack.pop();
02703         CXX_DELETE(term_stack, Malloc_Mem_Pool);
02704       
02705         result  = WN_Create_Shared_Ptr_Arithmetic (base, result, OPR_ADD,
02706                                                    Get_Type_Inner_Size(arr_ty),
02707                                                    Get_Type_Block_Size(arr_ty),
02708                                                    Get_Type_Block_Size(arr_ty) <= 1);
02709       }
02710     } else {
02711       //default case
02712       result = WN_Add(rtype,
02713                       WN_array_base(tree),
02714                       WN_Mpy(rtype, result, elm_size));
02715       result = lower_expr(block, result, actions);
02716       WN_Delete(tree);      /* ARRAY node not used */
02717     }
02718   }
02719   
02720  
02721 
02722   return result;
02723 }
02724 
02725 
02726 
02727 
02728 /* ====================================================================
02729  *
02730  * WN *lower_unsigned_to_float(WN *block, WN *tree, LOWER_ACTIONS actions)
02731  *
02732  * Perform lowering (see WN_Lower description) on conversions <tree>,
02733  * returning lowered expression tree.
02734  *
02735  * ==================================================================== */
02736 
02737 static WN *lower_unsigned_to_float(WN *block, WN *expr, TYPE_ID src,
02738                                    TYPE_ID dst, LOWER_ACTIONS actions)
02739 {
02740   LEAF  srcNo, dstNo;
02741 
02742 
02743   /* Special case of U4. Don't do this special case if the cvt.d.l 
02744    * instruction is slow. This is true on the R5000 which emulates
02745    * this in software due to a chip bug.
02746    */
02747   if (src == MTYPE_U4 && !Slow_CVTDL)
02748   {
02749      BOOL  simp=        WN_Simplifier_Enable(FALSE);
02750      WN * r;
02751 
02752      r = WN_Cvt(MTYPE_I8,dst,WN_Cvt(MTYPE_U4, MTYPE_U8, expr));
02753 
02754      WN_Simplifier_Enable(simp);
02755      return (r);
02756   }
02757 
02758 
02759   /*
02760    *  store the expr into a preg to avoid building a dag
02761    *    src = expr;
02762    */
02763   srcNo = Make_Leaf(block, expr, src);
02764 
02765   /*
02766    *  dst = (signed cvt) src ;
02767    */
02768   {
02769     WN  *ldid, *cvt;
02770 
02771     ldid = Load_Leaf(srcNo);
02772 
02773     cvt  = WN_Cvt(MTYPE_complement(src), dst, ldid);
02774 
02775     dstNo = Make_Leaf(block, cvt, dst);
02776   }
02777 
02778   /*
02779    *  build the select tree that looks like
02780    *    (src < 0) ? dst + 2**N : dst
02781    *     where N is the src size
02782    */
02783   {
02784     WN  *rel, *add, *select;
02785 
02786     rel = WN_LT(MTYPE_complement(src),
02787                 Load_Leaf(srcNo),
02788                 WN_Zerocon(MTYPE_complement(src)));
02789 
02790     add = WN_Add(dst,
02791                  Load_Leaf(dstNo),
02792                  WN_ConstPowerOf2( dst, MTYPE_size_reg(src)));
02793 
02794     select = WN_Select(dst, rel, add, Load_Leaf(dstNo));
02795     return select;
02796   }
02797 }
02798 
02799 
02800 
02801 
02802 /* ====================================================================
02803  *
02804  * WN *lower_float_to_unsigned(WN *block, WN *tree, LOWER_ACTIONS actions)
02805  *
02806  * Perform lowering (see WN_Lower description) on conversions <tree>,
02807  * returning lowered expression tree.
02808  *
02809  * ==================================================================== */
02810 
02811 static WN *lower_float_to_unsigned(WN *block, WN *expr, TYPE_ID src,
02812                                    TYPE_ID dst, LOWER_ACTIONS actions)
02813 {
02814   LEAF srcNo;
02815   WN *trunc1,*r;
02816   WN *rel, *sub, *trunc2,*add;
02817 
02818 
02819   /* Two cases, dest type = U8, and dest type = U4 */
02820   if (dst == MTYPE_U4) {
02821      r = WN_Cvt(MTYPE_I8,dst,WN_Trunc(src,MTYPE_I8,expr));
02822   } else if (src==MTYPE_FQ) {  /* Need to do this this way because there
02823                                 * is no quad floor */
02824      
02825      /*
02826       *  store the expr into a preg to avoid building a dag
02827       * src = expr;
02828       */
02829      srcNo = Make_Leaf(block, expr, src);
02830      
02831      /*
02832       *  build the select tree that looks like
02833       *
02834       * (2**(N-1) <= src) ? : 2**(N-1) + TRUNC(src-2**(N-1)) : TRUNC(src)
02835       *
02836       * where N is the unsigned dst size
02837       */
02838 
02839 
02840      trunc1 = WN_Trunc(src, MTYPE_complement(dst), Load_Leaf(srcNo));
02841      
02842      sub = WN_Sub(src, Load_Leaf(srcNo),
02843                   WN_ConstPowerOf2(src, MTYPE_size_reg(dst)-1));
02844 
02845      trunc2 =  WN_Trunc(src, MTYPE_complement(dst),sub);
02846 
02847      add = WN_Add(dst,trunc2,WN_ConstPowerOf2(dst, MTYPE_size_reg(dst)-1));
02848      
02849      rel = WN_LE(src,
02850                  WN_ConstPowerOf2(src, MTYPE_size_reg(dst)-1),
02851                  Load_Leaf(srcNo));
02852      
02853      r = WN_Cselect(dst,rel,add,trunc1);
02854   } else {
02855      
02856      /*
02857       *  store the expr into a preg to avoid building a dag
02858       * src = expr;
02859       */
02860      srcNo = Make_Leaf(block, expr, src);
02861      
02862      /*
02863       *  build the select tree that looks like
02864       *
02865       * (2**(N-1) <= src) ? : FLOOR(src-2**(N)) : TRUNC(src)
02866       *
02867       * where N is the unsigned dst size
02868       */
02869 
02870 
02871      trunc1 = WN_Trunc(src, MTYPE_complement(dst), Load_Leaf(srcNo));
02872      
02873      sub = WN_Sub(src, Load_Leaf(srcNo),
02874                   WN_ConstPowerOf2(src, MTYPE_size_reg(dst)));
02875 
02876      trunc2 =  WN_Floor(src, MTYPE_complement(dst),sub);
02877 
02878      rel = WN_LE(src,
02879                  WN_ConstPowerOf2(src, MTYPE_size_reg(dst)-1),
02880                  Load_Leaf(srcNo));
02881      
02882      r = WN_Cselect(dst,rel,trunc2,trunc1);
02883   }
02884   return (r);
02885 }
02886 
02887 
02888 
02889 
02890 /* ====================================================================
02891  *
02892  * WN *lower_cvt(WN *block, WN *tree, LOWER_ACTIONS actions)
02893  *
02894  * Perform lowering (see WN_Lower description) on conversions <tree>,
02895  * returning lowered expression tree.
02896  *
02897  * ==================================================================== */
02898 
02899 static WN *lower_cvt(WN *block, WN *tree, LOWER_ACTIONS actions)
02900 {
02901   WN    *expr, *cvt;
02902   TYPE_ID dst = WN_rtype(tree);
02903   TYPE_ID src = WN_desc(tree);
02904 
02905   expr = lower_expr(block, WN_kid0(tree), actions);
02906   WN_kid0(tree) = expr;
02907 
02908   if (   Targ_Lower_Unsigned_To_Float 
02909       && MTYPE_is_unsigned(src) && MTYPE_is_float(dst))
02910   {
02911     WN_Delete(tree);
02912 
02913     cvt = lower_unsigned_to_float(block, expr, src, dst, actions);
02914 
02915     return lower_expr(block, cvt, actions);
02916   }
02917   else if (   Targ_Lower_Float_To_Unsigned 
02918            && MTYPE_is_float(src) && MTYPE_is_unsigned(dst))
02919   {
02920     WN_Delete(tree);
02921 
02922     cvt = lower_float_to_unsigned(block, expr, src, dst, actions);
02923 
02924     return lower_expr(block, cvt, actions);
02925   }
02926   else if (   OPERATOR_is_compare(WN_operator(expr))
02927            && WN_rtype(expr) == MTYPE_B
02928            && (MTYPE_is_integral(dst) && src == MTYPE_B))
02929   {
02930 
02931     /* Optimize converts of MTYPE_B compares to integral values.
02932      */
02933     WN_Delete(tree);
02934 
02935     WN_set_rtype(expr, dst);
02936 
02937     return lower_expr(block, expr, actions);
02938   }
02939   
02940   return tree;
02941 }
02942 
02943 
02944 
02945 /* ====================================================================
02946  *
02947  * WN *lower_nary_madd(WN *block, WN *tree, LOWER_ACTIONS actions)
02948  *
02949  *  Create nary expression reassociate to produce MADDS
02950  *
02951  * ==================================================================== */
02952 
02953 static WN *lower_nary_madd(WN *block, WN *tree, LOWER_ACTIONS actions)
02954 {
02955 
02956   if (Enable_NaryExpr && Roundoff_Level >= ROUNDOFF_ASSOC)
02957   {
02958     TYPE_ID  type = WN_rtype(tree);
02959 
02960     tree = WN_ExprToNaryType(tree, type, 0);
02961 
02962     if (WN_nary_add(tree))
02963     {
02964       INT32     i;
02965       BOOL      found= TRUE;
02966 
02967      /*
02968       *  Find mpy then a non mpy under nary tree.
02969       *  The tree may change (ex. to a binary tree)
02970       */
02971       while(found)
02972       {
02973         INT32   mpyI, exprI, nmpyI, narympyI;
02974         WN      *mpy, *nmpy, *expr, *narympy;
02975         INT32   num_kids = WN_kid_count(tree);
02976 
02977         found=  FALSE;
02978         mpy  =  nmpy  = expr = narympy  = NULL;
02979         mpyI =  exprI = nmpyI = narympyI = 0;
02980 
02981         for(i = 0; i < num_kids; i++)
02982         {
02983           WN  *actual= WN_actual(tree, i);
02984 
02985           if (WN_operator_is(actual, OPR_MPY))
02986           {
02987             mpyI = i;
02988             mpy = actual;
02989           }
02990           else if (WN_operator_is(actual, OPR_NEG)      &&
02991                    WN_operator_is(WN_kid0(actual), OPR_MPY))
02992           {
02993             nmpyI = i;
02994             nmpy = WN_kid0(actual);
02995           }
02996           else if (WN_nary_mpy(actual) && WN_kid_count(actual) >= 2)
02997           {
02998             narympyI = i;
02999             narympy = actual;
03000           }
03001           else 
03002           {
03003             exprI = i;
03004             expr = actual;
03005           }
03006 
03007           if (mpy && expr)
03008           {
03009             WN_actual(tree, mpyI)= WN_Madd(type, expr, WN_kid0(mpy),
03010                                            WN_kid1(mpy));
03011             tree = WN_NaryDelete(tree, exprI);
03012             found=      TRUE;
03013             break;
03014           }
03015           else if (nmpy && expr)
03016           {
03017             WN_actual(tree, nmpyI)= WN_Nmsub(type, expr, WN_kid0(nmpy),
03018                                              WN_kid1(nmpy));
03019             tree = WN_NaryDelete(tree, exprI);
03020             found=      TRUE;
03021             break;
03022           }
03023           else if (narympy && expr)
03024           {
03025             mpy=        WN_kid0(narympy);
03026             narympy=    WN_NaryDelete(narympy, 0);
03027 
03028             WN_actual(tree, narympyI)= WN_Madd(type, expr, mpy, narympy);
03029             tree = WN_NaryDelete(tree, exprI);
03030             found=      TRUE;
03031             break;
03032           }
03033         }
03034       }
03035      /*
03036       *  There may be madd opportunites at the children
03037       */
03038       for(i = 0; i < WN_kid_count(tree); i++)
03039       {
03040         WN_actual(tree, i)= lower_madd(block, WN_actual(tree,i), actions);
03041       }
03042 
03043     }
03044     
03045     if (WN_nary_intrinsic(tree))
03046     {
03047       tree = WN_NaryToExpr(tree);
03048     }
03049   }
03050 
03051   return tree;
03052 }
03053 
03054 
03055 
03056 
03057 /* ====================================================================
03058  *
03059  * WN *lower_madd(WN *block, WN *tree, LOWER_ACTIONS actions)
03060  *
03061  * Perform lowering (see WN_Lower description) on expression <tree>,
03062  * returning lowered expression tree.
03063  *
03064  * ==================================================================== */
03065 
03066 static WN *lower_madd(WN *block, WN *tree, LOWER_ACTIONS actions)
03067 {
03068   TYPE_ID  type = WN_rtype(tree);
03069 
03070  /*
03071   *  look for madd patterns
03072   */
03073   switch (WN_operator(tree))
03074   {
03075   case OPR_NEG:
03076     {
03077       WN        *child = WN_kid0(tree);
03078 
03079       switch(WN_operator(child))
03080       {
03081       case OPR_MADD:
03082         WN_Delete(tree);
03083         return WN_Nmadd(type, WN_kid0(child), WN_kid1(child), WN_kid2(child));
03084 
03085       case OPR_MSUB:
03086         WN_Delete(tree);
03087         return WN_Nmsub(type, WN_kid0(child), WN_kid1(child), WN_kid2(child));
03088 
03089       case OPR_NMADD:
03090         WN_Delete(tree);
03091         return WN_Madd(type, WN_kid0(child), WN_kid1(child), WN_kid2(child));
03092 
03093       case OPR_NMSUB:
03094         WN_Delete(tree);
03095         return WN_Msub(type, WN_kid0(child), WN_kid1(child), WN_kid2(child));
03096       }
03097     }
03098     break;
03099 
03100   case OPR_ADD:
03101     {
03102       WN        *l= WN_kid0(tree);
03103       WN        *r= WN_kid1(tree);
03104 
03105       if (WN_operator_is(l, OPR_MPY))
03106       {
03107         WN_Delete(tree);
03108         return WN_Madd(type, r, WN_kid0(l), WN_kid1(l));
03109       }
03110       else if (WN_operator_is(r, OPR_MPY))
03111       {
03112         WN_Delete(tree);
03113         return WN_Madd(type, l, WN_kid0(r), WN_kid1(r));
03114       }
03115     }
03116     break;
03117 
03118   case OPR_SUB:
03119     {
03120       WN        *l= WN_kid0(tree);
03121       WN        *r= WN_kid1(tree);
03122 
03123       if (WN_operator_is(l, OPR_MPY))
03124       {
03125         WN_Delete(tree);
03126         return WN_Msub(type, r, WN_kid0(l), WN_kid1(l));
03127       }
03128       else if (WN_operator_is(r, OPR_MPY))
03129       {
03130         WN_Delete(tree);
03131         return WN_Nmsub(type, l, WN_kid0(r), WN_kid1(r));
03132       }
03133     }
03134     break;
03135 
03136   case OPR_MADD:
03137     {
03138       WN        *neg= WN_kid0(tree);
03139 
03140       if (WN_operator_is(neg, OPR_NEG))
03141       {
03142         WN      *child= WN_kid0(neg);
03143 
03144         WN_Delete(neg);
03145         return WN_Msub(type, child, WN_kid1(tree), WN_kid2(tree));
03146       }
03147     }
03148     break;
03149 
03150   case OPR_MSUB:
03151     {
03152       WN        *neg= WN_kid0(tree);
03153 
03154       if (WN_operator_is(neg, OPR_NEG))
03155       {
03156         WN      *child= WN_kid0(neg);
03157 
03158         WN_Delete(neg);
03159         return WN_Madd(type, child, WN_kid1(tree), WN_kid2(tree));
03160       }
03161     }
03162     break;
03163 
03164   case OPR_NMADD:
03165     {
03166       WN        *neg= WN_kid0(tree);
03167 
03168       if (WN_operator_is(neg, OPR_NEG))
03169       {
03170         WN      *child= WN_kid0(neg);
03171 
03172         WN_Delete(neg);
03173         return WN_Nmsub(type, child, WN_kid1(tree), WN_kid2(tree));
03174       }
03175     }
03176     break;
03177 
03178   case OPR_NMSUB:
03179     {
03180       WN        *neg= WN_kid0(tree);
03181 
03182       if (WN_operator_is(neg, OPR_NEG))
03183       {
03184         WN      *child= WN_kid0(neg);
03185 
03186         WN_Delete(neg);
03187         return WN_Nmadd(type, child, WN_kid1(tree), WN_kid2(tree));
03188       }
03189     }
03190     break;
03191   }
03192 
03193   return tree;
03194 }
03195 
03196 
03197 
03198 
03199 /* ====================================================================
03200  *
03201  * WN *lower_tree_height(WN *block, WN *wn, LOWER_ACTIONS actions)
03202  *
03203  *  Reassociate binary commutative operator at this level 
03204  *  (ie no recursion)
03205  *
03206  * ==================================================================== */
03207 
03208 static WN *lower_tree_height(WN *block, WN *wn, LOWER_ACTIONS actions)
03209 {
03210   OPCODE  opcode = WN_opcode(wn);
03211   WN      *l, *r;
03212 
03213   if (NotAction(LOWER_TREEHEIGHT))
03214     return wn;
03215 
03216   Is_True(WN_is_commutative(wn),("expected commutative op"));
03217 
03218   l = WN_kid0(wn);
03219   r = WN_kid1(wn);
03220 
03221  /*
03222   *  do not transform an already balanced tree
03223   */
03224   if (opcode == WN_opcode(l) ^ opcode == WN_opcode(r))
03225 
03226   {
03227     WN *wn1 =  (opcode == WN_opcode(l)) ? l : r;
03228     WN *wn1X = (opcode == WN_opcode(l)) ? r : l;
03229 
03230     WN *wn1_l = WN_kid0(wn1);
03231     WN *wn1_r = WN_kid1(wn1);
03232 
03233     if (opcode == WN_opcode(wn1_l) ^ opcode == WN_opcode(wn1_r))
03234     {
03235 
03236       WN *wn2 =  (opcode == WN_opcode(wn1_l)) ? wn1_l : wn1_r;
03237       WN *wn2X = (opcode == WN_opcode(wn1_l)) ? wn1_r : wn1_l;
03238      /*
03239       *  rearrange tree
03240       */
03241       WN_kid0(wn1) =    wn2X;
03242       WN_kid1(wn1) =    wn1X;
03243 
03244       WN_kid0(wn) =     wn2;
03245       WN_kid1(wn) =     wn1;
03246 
03247       if (traceTreeHeight)
03248       {
03249         DevWarn("lower_tree_height: trace (%s) has been reassociated (line %d)",
03250                 OPCODE_name(WN_opcode(wn)), Srcpos_To_Line(current_srcpos));
03251       }
03252     }
03253   }
03254   return wn;
03255 }
03256 
03257 
03258 
03259 
03260 /* ====================================================================
03261  *
03262  * WN *lower_recip(WN *block, WN *tree, LOWER_ACTIONS actions)
03263  *
03264  * WN *lower_rsqrt(WN *block, WN *tree, LOWER_ACTIONS actions)
03265  *
03266  * lower recip/rsqrt based on ISA flags
03267  *
03268  * Quad is lowered unconditionally, as there is no runtime support
03269  * (kludge alert: turn off simplifer when creating quad divide !!)
03270  *
03271  * ==================================================================== */
03272 
03273 static WN *lower_recip(WN *block, WN *tree, LOWER_ACTIONS actions)
03274 {
03275   TYPE_ID  type = WN_rtype(tree);
03276   WN      *kid0 = WN_kid0(tree);
03277   WN      *div =  NULL;
03278 
03279   Is_True(WN_operator_is(tree, OPR_RECIP), ("expected recip"));
03280   Is_True(MTYPE_float(type), ("expected float type"));
03281 
03282 
03283   if (Recip_Allowed == FALSE)
03284   {
03285     div = WN_Div(type, WN_Floatconst(type, 1.0), kid0);
03286   }
03287   else if (Action(LOWER_QUAD) && MTYPE_is_quad(type))
03288   {
03289     BOOL  simp= WN_Simplifier_Enable(FALSE);
03290 
03291     div = WN_Div(type, WN_Floatconst(type, 1.0), kid0);
03292 
03293     WN_Simplifier_Enable(simp);
03294   }
03295 
03296   if (div)
03297   {
03298     WN_Delete(tree);
03299     return div;
03300   }
03301 
03302   return tree;
03303 }
03304 
03305 static WN *lower_rsqrt(WN *block, WN *tree, LOWER_ACTIONS actions)
03306 {
03307   TYPE_ID  type = WN_rtype(tree);
03308 
03309   Is_True(WN_operator_is(tree, OPR_RSQRT), ("expected rsqrt"));
03310   Is_True(MTYPE_float(WN_rtype(tree)), ("expected float type"));
03311 
03312   if (Rsqrt_Allowed == FALSE || MTYPE_is_quad(type))
03313   {
03314     WN  *div;
03315 
03316     div = WN_Div(type, WN_Floatconst(type, 1.0), WN_Sqrt(type, WN_kid0(tree)));
03317     WN_Delete(tree);
03318 
03319     return div;
03320   }
03321   return tree;
03322 }
03323 
03324 
03325 /* IPA can mark variables gp-relative, even if they are not allocated
03326  * in this source file. To deal with them, we explicitly check if a 
03327  * variable is gp-relative.
03328  */
03329 static BOOL Symbol_Is_Base_Register (ST *sym)
03330 {
03331   return ((ST_class(sym) == CLASS_BLOCK && STB_is_basereg(sym)) ||
03332           (ST_class(sym) == CLASS_VAR && ST_gprel(sym)));
03333 }
03334 
03335 
03336 
03337 /* ====================================================================
03338  *
03339  * WN *lower_split_sym_addrs(WN *tree, INT64 offset, LOWER_ACTIONS actions)
03340  *
03341  * Split symbols into base/offset depending on type/class etc.
03342  *
03343  *
03344  * ==================================================================== */
03345 
03346 static WN *lower_split_sym_addrs(WN *tree, INT64 offset, LOWER_ACTIONS actions)
03347 {
03348   ST *sym  = WN_st(tree);
03349   ST *base = ST_base(sym);
03350   INT64 newoffset = 0;
03351 
03352   if (traceSplitSymOff)
03353     return NULL;
03354 
03355   switch(ST_class(sym))
03356   {
03357   case CLASS_CONST:
03358    /*
03359     *  for non_shared, non-gprelative constants we want to expose the
03360     *  base for RVI
03361     */
03362     if (PIC_NONSHARED && (ST_size(sym) > Max_Sdata_Elt_Size))
03363     {
03364       Allocate_Object(sym);
03365       Base_Symbol_And_Offset_For_Addressing(sym, offset, &base, &newoffset);
03366       return lower_base_reference(tree, base, newoffset, actions);
03367     }
03368     return NULL;
03369 
03370   case CLASS_PREG:
03371     return NULL;
03372 
03373   case CLASS_FUNC:
03374     if (PIC_SHARED && ST_is_preemptible(sym))
03375     {
03376       return NULL;
03377     }
03378     break;
03379 
03380   case CLASS_BLOCK:
03381   case CLASS_VAR:
03382     Base_Symbol_And_Offset_For_Addressing(sym, offset, &base, &newoffset);
03383 
03384     if (ST_is_uplevelTemp(sym))
03385     {
03386       return NULL;
03387     }
03388     if (ST_assigned_to_dedicated_preg(sym)) 
03389     {
03390         return NULL;
03391     }
03392 
03393    /*
03394     *  We cannot keep lowering LDA's or we will forever recurse
03395     */
03396     if (WN_operator_is(tree, OPR_LDA) && base == sym) 
03397       return NULL;
03398 
03399     switch(ST_sclass(sym))
03400     {
03401     case SCLASS_REG:
03402     case SCLASS_TEXT:
03403       return NULL;
03404 
03405     case SCLASS_FORMAL_REF:     
03406      /*
03407       *  If we expand the base, we will lose the FORMAL_REF'ness of the ST
03408       *  and will not be able to dereference it later
03409       */
03410       if (base != sym)
03411       {
03412         base =  sym;
03413       }
03414       break;
03415 
03416     case SCLASS_FORMAL:
03417      /*
03418       *  Do not allocate Formal_Arg_StkSeg, as it is not correct yet !!
03419       *  (it will eventually be .sp + <offset> )
03420       */
03421       return NULL;
03422 
03423     case SCLASS_AUTO:
03424       /* 
03425        * For now, never split a stack variable.
03426        * We only see stack variables with bases when we do regions,
03427        * and for now we want to keep those cases looking like the
03428        * regular cases for correctness.  But at a later date we should
03429        * try to split these in the region case, as that may allow a
03430        * base register to be allocated for things like FP+32000,
03431        * so we could then get 1-instruction accesses to large offsets.
03432        * But that requires a cgexp change too, so wait on it.
03433        */
03434 #if 0
03435       if (Uses_Small_Offset(sym, offset))
03436         break;
03437 #endif
03438       return NULL;
03439 
03440     case SCLASS_EXTERN:
03441      /*
03442       * okay to split these. A dlopen() can never redefine these (unless
03443       * they are weak)
03444       */
03445       if (ST_is_weak_symbol(sym))
03446         return NULL;
03447       break;
03448 
03449     case SCLASS_COMMON:
03450      /*
03451       * commons may be preempted by a dlopen() (if the new definition is
03452       * initialized) see wilson/lillian for details of this rather obscure
03453       * point suneel says not to worry about this though, so please direct
03454       * bugs to him
03455       *
03456       * In the new symbol table, we need to also split common symbols
03457       * here. The reason is that now both members and the common itself
03458       * are SCLASS_COMMON, whereas before they used to be SCLASS_BASED.
03459       * We no longer have to worry about the ST_Full that was present in
03460       * the old symbol table
03461       */
03462       sym = base;
03463       break;
03464 
03465     case SCLASS_PSTATIC:
03466     case SCLASS_UGLOBAL:
03467     case SCLASS_DGLOBAL:
03468     case SCLASS_FSTATIC:
03469      /*
03470       *  okay to split these. We will never split incorrectly as
03471       *  Base_Symbol_And_Offset_For_Addressing() will not split a preemptible
03472       *  symbol
03473       */
03474       break;
03475 
03476     default:
03477       return NULL;
03478     }
03479 
03480     if (ST_gprel(sym))
03481     {
03482       return NULL;
03483     }
03484     tree = lower_base_reference(tree, base, newoffset, actions);
03485     return tree;
03486 
03487   default:
03488     return NULL;
03489   }
03490 
03491   return NULL;
03492 }
03493 
03494 
03495 
03496 
03497 /* ====================================================================
03498  *
03499  * WN *lower_uplevel_reference(WN *tree, INT64 offset, LOWER_ACTIONS actions)
03500  *
03501  * Split uplevel symbols into indirect of slink
03502  *
03503  * ==================================================================== */
03504 
03505 static WN *lower_uplevel_reference(WN *tree, INT64 offset,
03506                                    LOWER_ACTIONS actions)
03507 {
03508   ST    *sym = WN_st(tree);
03509   ST    *base;
03510   INT64 newoffset;
03511 
03512   Is_True(ST_is_uplevelTemp(sym), ("expected uplevel %s",ST_name(sym)));
03513 
03514   Base_Symbol_And_Offset_For_Addressing(sym, offset, &base, &newoffset);
03515   base = Find_Slink_For_ST(sym);
03516 
03517   tree = lower_dereference(tree, newoffset, base, 0, actions);
03518   return tree;
03519 }
03520 
03521 
03522 
03523 
03524 /* ====================================================================
03525  *
03526  * WN *lower_formal_ref(WN *tree, INT64 offset, ST *base,
03527  *                      LOWER_ACTIONS actions)
03528  *
03529  * lower an SCLASS_FORMAL_REF into a dereference of the new base.
03530  * or
03531  * lower an SCLASS_FORMAL into a preg, already computed
03532  *
03533  * ==================================================================== */
03534 static WN *lower_formal_ref(WN *tree, INT64 offset, ST *base,
03535                             LOWER_ACTIONS actions)
03536 {
03537   PREG_NUM      preg;
03538 
03539   switch(ST_sclass(base))
03540   {
03541   case SCLASS_FORMAL_REF:
03542     base = Get_ST_formal_ref_base(base);
03543     if (preg = Get_ST_formal_preg_num(base))
03544     {
03545       Is_True((ST_has_nested_ref(WN_st(tree))==FALSE),
03546               ("lower_formal_ref: cannot use preg for nested ref %s",
03547                ST_name(WN_st(tree))));
03548       base = MTYPE_To_PREG(TY_mtype(Ty_Table[ST_type(base)]));
03549     }
03550     return lower_dereference(tree, offset, base, preg, actions);
03551 
03552   case SCLASS_FORMAL:
03553     if (preg= Get_ST_formal_preg_num(base))
03554     {
03555       base = MTYPE_To_PREG(TY_mtype(Ty_Table[ST_type(base)]));
03556       tree = lower_base_register(tree, base, preg, actions);
03557       return tree;
03558     }
03559     break;
03560   }
03561   return NULL;
03562 }
03563 
03564 
03565 
03566 
03567 /* ====================================================================
03568  *
03569  * WN *lower_base_register(WN *tree, ST *base, INT64 offset,
03570  *                         LOWER_ACTIONS actions)
03571  *
03572  * common routine for lowering to a base register for LDA, LDID, STID
03573  * into using a new base/offset
03574  *
03575  * ==================================================================== */
03576 
03577 static WN *lower_base_register(WN *tree, ST *base, INT64 offset,
03578                                LOWER_ACTIONS actions)
03579 {
03580   Is_True(WN_st(tree) != base, ("lower_base_register(): possible recursion"));
03581 
03582   switch (WN_operator(tree))
03583   {
03584   case OPR_LDA:
03585    /*
03586     * Convert
03587     *     LDA (offset) <sym> into
03588     *
03589     *     LDA (offset) <base>
03590     */
03591     WN_st_idx(tree) = ST_st_idx(base);
03592     WN_lda_offset(tree) = mem_offset_hi(offset);
03593     return tree;
03594 
03595   case OPR_LDID:
03596    /*
03597     * Convert
03598     *     LDID (offset> <sym>  into
03599     *     LDID (offset <base>
03600     */
03601     WN_st_idx(tree) = ST_st_idx(base);
03602     WN_load_offset(tree) = offset;
03603     break;
03604 
03605   case OPR_STID:
03606    /*
03607     * Convert
03608     *     STID (offset> <sym>  into
03609     *     STID (offset <base>
03610     */
03611     WN_st_idx(tree) = ST_st_idx(base);
03612     WN_store_offset(tree) = offset;
03613     break;
03614 
03615   default:
03616     Is_True(FALSE,("expected lda/ldid/stid"));
03617     return NULL;
03618   }
03619 
03620   return tree;
03621 }
03622 
03623 
03624 // replace the type of LDID/STID nodes with non-zero field_id to the type
03625 // of the field
03626 static void
03627 lower_field_id (WN* tree)
03628 {
03629   OPERATOR opr = WN_operator(tree);
03630 
03631   Is_True (opr == OPR_LDID || opr == OPR_STID || opr == OPR_MLOAD ||
03632            opr == OPR_MSTORE, ("expecting LDID or STID nodes"));
03633 
03634   if (WN_field_id (tree) == 0)
03635     return;
03636 
03637   BOOL is_ptr_type = (opr == OPR_MLOAD || opr == OPR_MSTORE);
03638 
03639   TY_IDX ty_idx = is_ptr_type ? TY_pointed (WN_ty (tree)) : WN_ty (tree);
03640 
03641   Is_True (TY_kind (ty_idx) == KIND_STRUCT,
03642            ("non-zero field id must have KIND_STRUCT"));
03643 
03644   UINT field_id = 0;
03645   FLD_HANDLE fld = FLD_get_to_field (ty_idx, WN_field_id (tree), field_id); 
03646   
03647   Is_True (! fld.Is_Null (), ("invalid bit-field ID for %s",
03648                               OPERATOR_name(opr)));
03649 
03650   WN_set_ty (tree, (is_ptr_type ? Make_Pointer_Type (FLD_type (fld)) :
03651                     FLD_type (fld)));
03652   WN_set_field_id (tree, 0);
03653   return;
03654 } // lower_field_id
03655 
03656 
03657 /* ====================================================================
03658  *
03659  * WN *lower_base_reference(WN *tree, ST *base, INT64 offset,
03660  *                          LOWER_ACTIONS actions)
03661  *
03662  * common routine for lowering to a base reference for LDA, LDID, STID
03663  *
03664  * ==================================================================== */
03665 
03666 static WN *lower_base_reference(WN *tree, ST *base, INT64 offset,
03667                                 LOWER_ACTIONS actions)
03668 {
03669   WN    *addr, *wn;
03670 
03671   switch (WN_operator(tree))
03672   {
03673   case OPR_LDA:
03674    /*
03675     * Convert
03676     *     LDA (offset) <sym>
03677     * 
03678     * (lo > 0)
03679     *       LDA (hi) <base>
03680     *       CONST (lo)
03681     *     ADD
03682     *
03683     * (offset >= 2GB)
03684     *       LDA (0) <base>
03685     *       CONST (offset)
03686     *     ADD
03687     */
03688 
03689     WN_st_idx(tree) = ST_st_idx(base);
03690 
03691     if (mem_offset_2GB(offset))
03692     {
03693       addr =    WN_Add(Pointer_type, tree, WN_Intconst(Pointer_type, offset));
03694       WN_lda_offset(tree)=  0;
03695       return addr;
03696     }
03697     else if (Action(LOWER_SPLIT_CONST_OFFSETS)  &&
03698              mem_offset_lo(offset))
03699     {
03700      /* turn off simplifier else ADD may be removed */
03701       BOOL  simp=        WN_Simplifier_Enable(FALSE);
03702 
03703       addr =    WN_Add(Pointer_type,
03704                        tree,
03705                        WN_Intconst(Pointer_type, mem_offset_lo(offset)));
03706       WN_lda_offset(tree)=      mem_offset_hi(offset);
03707 
03708       WN_Simplifier_Enable(simp);
03709       return addr;
03710     }
03711     WN_lda_offset(tree)=  offset;
03712     return tree;
03713 
03714   case OPR_LDID:
03715   case OPR_STID:
03716   case OPR_LDBITS:
03717   case OPR_STBITS:
03718    /*
03719     * Process the common address
03720     *
03721     * if (offset > 2GB)
03722     *      LDA (hi) <sym>
03723     *      CONST offset
03724     *    ADD
03725     *
03726     * if (offset > 16K)
03727     *      LDA (hi) <sym>
03728     *    ILOAD | ISTORE (lo)
03729     */
03730     addr =      WN_Lda(Pointer_type, 0, base);
03731 
03732     if (mem_offset_2GB(offset))
03733     {
03734       addr =    WN_Add(Pointer_type, addr, WN_Intconst(Pointer_type, offset));
03735       offset =  0;
03736     }
03737     if (Action(LOWER_SPLIT_CONST_OFFSETS) && mem_offset_must_be_split(offset))
03738     {
03739       WN_lda_offset(addr) =     mem_offset_hi(offset);
03740       offset =                  mem_offset_lo(offset);
03741     }
03742     break;
03743 
03744   default:
03745     Is_True(FALSE,("expected lda/ldid/stid"));
03746     return NULL;
03747   }     
03748 
03749   switch (WN_operator(tree))
03750   {
03751   case OPR_LDID:
03752    /*
03753     * Convert (LDID () <sym>) into
03754     *      LDA (0) <base>
03755     *    ILOAD (offset+ofst)
03756     */
03757     if (WN_field_id (tree) != 0)
03758       lower_field_id (tree);
03759     
03760     wn =        WN_RIload(WN_rtype(tree), WN_desc(tree), offset, WN_ty(tree),
03761                           addr);
03762     break;
03763   case OPR_LDBITS:
03764     wn =        WN_RIload(WN_rtype(tree), WN_desc(tree), offset, WN_ty(tree),
03765                           addr);
03766     WN_set_operator(wn, OPR_ILDBITS);
03767     WN_set_bit_offset_size(wn, WN_bit_offset(tree), WN_bit_size(tree));
03768     break;
03769 
03770   case OPR_STID:
03771    /*
03772     * Convert   STID (offset) <sym>
03773     *  into
03774     *       LDA (0) <base>
03775     *     ISTORE (offs+ofst)
03776     */
03777     if (WN_field_id (tree) != 0)
03778       lower_field_id (tree);
03779     
03780     wn =        WN_Istore(WN_desc(tree),
03781                           offset,
03782                           // The resulting TY is not an f90 pointer
03783                           // type because we're converting an STID.
03784                           // In the case where this STID
03785                           // came about because of conversion of
03786                           // ISTORE(something) in the past, and that
03787                           // ISTORE was through an f90 pointer, the
03788                           // destination of the STID will have the
03789                           // F90_TARGET attribute, and we're OK.
03790                           Make_Pointer_Type(WN_ty(tree)),
03791                           addr,
03792                           WN_kid0(tree));
03793     WN_Set_Linenum(wn, WN_Get_Linenum(tree));
03794     break;
03795   case OPR_STBITS:
03796     wn =        WN_Istore(WN_desc(tree),
03797                           offset,
03798                           Make_Pointer_Type(WN_ty(tree)),
03799                           addr,
03800                           WN_kid0(tree));
03801     WN_set_operator(wn, OPR_ISTBITS);
03802     WN_set_bit_offset_size(wn, WN_bit_offset(tree), WN_bit_size(tree));
03803     WN_Set_Linenum(wn, WN_Get_Linenum(tree));
03804     break;
03805   }     
03806 
03807   lower_copy_maps(tree, wn, actions);
03808   WN_Delete(tree);
03809 
03810   return wn;
03811 }
03812 
03813 
03814 
03815 /* ====================================================================
03816  *
03817  * WN *lower_dereference(WN *tree, INT64 offset, ST *base,
03818  *                       PREG_NUM *preg, LOWER_ACTIONS actions)
03819  *
03820  * Perform address dereferencing for SCLASS_FORMAL_REF and uplevel variable
03821  * Caller is responsible for any further lowering.
03822  *
03823  *  For uplevel references the idea is to replace the st with a reference
03824  *  of the slink_sym at level ST_level(st) + 1
03825  *  This will only work recursively
03826  *  (ie. that sym must be referenced via the next level's scope
03827  *
03828  * ==================================================================== */
03829 static WN
03830 *lower_dereference(WN *tree, INT64 offset, ST *base, PREG_NUM preg,
03831                    LOWER_ACTIONS actions)
03832 {
03833   WN     *addr, *deref;
03834   TY_IDX  addr_ty;
03835 
03836   switch (WN_operator(tree))
03837   {
03838   case OPR_LDA:
03839    /*
03840     * Convert uplevel reference
03841     *     LDA (offset) <sym>
03842     *  into 
03843     *       LDID (0) <base>
03844     *       CONST (offset)    
03845     *     ADD
03846     */
03847     deref =     WN_Ldid(Pointer_type, preg, base, WN_ty(tree));
03848     addr =      WN_Add(Pointer_type, deref, WN_Intconst(Pointer_type, offset));
03849     return addr;
03850 
03851   case OPR_LDID:
03852   case OPR_STID:
03853    /*
03854     * Process the common address
03855     *
03856     */
03857     addr_ty = Make_Pointer_Type(WN_ty(tree));
03858     addr =      WN_Ldid(Pointer_type, preg, base, addr_ty);
03859 
03860     if (mem_offset_2GB(offset))
03861     {
03862       addr =    WN_Add(Pointer_type, addr, WN_Intconst(Pointer_type, offset));
03863       offset =  0;
03864     }
03865     break;
03866 
03867   default:
03868     Is_True(FALSE,("expected lda/ldid/stid"));
03869     return NULL;
03870   }     
03871 
03872   switch (WN_operator(tree))
03873   {
03874   case OPR_LDID:
03875    /*
03876     * Convert uplevel reference  LDID () <sym>
03877     * into
03878     *      LDID (preg) <base>
03879     *    ILOAD (offset)
03880     */
03881     deref = WN_RIload(WN_rtype(tree), WN_desc(tree), offset, WN_ty(tree), addr);
03882     break;
03883 
03884   case OPR_STID:
03885    /*
03886     * Convert  STID () <sym>
03887     * into
03888     *       LDID (preg) <base> 
03889     *     ISTORE (offset)          
03890     */
03891     deref = WN_Istore(WN_desc(tree), offset, addr_ty, addr, WN_kid0(tree));
03892     WN_Set_Linenum(deref, WN_Get_Linenum(tree));
03893     break;
03894   }     
03895 
03896   lower_copy_maps(tree, deref, actions);
03897   WN_Delete(tree);
03898 
03899   return deref;
03900 }
03901 
03902 /* ====================================================================
03903  *
03904  * WN *lower_return_ldid(WN *block, WN *tree, LOWER_ACTIONS actions)
03905  *
03906  * Perform lowering (see WN_Lower description) on 'LDID Return_Val_Preg'
03907  * nodes returning a lowered 'LDID normal_PREG' node.
03908  *
03909  * ==================================================================== */
03910 
03911 static WN *lower_return_ldid(WN *block, WN *tree, LOWER_ACTIONS actions)
03912 {
03913   TY_IDX   ty_idx  = WN_ty(tree);
03914   TY&      ty      = Ty_Table[ty_idx];
03915   TYPE_ID  mtype   = TY_mtype (ty);
03916 
03917   Is_True((WN_operator(tree) == OPR_LDID),
03918           ("expected LDID node, not %s", OPCODE_name(WN_opcode(tree))));   
03919 
03920   switch (mtype) {
03921 
03922     case MTYPE_I8:
03923     case MTYPE_U8:
03924       WN_st_idx(tree) = ST_st_idx(MTYPE_To_PREG(mtype));
03925       WN_load_offset(tree) = First_Int_Preg_Return_Offset;
03926       return tree;
03927 
03928     case MTYPE_I1:
03929     case MTYPE_I2:
03930     case MTYPE_I4:
03931     case MTYPE_U1:
03932     case MTYPE_U2:
03933     case MTYPE_U4:
03934       WN_st_idx(tree) = ST_st_idx(Int_Preg);
03935       WN_load_offset(tree) = First_Int_Preg_Return_Offset;
03936       return tree;
03937 
03938     case MTYPE_F4:
03939     case MTYPE_F8:
03940     case MTYPE_FQ:
03941     case MTYPE_C4:
03942     case MTYPE_C8:
03943     case MTYPE_CQ:
03944       WN_st_idx(tree) = ST_st_idx(Float_Preg);
03945       WN_load_offset(tree) = First_Float_Preg_Return_Offset;
03946       return tree;
03947 
03948     case MTYPE_M:
03949       Fail_FmtAssertion ("MLDID of Return_Val_Preg not allowed in middle"
03950                          " of expression");
03951       /*NOTREACHED*/
03952     default:
03953       Fail_FmtAssertion ("Unexpected type in lower_return_ldid");
03954       /*NOTREACHED*/
03955   }
03956 }
03957 
03958 
03959 static TY_IDX
03960 get_field_type (TY_IDX struct_type, UINT field_id)
03961 {
03962   Is_True (TY_kind (struct_type) == KIND_STRUCT, ("expecting KIND_STRUCT"));
03963   UINT cur_field_id = 0;
03964   FLD_HANDLE fld = FLD_get_to_field (struct_type, field_id, cur_field_id);
03965   Is_True (! fld.Is_Null(), ("Invalid field id %d for type 0x%x",
03966                              field_id, struct_type));
03967   return FLD_type (fld);
03968 }
03969 
03970 
03971 /* ====================================================================
03972  *
03973  * WN *lower_mldid(WN *block, WN *tree, LOWER_ACTIONS actions)
03974  *
03975  * Perform lowering (see WN_Lower description) on MLDID nodes returning
03976  * an equivalent MLOAD node.  Note that MLDID's of Return_Val_Preg are
03977  * not lowered here.  They are handled by lower_return_ldid.
03978  *
03979  * ==================================================================== */
03980 
03981 static WN *lower_mldid(WN *block, WN *tree, LOWER_ACTIONS actions)
03982 {
03983   TY_IDX ty_idx  = WN_ty(tree);
03984   TY_IDX fld_idx = WN_field_id(tree) == 0 ? 0 : 
03985     get_field_type (ty_idx, WN_field_id (tree));
03986   TY_IDX pty_idx;
03987 
03988   UINT64 size    = fld_idx == 0 ? TY_size(ty_idx) : TY_size(fld_idx);
03989   
03990   if(Action(LOWER_UPC_MFIELD) && WN_field_id(tree) && Type_Is_Shared_Ptr(fld_idx))
03991     size = TY_size(TY_To_Sptr_Idx(fld_idx));
03992 
03993   WN*    wn;
03994   WN*    awn;
03995   WN*    swn;
03996 
03997   Is_True((WN_opcode(tree) == OPC_MMLDID),
03998           ("expected mldid node, not %s", OPCODE_name(WN_opcode(tree))));
03999 
04000   pty_idx = Make_Pointer_Type (ty_idx, FALSE);
04001 
04002   swn = WN_CreateIntconst(OPC_U4INTCONST, size);
04003   awn = WN_CreateLda(OPR_LDA, Pointer_Mtype, MTYPE_V, WN_load_offset(tree),
04004                      pty_idx, WN_st(tree));
04005   wn  = WN_CreateMload(0, pty_idx, awn, swn);
04006   WN_set_field_id(wn, WN_field_id(tree));
04007   wn  = lower_expr(block, wn, actions);
04008 
04009   WN_Delete(tree);
04010   return wn;
04011 }
04012 
04013 /* ====================================================================
04014  *
04015  * WN *lower_miload(WN *block, WN *tree, LOWER_ACTIONS actions)
04016  *
04017  * Perform lowering (see WN_Lower description) on MILOAD nodes returning
04018  * an equivalent MLOAD node.
04019  *
04020  * ==================================================================== */
04021 
04022 static WN *lower_miload(WN *block, WN *tree, LOWER_ACTIONS actions)
04023 {
04024   TY_IDX ty_idx  = WN_field_id (tree) == 0 ?
04025     WN_ty(tree) :
04026     get_field_type (WN_ty (tree), WN_field_id (tree));
04027   TY_IDX pty_idx = WN_load_addr_ty(tree);
04028   UINT64 size    = TY_size(Ty_Table[ty_idx]);
04029   if(Action(LOWER_UPC_MFIELD) && WN_field_id(tree) && Type_Is_Shared_Ptr(ty_idx)) {
04030     pty_idx = Make_Pointer_Type(WN_ty(tree));
04031     size = TY_size(TY_To_Sptr_Idx(ty_idx));
04032   }
04033   WN*    wn;
04034   WN*    swn;
04035 
04036   Is_True((WN_opcode(tree) == OPC_MMILOAD),
04037           ("expected miload node, not %s", OPCODE_name(WN_opcode(tree))));
04038 
04039   swn = WN_CreateIntconst (OPC_U4INTCONST, size);
04040   wn  = WN_CreateMload (WN_offset(tree), pty_idx, WN_kid0(tree), swn);
04041   WN_set_field_id(wn, WN_field_id(tree));
04042   // if(Action(LOWER_UPC_MFIELD))
04043 //     return wn;
04044   wn  = lower_expr (block, wn, actions);
04045 
04046   WN_Delete (tree);
04047   return wn;
04048 }
04049 
04050 /* ====================================================================
04051  *
04052  * lower_load_bits
04053  *
04054  * lower LDBITS and ILDBITS into shifts
04055  *
04056  * ==================================================================== */
04057 static WN*
04058 lower_load_bits (WN* block, WN* wn, LOWER_ACTIONS actions)
04059 {
04060   Is_True (WN_operator (wn) == OPR_LDBITS || WN_operator (wn) == OPR_ILDBITS,
04061            ("expected LDBITS or ILDBITS, not %s",
04062             OPERATOR_name(WN_operator(wn))));
04063 
04064   TYPE_ID rtype = WN_rtype (wn);
04065   TYPE_ID desc = WN_desc (wn);
04066   INT delta = MTYPE_bit_size(rtype) - MTYPE_bit_size(desc);
04067   if (delta < 0) {
04068     rtype = Mtype_TransferSize (desc, rtype);
04069     delta = 0;
04070   }
04071 
04072   WN* tree = wn;
04073 
04074   INT bit_size = WN_bit_size (wn);
04075   INT bit_ofst = Target_Byte_Sex == BIG_ENDIAN ?
04076     WN_bit_offset (wn) :
04077     MTYPE_bit_size(desc) - bit_size - WN_bit_offset (wn);
04078   BOOL bits_signed = MTYPE_signed(rtype);
04079   
04080   if (bit_ofst == 0)
04081     bit_size += delta;
04082   else {
04083     bit_ofst += delta;
04084     if (bits_signed)
04085       tree = WN_Shl (rtype, tree, WN_Intconst (MTYPE_I4, bit_ofst));
04086     else {
04087       INT shift_count = 64 - (MTYPE_bit_size(rtype) - bit_ofst);
04088       mUINT64 mask = (~(mUINT64)0) >> shift_count;
04089       tree = WN_Band (rtype, tree,
04090                       WN_Intconst (Mtype_TransferSign (MTYPE_U4, rtype),
04091                                    mask));
04092       bit_size += bit_ofst;
04093     }
04094   }
04095 
04096   INT right_shift = MTYPE_bit_size(rtype) - bit_size;
04097 
04098   if (right_shift > 0) {
04099     OPERATOR opr = bits_signed ? OPR_ASHR : OPR_LSHR;
04100     tree = WN_Binary (opr, rtype, tree, WN_Intconst (MTYPE_I4, right_shift));
04101   }
04102 
04103   TYPE_ID orig_rtype = WN_rtype (wn);
04104   
04105   WN_set_rtype (wn, rtype);
04106   WN_set_bit_offset_size (wn, 0, 0);
04107   WN_set_operator (wn, WN_operator (wn) == OPR_LDBITS ? OPR_LDID : OPR_ILOAD);
04108 
04109   if (rtype != orig_rtype)
04110     tree = WN_Type_Conversion (tree, orig_rtype);
04111 
04112   return lower_expr (block, tree, actions);
04113 } // lower_load_bits
04114 
04115 
04116 /* ====================================================================
04117  *
04118  * lower_store_bits
04119  *
04120  * lower STBITS and ISTBITS
04121  *
04122  * ==================================================================== */
04123 static WN*
04124 lower_store_bits (WN* block, WN* wn, LOWER_ACTIONS actions)
04125 {
04126   Is_True (WN_operator (wn) == OPR_STBITS || WN_operator (wn) == OPR_ISTBITS,
04127            ("expected STBITS or ISTBITS, not %s",
04128             OPERATOR_name (WN_operator (wn))));
04129 
04130   INT bit_size = WN_bit_size (wn);
04131   INT bit_ofst = WN_bit_offset (wn); 
04132 
04133   WN* orig_value;
04134 
04135   if (WN_operator (wn) == OPR_ISTBITS) {
04136     WN* load_address = lower_copy_tree (WN_kid1 (wn), actions);
04137     orig_value = WN_Iload (Mtype_TransferSign (MTYPE_U4, WN_desc (wn)),
04138                            WN_offset (wn), WN_ty (wn), load_address, 0);
04139   } else 
04140     orig_value = WN_Ldid (Mtype_TransferSign (MTYPE_U4, WN_desc (wn)),
04141                           WN_offset (wn), WN_st_idx (wn), WN_ty (wn), 0);
04142   
04143   TYPE_ID cmp_type = WN_rtype (orig_value);
04144   
04145   INT shift = Target_Byte_Sex == BIG_ENDIAN ?
04146       MTYPE_bit_size (WN_desc (wn)) - bit_ofst - bit_size :
04147       bit_ofst;
04148   mUINT64 mask = ~((~((mUINT64)0) >> (64 - bit_size)) << shift);
04149   orig_value = WN_Band (cmp_type, orig_value, WN_Intconst (cmp_type, mask));
04150 
04151   WN* new_value = WN_kid0 (wn);
04152 
04153   // check if we need to sign-extend the value
04154   if (bit_size > MTYPE_bit_size (WN_rtype (new_value)))
04155     new_value =
04156       WN_CreateCvtl (OPR_CVTL,
04157                      Mtype_TransferSign (WN_rtype (new_value), cmp_type),
04158                      WN_rtype (new_value),
04159                      MTYPE_bit_size (WN_rtype (new_value)),
04160                      new_value);
04161   
04162   // now, truncate to the right bit size for store
04163   mask = ~((mUINT64)0) >> (64 - bit_size);
04164   new_value =
04165     WN_Band (cmp_type, new_value,
04166              WN_Intconst (Mtype_TransferSize (WN_rtype (new_value), cmp_type),
04167                           mask));
04168 
04169   // move the bits to the right position
04170   if (shift > 0)
04171     new_value = WN_Shl (cmp_type, new_value, WN_Intconst (cmp_type, shift));
04172 
04173   // set the value with bitwise or
04174   new_value = WN_Bior (cmp_type, orig_value, new_value);
04175 
04176   WN_kid0 (wn) = new_value;
04177   WN_set_bit_offset_size (wn, 0, 0);
04178   WN_set_operator (wn, WN_operator(wn) == OPR_STBITS ? OPR_STID : OPR_ISTORE);
04179 
04180   return lower_store (block, wn, actions);
04181 } // lower_store_bits
04182 
04183 #if 0
04184 /* ====================================================================
04185  *
04186  * check_unaligned
04187  *
04188  * required_alignment is the natural alignment; offset is the actual offset
04189  * used in the current access; ty_align is the alignment in the TY of the
04190  * current access.  Return whether the access is unaligned.
04191  *
04192  * ==================================================================== */
04193 static bool check_unaligned(INT required_alignment, INT offset, INT ty_align)
04194 {
04195   if (required_alignment <= 1)
04196     return FALSE;
04197   INT align = ty_align;
04198   if (offset) {
04199     INT offset_align = offset % required_alignment;
04200     if (offset_align)
04201       align = MIN(align, offset_align);
04202   }
04203   return align < required_alignment;
04204 }
04205 #endif
04206 
04207 
04208 // --------------------------------------------------------------------
04209 // This function mimics FLD_get_to_field from common/com/symtab.cxx,
04210 // but it also computes the offset of <field_id> within <struct_ty_idx>
04211 // We need this because FLD_ofst only gives the offset within the first
04212 // enclosing struct.
04213 // --------------------------------------------------------------------
04214 FLD_HANDLE
04215 FLD_And_Offset_From_Field_Id (TY_IDX  struct_ty_idx, 
04216                               UINT    field_id, 
04217                               UINT&   cur_field_id,
04218                               UINT64& offset)
04219 {
04220   FLD_ITER fld_iter = Make_fld_iter(TY_fld(struct_ty_idx));
04221   do {
04222     FLD_HANDLE fld(fld_iter);
04223     cur_field_id++;
04224     if (cur_field_id == field_id) {
04225       offset += FLD_ofst(fld);
04226       return fld;
04227     }
04228     if (TY_kind(FLD_type(fld)) == KIND_STRUCT &&
04229         TY_fld(FLD_type(fld)) != FLD_HANDLE()) {
04230       UINT64 nested_offset = offset + FLD_ofst(fld);
04231       fld = FLD_And_Offset_From_Field_Id(FLD_type(fld), field_id, 
04232                                          cur_field_id, nested_offset);
04233       if (cur_field_id == field_id) {
04234         offset = nested_offset;
04235         return fld;
04236       }
04237     }
04238   } while (!FLD_last_field(fld_iter++));
04239   
04240   return FLD_HANDLE();
04241 } 
04242 
04243 /* ====================================================================
04244  *
04245  * lower_bit_field_id
04246  *
04247  * The given LDID/STID/ILOAD/ISTORE node has desc type MTYPE_BS.  Lower
04248  * the node by changing the field_id to bit_offset/bit_size combination.
04249  * The desc field is changed to reflect the unit in memory to load, and
04250  * the offset field may need to be updated.
04251  *
04252  * ==================================================================== */
04253 static void lower_bit_field_id(WN *wn)
04254 {
04255   TY_IDX struct_ty_idx;
04256   TY_IDX ty_idx;
04257   TYPE_ID rtype;
04258   OPERATOR opr = WN_operator(wn);
04259   OPERATOR new_opr;
04260   BOOL indirect;
04261   if (opr == OPR_LDID || opr == OPR_STID) {
04262     ST_IDX st_idx = WN_st_idx(wn);
04263     struct_ty_idx = WN_ty(wn);
04264     new_opr = (opr == OPR_LDID) ? OPR_LDBITS : OPR_STBITS;
04265     indirect = FALSE;
04266   }
04267   else {
04268     if (WN_operator(wn) == OPR_ILOAD) {
04269       ty_idx = WN_load_addr_ty(wn);
04270       new_opr = OPR_ILDBITS;
04271     }
04272     else {      // ISTORE
04273       ty_idx = WN_ty(wn);
04274       new_opr = OPR_ISTBITS;
04275     }
04276     Is_True(TY_kind(ty_idx) == KIND_POINTER,
04277             ("addr ty not pointer type for %s", OPERATOR_name(opr)));
04278     struct_ty_idx = TY_pointed(ty_idx);
04279     indirect = TRUE;
04280   }
04281   Is_True(TY_kind(struct_ty_idx) == KIND_STRUCT,
04282           ("struct type not associated with bit-field access for %s", OPERATOR_name(opr)));
04283   UINT cur_field_id = 0;
04284   UINT64 field_offset = 0;
04285   FLD_HANDLE fld = FLD_And_Offset_From_Field_Id(struct_ty_idx, 
04286                                                 WN_field_id(wn),
04287                                                 cur_field_id,
04288                                                 field_offset); 
04289   Is_True(! fld.Is_Null(),
04290           ("invalid bit-field ID for %s", OPERATOR_name(opr)));
04291   TY_IDX fld_ty_idx = FLD_type(fld);
04292   WN_set_ty (wn, (opr == OPR_ISTORE ?
04293                   Make_Pointer_Type (fld_ty_idx, FALSE) :
04294                   fld_ty_idx));
04295   
04296   Is_True(FLD_is_bit_field(fld),
04297           ("non-bit-field associated with bit-field access for  %s", OPERATOR_name(opr)));
04298 
04299   // analyze bit field accessed
04300   UINT bytes_accessed = TY_size(fld_ty_idx);
04301   if (OPERATOR_is_store(new_opr))
04302     rtype = TY_mtype(fld_ty_idx);
04303   else rtype = WN_rtype(wn);
04304   INT ofst = field_offset;
04305 #if 0
04306   BOOL unaligned_field = check_unaligned(bytes_accessed * 8, ofst,
04307                                          TY_align(struct_ty_idx));
04308 #endif
04309   if (ofst >= 0)
04310     ofst = ofst / bytes_accessed * bytes_accessed;
04311   else ofst =  (ofst - bytes_accessed + 1) / bytes_accessed * bytes_accessed;
04312   UINT bsize = FLD_bsize(fld);
04313   UINT bofst = FLD_bofst(fld) + (field_offset-ofst) * 8;
04314   if ((bofst + bsize) > (bytes_accessed * 8)) {
04315     if (bytes_accessed == MTYPE_byte_size(Max_Int_Mtype)) { 
04316       // can't enlarge; reverse the adjustment
04317       ofst = field_offset;
04318       bofst = FLD_bofst(fld);
04319     }
04320     else bytes_accessed *= 2;
04321   }
04322   WN_load_offset(wn) = WN_load_offset(wn) + ofst; 
04323 
04324   if ((bsize & 7) == 0 &&                  // field size multiple of bytes
04325       (bytes_accessed * 8 % bsize) == 0 && // bytes_accessed multiple of bsize
04326       (bofst % bsize) == 0) {              // bofst multiple of bsize
04327     // bit-field operation not needed; leave operator as previous one
04328     WN_set_field_id(wn, 0);
04329     WN_set_desc(wn, Mtype_AlignmentClass(bsize >> 3, MTYPE_type_class(rtype)));
04330     WN_load_offset(wn) = WN_load_offset(wn) + (bofst >> 3);
04331   }
04332   else { // generate lowered-to bit-field operator
04333 #if defined(TARG_MIPS) || defined(TARG_IA32)
04334     if ((indirect || WN_class(wn) != CLASS_PREG) && 
04335         bofst % 8 == 0 &&               // bit offset on byte boundary
04336         compute_offset_alignment(bytes_accessed*8, bofst) >= bsize) {
04337       // adjust bytes accessed to get rid of the left-shift
04338       WN_load_offset(wn) = WN_load_offset(wn) + (bofst >> 3);
04339       bytes_accessed = compute_offset_alignment(bytes_accessed, bofst >> 3);
04340       bofst = 0;
04341     }
04342 #endif
04343     WN_set_operator(wn, new_opr);
04344     WN_set_desc(wn, Mtype_AlignmentClass(bytes_accessed, MTYPE_type_class(rtype)));
04345     if (OPERATOR_is_load(new_opr) && 
04346         MTYPE_byte_size(WN_rtype(wn)) < bytes_accessed)
04347       WN_set_rtype(wn, WN_desc(wn));
04348     WN_set_bit_offset_size(wn, bofst, bsize);
04349   }
04350 }
04351 
04352 static void lower_trapuv_alloca (WN *block, WN *tree, LOWER_ACTIONS actions)
04353 {
04354         WN *size = WN_kid0(tree);
04355         WN *con = WN_UVConst(WN_rtype(size));
04356         WN *mstore;
04357         if (WN_operator(size) == OPR_INTCONST && WN_const_val(size) == 0)
04358                 return; // nothing to do
04359 
04360         mstore = WN_CreateMstore(0,
04361                 Make_Pointer_Type(MTYPE_To_TY(WN_rtype(size)),TRUE),
04362                 con,
04363                 WN_LdidPreg(Pointer_type, Stack_Pointer_Preg_Offset),
04364                 WN_COPY_Tree(size) );
04365         mstore = lower_store (block, mstore, actions);
04366         WN_INSERT_BlockLast(block, mstore);
04367 }
04368 
04369 
04370 inline BOOL Should_Call_Divide(TYPE_ID rtype)
04371 {
04372 #if defined(TARG_IA64)
04373   if (!OPT_Inline_Divide) {
04374     if (   rtype == MTYPE_I8 || rtype == MTYPE_U8
04375         || rtype == MTYPE_I4 || rtype == MTYPE_U4
04376         || rtype == MTYPE_F4 || rtype == MTYPE_F8) return TRUE;
04377   }
04378 #elif defined(EMULATE_LONGLONG)
04379   if (rtype == MTYPE_I8 || rtype == MTYPE_U8) return TRUE;
04380 #endif
04381   return FALSE;
04382 }
04383 
04384 static BOOL Is_Fast_Divide(WN *wn)
04385 {
04386   OPERATOR opr = WN_operator(wn);
04387   switch (opr) {
04388   case OPR_DIV:
04389   case OPR_REM:
04390   case OPR_MOD:
04391     {
04392       if (WN_operator_is(WN_kid1(wn), OPR_INTCONST)) {
04393         TYPE_ID rtype = OPCODE_rtype(WN_opcode(wn));
04394         INT64 constval = WN_const_val(WN_kid1(wn));
04395 
04396         return   opr == OPR_DIV
04397                ? Can_Do_Fast_Divide(rtype, constval)
04398                : Can_Do_Fast_Remainder(rtype, constval);
04399       }
04400     }
04401     break;
04402   }
04403 
04404   return FALSE;
04405 }
04406 
04407 
04408 
04409 static WN *lower_parm(WN *block, WN *tree, LOWER_ACTIONS actions){
04410   
04411 
04412   Is_True(Action(LOWER_UPC_TO_INTR) && WN_operator(tree) == OPR_PARM,
04413           ("Incorrect call to lower parm",""));
04414   
04415   WN *kid = WN_kid0(tree);
04416   TY_IDX actual_ty;
04417   TY_IDX formal_ty = WN_ty(tree);
04418   TY_IDX access_ty;
04419   INT field_id;
04420   WN_OFFSET offset;
04421   WN *result;
04422   INTRINSIC iop;
04423 
04424  
04425     
04426   SPTR_ACCUMULATION_STATE saved_acc_state = sptr_accumulation_state;
04427   sptr_accumulation_state = NO_ACCUMULATION;
04428   
04429   field_id = WN_field_id(kid);
04430   offset = WN_offset(kid);
04431   
04432   switch (WN_operator(kid)) {
04433   case OPR_LDID: {
04434     BOOL cvt = FALSE;
04435     INTRINSIC iop;
04436     if(field_id) {
04437       actual_ty = WN_object_ty(kid);
04438       access_ty = WN_ty(kid);
04439     } else
04440       actual_ty = ST_type(WN_st(kid));
04441     
04442     if(Type_Is_Shared_Ptr(formal_ty)) {
04443       if(!Type_Is_Shared_Ptr(actual_ty) || 
04444          ( field_id && !Type_Is_Shared_Ptr(access_ty)) ) {
04445         Is_True(0, ("Local to shared cast in function param!","")); 
04446       } else {
04447         //formal is shared ptr  
04448         kid = lower_expr(block, kid, actions);
04449         if(Need_StoP_Cvt(actual_ty, formal_ty, &iop)) {
04450           kid = WN_Create_StoP_Cvt(kid, iop);   
04451           actual_ty = formal_ty;
04452         }
04453         if(TY_kind(formal_ty) == KIND_SCALAR && TY_kind(actual_ty) == KIND_SCALAR)
04454           result =  WN_CreateParm(TY_mtype(actual_ty), kid, actual_ty, WN_PARM_BY_VALUE);
04455         else
04456           result =  WN_CreateParm(TY_mtype(TY_To_Sptr_Idx(actual_ty)), kid,
04457                                 TY_To_Sptr_Idx(actual_ty), WN_PARM_BY_VALUE);
04458       }
04459     } else {
04460       // formal is not shared 
04461       Is_True(Type_Is_Shared_Ptr(actual_ty) || Type_Is_Shared_Ptr(access_ty),
04462               ("",""));
04463       if(WN_rtype(tree) != MTYPE_M) {
04464         kid = lower_expr(block, kid, actions);
04465         kid = Spill_Shared_Load(kid);
04466         result =   WN_CreateParm(TY_mtype(formal_ty), kid,
04467                                  formal_ty, WN_PARM_BY_VALUE);
04468       } else {
04469         //load of struct
04470       }
04471       
04472     }
04473   }
04474     break;
04475   case OPR_ILOAD:  
04476     actual_ty = WN_ty(kid);
04477     
04478     if (TY_mtype(actual_ty) != MTYPE_M ||  
04479         (field_id && WN_object_ty(kid) != MTYPE_M))
04480       {
04481         INTRINSIC iop;
04482         kid = lower_expr(block, kid, actions); 
04483         if(WN_operator(WN_kid0(tree)) == OPR_TAS)
04484           kid = Strip_TAS(kid);
04485         TY_IDX src = actual_ty;
04486         TY_IDX dest = formal_ty;
04487         
04488         if(field_id) {
04489 
04490         }
04491         
04492         if(Type_Is_Shared_Ptr(actual_ty, TRUE) && Type_Is_Shared_Ptr(formal_ty, TRUE) &&
04493            Need_StoP_Cvt(actual_ty, formal_ty, &iop)) {
04494           kid = WN_Create_StoP_Cvt(kid, iop);   
04495           actual_ty = formal_ty;
04496         }
04497         
04498         if(TY_kind(formal_ty) != KIND_SCALAR && Type_Is_Shared_Ptr(formal_ty)) {
04499           formal_ty = TY_To_Sptr_Idx(formal_ty);
04500         }
04501         result =   WN_CreateParm(TY_mtype(formal_ty), kid,
04502                                  formal_ty, WN_PARM_BY_VALUE);
04503     } else {
04504       access_ty = WN_load_addr_ty(kid);
04505       if (Type_Is_Shared_Ptr(access_ty)) {
04506         WN_kid0(tree) = lower_expr(block, WN_kid0(tree), actions);
04507         if(WN_operator(WN_kid0(tree)) == OPR_TAS)
04508           WN_kid0(tree) = WN_kid0(WN_kid0(tree));
04509         
04510         ST *spill_st = Gen_Temp_Symbol(actual_ty, (char*) ".Mspill");
04511         WN *dest = WN_Lda(Pointer_Mtype, 0, spill_st, 0);
04512         kid  = WN_Create_Shared_Load(kid, dest, TRUE, 0, actual_ty);
04513         WN *blk = WN_CreateBlock();
04514         WN_INSERT_BlockLast(blk, kid);
04515         WN *ld = WN_Ldid(MTYPE_M, 0, spill_st, access_ty);
04516         kid = WN_CreateComma(OPR_COMMA, MTYPE_M, MTYPE_V, blk, ld);
04517         WN_kid0(tree) = kid;
04518         result =  tree;
04519       } else 
04520         Is_True(0,("",""));
04521     }
04522     break;
04523   case OPR_MLOAD:
04524     {
04525       //WEI: for some reason ty is not set here
04526       actual_ty = WN_ty(tree);
04527       access_ty = WN_ty(kid);
04528 
04529       WN_OFFSET offt = WN_offset(WN_kid0(kid));
04530       WN_kid0(kid) = lower_expr(block, WN_kid0(kid), actions);
04531       WN_kid1(kid) = lower_expr(block, WN_kid1(kid), actions);
04532         
04533       ST *spill_st = Gen_Temp_Symbol(actual_ty, (char*) ".Mspill");
04534       WN *dest = WN_Lda(Pointer_Mtype, 0, spill_st, 0);
04535       kid  = WN_Create_Shared_Load(kid, dest, TRUE, offt, actual_ty);
04536       WN *blk = WN_CreateBlock();
04537       WN_INSERT_BlockLast(blk, kid);
04538       //WN *ld = WN_Ldid(MTYPE_M, 0, spill_st, access_ty);
04539       WN *ld = WN_Ldid(MTYPE_M, 0, spill_st, actual_ty);
04540       kid = WN_CreateComma(OPR_COMMA, MTYPE_M, MTYPE_V, blk, ld);
04541       WN_kid0(tree) = kid;
04542       result = tree;
04543     }
04544     break;
04545     
04546   case OPR_TAS: 
04547     {
04548       BOOL cvt = TRUE;
04549       actual_ty = WN_ty(kid);
04550       if (WN_Type_Is_Shared_Ptr(WN_kid0(kid), TRUE) && 
04551           Type_Is_Shared_Ptr(actual_ty, TRUE)) {
04552         // shared to shared is converted by the TAS lowering
04553         cvt = FALSE;
04554       }
04555         
04556       kid = lower_expr(block, kid, actions);
04557       kid = Strip_TAS(kid);
04558       
04559       if (!Type_Is_Shared_Ptr(formal_ty, TRUE)) {
04560         if(Type_Is_Shared_Ptr(actual_ty, TRUE)) {
04561           kid = WN_Convert_Shared_To_Local(kid);
04562         }
04563       } else {
04564         if (cvt && Type_Is_Shared_Ptr(actual_ty, TRUE) && 
04565             Need_StoP_Cvt(actual_ty, formal_ty, &iop))
04566           {
04567             kid = WN_Create_StoP_Cvt(kid, iop);     
04568           }
04569       }
04570       
04571       WN_kid0(tree) = kid;
04572       result = tree;
04573     }
04574     break;
04575   case OPR_LDA:
04576     {
04577       actual_ty = WN_ty(kid);
04578       
04579       if(Type_Is_Shared_Ptr(actual_ty) && Type_Is_Shared_Ptr(formal_ty) &&
04580          Need_StoP_Cvt(actual_ty, formal_ty, &iop)) {
04581         kid = lower_expr(block, kid, actions);
04582         kid =  WN_Create_StoP_Cvt(kid, iop);    
04583       } else 
04584         kid = lower_expr(block, kid, actions);
04585       WN_kid0(tree) = kid;
04586       result = tree;
04587     }
04588     break;
04589   default:
04590     WN_kid0(tree) = lower_expr(block, WN_kid0(tree), actions);
04591     result = tree;
04592   }
04593   
04594   sptr_accumulation_state = saved_acc_state;
04595   return result;
04596 } 
04597 
04598 
04599 
04600 
04601 /* ====================================================================
04602  *
04603  * WN *lower_expr(WN *block, WN *tree, LOWER_ACTIONS actions)
04604  *
04605  * Perform lowering (see WN_Lower description) on expression <tree>,
04606  * returning lowered expression tree.
04607  *
04608  * ==================================================================== */
04609 
04610 static WN *lower_expr(WN *block, WN *tree, LOWER_ACTIONS actions)
04611 {
04612   BOOL kids_lowered = FALSE;    /* becomes TRUE when kids are lowered */
04613   BOOL intrinsic_lowered;
04614 
04615   TYPE_ID type = WN_rtype(tree);
04616 
04617   Is_True(OPCODE_is_expression(WN_opcode(tree)),
04618           ("expected expression node, not %s", OPCODE_name(WN_opcode(tree))));
04619 
04620   if (OPCODE_is_load(WN_opcode(tree)))
04621     lower_map(tree, actions);
04622 
04623  /*
04624   *  before children are processed reassociate for madd oportunities
04625   */
04626   if (Action(LOWER_MADD)        &&
04627       Madd_Allowed              &&
04628      (MTYPE_id(type) == MTYPE_F4 || MTYPE_id(type) == MTYPE_F8))
04629   {
04630     tree = lower_nary_madd(block, tree, actions);
04631     tree = lower_madd(block, tree, actions);
04632   }
04633   if (Action(LOWER_TREEHEIGHT)  &&
04634       WN_is_commutative(tree))
04635   {
04636     if (MTYPE_is_integral(type) || Roundoff_Level >= ROUNDOFF_ASSOC)
04637       tree = lower_tree_height(block, tree, actions);
04638   }
04639 
04640  /* Note: We must split constant offsets after lowering complex exprs
04641   * and splitting symbol addresses since these may create new offsets
04642   * that need to be split.
04643   */
04644   switch (WN_operator(tree)) {
04645 
04646   case OPR_SUB:
04647     {
04648       if(Action(LOWER_UPC_TO_INTR)) {
04649         if(WN_Type_Is_Shared_Ptr(WN_kid0(tree), TRUE) &&  
04650            WN_Type_Is_Shared_Ptr(WN_kid1(tree), TRUE)) {
04651           // shared ptr difference
04652           TY_IDX eltype = WN_ty(WN_kid0(tree));
04653           TY_IDX eltype2 = WN_ty(WN_kid1(tree));
04654           return WN_Create_Shared_Ptr_Diff(lower_expr(block, WN_kid0(tree), actions),
04655                                            lower_expr(block, WN_kid1(tree), actions),
04656                                            eltype,
04657                                            eltype2);
04658         }
04659       }
04660     }
04661     break;
04662   case OPR_PARM:
04663     {
04664       if(Action(LOWER_UPC_TO_INTR)) {
04665         TY_IDX formal_idx = WN_ty(tree);
04666         TY_IDX actual_idx = WN_object_ty(WN_kid0(tree));
04667         if (Type_Is_Shared_Ptr(formal_idx) || 
04668             WN_Type_Is_Shared_Ptr(WN_kid0(tree)) ||
04669             (WN_operator(WN_kid0(tree)) == OPR_ILOAD && 
04670              Type_Is_Shared_Ptr(WN_load_addr_ty(WN_kid0(tree))))) {
04671           
04672           return  lower_parm(block, tree, actions);
04673          
04674           // fdump_tree(stderr, WN_kid0(tree));
04675            
04676 //        if(Type_Is_Shared_Ptr(formal_idx))
04677 //          tree = WN_CreateParm(TY_mtype(shared_ptr_idx), WN_COPY_Tree(WN_kid0(tree)),
04678 //                               shared_ptr_idx, WN_PARM_BY_VALUE);
04679 //        else {
04680 //          if (TY_kind(formal_idx) == KIND_POINTER)
04681 //            tree =  WN_CreateParm(TY_mtype(shared_ptr_idx), 
04682 //                                  WN_Convert_Shared_To_Local(WN_kid0(tree), 
04683 //                                                             WN_ty(tree), 0),
04684 //                                  shared_ptr_idx, WN_PARM_BY_VALUE);
04685 //          else {
04686 //            Is_True(TY_mtype(actual_idx) != MTYPE_M, ("",""));
04687 //            tree = WN_CreateParm(TY_mtype(shared_ptr_idx), 
04688 //                                 Spill_Shared_Load(WN_kid0(tree)),
04689 //                                  shared_ptr_idx, WN_PARM_BY_VALUE);
04690 //          }
04691 //        }
04692 //        fdump_tree(stderr, tree);
04693 //        return tree;
04694         } else if (WN_operator(WN_kid0(tree)) == OPR_ADD) {
04695           //WEI: a special case for when exprs like foo->x[i] is passed to a function,
04696           //and we need to adjust the field offset
04697           WN* kid = WN_kid0(tree);
04698           WN* offset = WN_kid1(kid);
04699           if (WN_operator(offset) == OPR_INTCONST) {
04700             TY_IDX obj_ty = struct_addr_ty(WN_kid0(kid));
04701             if (obj_ty != 0) {
04702               int field_id = find_field_from_offset(obj_ty, WN_const_val(offset));
04703               int real_ofst =  Adjust_Field_Offset(obj_ty, field_id);
04704               WN_kid1(kid) = WN_CreateIntconst(OPR_INTCONST, Pointer_Mtype, MTYPE_V, real_ofst); 
04705               //cout << "PARM OFFSET: " << real_ofst << endl;
04706             }
04707           }
04708         }
04709       }
04710     }
04711     break; /* PARM */
04712     
04713   case OPR_INTRINSIC_OP:
04714     //FIX:
04715     if (WN_intrinsic(tree) == INTRN_TLD_ADDR) {
04716       //prevent the lowering of TLD_ADDR from happening twice
04717       kids_lowered = TRUE;
04718     }
04719     
04720     if (INTRN_is_nary(WN_intrinsic(tree)))
04721       break;
04722 
04723     if (INTRN_cg_intrinsic(WN_intrinsic(tree)))
04724       break;
04725 
04726     if (INTRN_is_actual(WN_intrinsic(tree)))
04727     {
04728       if (Action(LOWER_INTRINSIC))
04729       {
04730         tree = lower_intrinsic(block, tree, actions);
04731         kids_lowered = TRUE;
04732       }
04733       break;
04734     }
04735     if (Action(LOWER_INTRINSIC) ||
04736         Action(LOWER_INLINE_INTRINSIC) ||
04737         Action(LOWER_INL_STACK_INTRINSIC))
04738     {
04739       tree = lower_emulation(block, tree, actions, intrinsic_lowered);
04740       kids_lowered = TRUE;
04741     }
04742     break;
04743 
04744   case OPR_ARRAY:
04745     if (Action(LOWER_ARRAY))
04746     {
04747       
04748       tree = lower_linearize_array_addr(block, tree, actions);
04749       kids_lowered = TRUE;
04750     
04751     }
04752     break;
04753 
04754   case OPR_ADD:
04755     if (Action(LOWER_SPLIT_CONST_OFFSETS))
04756     {
04757      /*
04758       * Split
04759       *       LDA   (c1) <sym>
04760       *       CONST (c2)
04761       *     ADD
04762       * Into
04763       *       LDA   (hi) <sym>
04764       *       CONST (low)
04765       *     ADD
04766       */
04767       WN *lda = WN_kid0(tree);
04768       WN *con = WN_kid1(tree);
04769 
04770       if (WN_operator_is(con, OPR_INTCONST) &&
04771           foldLdaOffset(lda, WN_const_val(con)))
04772       {
04773         WN_OFFSET  offset = WN_lda_offset(lda) + WN_const_val(con);
04774 
04775         if (mem_offset_must_be_split(offset))
04776         {
04777           WN_lda_offset(lda) = mem_offset_hi(offset);
04778           WN_const_val(con) =  mem_offset_lo(offset);
04779         }
04780       }
04781     }
04782     else
04783     {
04784      /*
04785       * Fold
04786       *       LDA   (c1) <sym>
04787       *       CONST (c2)
04788       *     ADD
04789       * Into
04790       *     LDA (c1+c2) <sym>
04791       */
04792       WN *lda = WN_kid0(tree);
04793       WN *con = WN_kid1(tree);
04794 
04795       if (Action(LOWER_UPC_TO_INTR)) {
04796       
04797         TY_IDX idx_ptr, idx_off;
04798         idx_ptr = WN_ty(lda);
04799         idx_off = WN_ty(con);
04800         int esize = 0;
04801         int bsize = 0;
04802         WN *ptr, *off;
04803         BOOL ptr_ptr = FALSE;
04804 
04805 
04806 
04807 //      fprintf(stderr, "++++++++++++++++++++++++++\n");
04808 //      fprintf(stderr, "ADD kid0\n");
04809 //      fdump_tree(stderr, WN_kid0(tree));
04810 //      fprintf(stderr, "ADD kid1\n");
04811 //      fdump_tree(stderr, WN_kid1(tree));
04812 //      fprintf(stderr, "++++++++++++++++++++++++++\n");
04813         
04814         
04815         if (WN_operator(lda) == OPR_CONST) {
04816           idx_ptr = 0;
04817         }  else if(OPERATOR_is_load(WN_operator(lda)) && WN_field_id(lda)) {
04818           idx_ptr = Get_Field_Type(WN_ty(lda), WN_field_id(lda));
04819         }
04820  
04821         if (WN_operator(con) == OPR_CONST) {
04822           idx_off = 0;
04823         } else if(OPERATOR_is_load(WN_operator(con)) && WN_field_id(con)) {
04824             idx_off = Get_Field_Type(WN_ty(con), WN_field_id(con));
04825         } 
04826 
04827         /* if idx_ptr == idx_off == 0, i.e. we should have a regular
04828            scalar add. However, the optimizer folds cts to right hand side
04829            of the tree. While doing this it loses type information.
04830            Ex: compile  a[j+100][i+100]
04831            Try recapture that info here. The right way would be of course to fix
04832            the optimizer (This happens after a call to SSA::Create_CODEMAP -> Value_number) */
04833 
04834         if (!idx_ptr && !idx_off) {
04835           TY_IDX op_ty;
04836           
04837 
04838           if (WN_operator(lda) == OPR_ADD) {
04839             op_ty = WN_ty(WN_kid0(lda));
04840             if(Type_Is_Shared_Ptr(op_ty) && TY_kind(op_ty) != KIND_SCALAR)
04841               idx_ptr = op_ty;
04842             op_ty = WN_ty(WN_kid1(lda));
04843             if(Type_Is_Shared_Ptr(op_ty) && TY_kind(op_ty) != KIND_SCALAR)
04844               idx_ptr = op_ty;
04845           }
04846           else if (WN_operator(con) == OPR_ADD) {
04847             op_ty = WN_ty(WN_kid0(con));
04848             if(Type_Is_Shared_Ptr(op_ty) && TY_kind(op_ty) != KIND_SCALAR)
04849               idx_off = op_ty;
04850             op_ty = WN_ty(WN_kid1(con));
04851             if(Type_Is_Shared_Ptr(op_ty) && TY_kind(op_ty) != KIND_SCALAR)
04852               idx_off = op_ty;
04853           } 
04854         }
04855         
04856 
04857         /* lower shared ptr arithmetic - check for the base case where 
04858            one of the operands is shared */
04859         /* apparently when ptr = LDA, the operand is a pointer to the shared ptr.
04860            elem size is given by TY_size(TY_pointed(TY_etype/pointed ())) */
04861         if (idx_ptr || idx_off  ) {
04862           
04863           ptr = lda;
04864           off = con;
04865 
04866           if ( TY_kind(idx_ptr) == KIND_POINTER && TY_is_shared(TY_pointed(idx_ptr)) ) {
04867             idx_off = TY_pointed(idx_ptr);
04868             esize = Get_Type_Inner_Size(idx_off);
04869             bsize = Get_Type_Block_Size(idx_off);
04870           } else if ( TY_kind(idx_off) == KIND_POINTER && TY_is_shared(TY_pointed(idx_off)) ) {
04871             ptr = con;
04872             off = lda;
04873             idx_ptr = idx_off;
04874             idx_off = TY_pointed(idx_off);
04875             esize = Get_Type_Inner_Size(idx_off);
04876             bsize = Get_Type_Block_Size(idx_off);
04877           } else if ( TY_kind(idx_ptr) == KIND_ARRAY && TY_is_shared(TY_etype(idx_ptr)) ) {
04878             Is_True(0,("",""));
04879             esize = TY_size(TY_etype(idx_ptr));
04880             bsize = TY_block_size(TY_etype(idx_ptr));
04881           } else if ( TY_kind(idx_off) == KIND_ARRAY && TY_is_shared(TY_etype(idx_off)) ) {
04882             Is_True(0,("",""));
04883             ptr = con;
04884             off = lda;
04885             esize = TY_size(TY_etype (idx_off));
04886             bsize = TY_block_size(TY_etype(idx_off));
04887           } else {
04888             
04889             ptr_ptr = TRUE; 
04890           }       
04891 
04892          //  int offset = WN_offset(ptr);
04893          
04894 //        ptr = lower_expr(block, ptr, actions);
04895 //        off = lower_expr(block, off, actions);
04896           
04897 //        if(sptr_accumulation_state == ACCUMULATION) {
04898 //          if(!ptr_ptr) {
04899 //            if(offset) {
04900 //              sptr_off_accumulation_stack.top()->push(WN_Intconst(Integer_type, offset));
04901 //              //WN_offset(ptr) = 0;
04902 //            }
04903 //          }
04904 //        }
04905           
04906           if(sptr_accumulation_state == ACCUMULATION) {
04907             if(!ptr_ptr) {
04908               if(WN_offset(ptr)) {
04909                 if(OPERATOR_is_load(WN_operator(ptr)) && WN_field_id(ptr) && 
04910                    Type_Is_Shared_Ptr(WN_ty(ptr)))
04911                   ;
04912                 else
04913                   sptr_off_accumulation_stack.top()->push(WN_Intconst(Integer_type, WN_offset(ptr)));
04914                 WN_offset(ptr) = 0;
04915               }
04916             }
04917           }
04918 
04919           ptr = lower_expr(block, ptr, actions);
04920           off = lower_expr(block, off, actions);
04921           
04922           
04923 
04924           if(ptr_ptr) {
04925             //talentless hack
04926             // this is for multidimensional array indexing expressions
04927             if (WN_operator(ptr) == OPR_COMMA && 
04928                 (WN_ty(WN_kid1(ptr)) == shared_ptr_idx || WN_ty(WN_kid1(ptr)) == pshared_ptr_idx))
04929               goto do_arith;
04930             else if (WN_operator(off) == OPR_COMMA && 
04931                      (WN_ty(WN_kid1(off)) == shared_ptr_idx || WN_ty(WN_kid1(off)) == pshared_ptr_idx)){
04932               lda = ptr;
04933               ptr = off;
04934               off = lda;
04935               goto do_arith;
04936             }   
04937             
04938             WN_kid0(tree) = ptr;
04939             WN_kid1(tree) = off;
04940             return tree;
04941           }
04942 
04943 do_arith:
04944           
04945           if (sptr_accumulation_state == NO_ACCUMULATION) {
04946             // here idx_ptr should hold the pointer type
04947             Is_True(TY_kind(idx_ptr) == KIND_POINTER && Type_Is_Shared_Ptr(idx_ptr) // ||
04948 //                  TY_kind(idx_off) == KIND_POINTER && Type_Is_Shared_Ptr(idx_off)
04949                     , ("",""));
04950             if(Type_Is_Shared_Ptr(TY_pointed(idx_ptr)))
04951                ptr  = WN_Create_Shared_Ptr_Arithmetic (ptr, off, OPR_ADD,  esize, bsize);
04952             else {
04953               WN_kid0(tree) = ptr;
04954               WN_kid1(tree) = off;
04955               return tree;
04956             }
04957           } else {
04958             sptr_off_accumulation_stack.top()->push(off);
04959           }
04960           WN_Delete (tree);
04961 
04962           tree = ptr;
04963           kids_lowered = TRUE;
04964           // fdump_tree(stderr, tree);
04965         }
04966       } 
04967       
04968 no_shared:
04969       if (WN_operator_is(con, OPR_INTCONST) &&
04970           foldLdaOffset(lda, WN_const_val(con)))
04971       {
04972         WN_lda_offset(lda) += WN_const_val(con);
04973         WN_Delete(tree);
04974         WN_Delete(con);
04975         tree = lower_expr(block, lda, actions);;
04976       }
04977     }
04978     break;
04979 
04980   case OPR_MLOAD:  
04981     if (Action(LOWER_UPC_TO_INTR)) {
04982       TY_IDX idx = WN_ty(tree);
04983       WN *ild;
04984       if (Type_Is_Shared_Ptr(idx)) {
04985         SPTR_ACCUMULATION_STATE saved_acc_state = sptr_accumulation_state;
04986         sptr_accumulation_state = ACCUMULATION;
04987         sptr_off_accumulation_stack.push(CXX_NEW(SPTR_OFFSET_TERM_STACK, Malloc_Mem_Pool));
04988         SPTR_OFFSET_TERM_STACK *term_stack = sptr_off_accumulation_stack.top();
04989         if(WN_offset(tree)) {
04990           term_stack->push(WN_Intconst(Integer_type, WN_offset(tree)));
04991           WN_offset(tree) = 0;                     
04992         }
04993                 
04994         WN_kid0(tree) = lower_expr(block, WN_kid0(tree), actions);
04995         WN_kid1(tree) = lower_expr(block, WN_kid1(tree), actions);
04996 
04997         if(WN_operator(WN_kid0(tree)) == OPR_TAS)
04998           WN_kid0(tree) = Strip_TAS(WN_kid0(tree));
04999         
05000         ild = Combine_Offset_Terms(*term_stack);
05001 //      if(ild)
05002 //        fdump_tree(stderr, ild);
05003         
05004         sptr_accumulation_state = saved_acc_state;
05005         sptr_off_accumulation_stack.pop();
05006         CXX_DELETE(term_stack, Malloc_Mem_Pool);
05007         //need to reset the offset of the ld;
05008 //      WN_kid0(tree)  = WN_Create_Shared_Ptr_Arithmetic (WN_kid0(tree), ild, OPR_ADD,
05009 //                                                        Get_Type_Inner_Size(idx),
05010 //                                                        Get_Type_Block_Size(idx),
05011 //                                                        Get_Type_Block_Size(idx) <= 1);
05012         return WN_Create_Shared_Load(tree, 0, FALSE, 0, 0,/*has off*/  TRUE, ild);
05013       }
05014     } else
05015       if (Align_Object)
05016         {
05017           WN_kid0(tree)=        lower_expr(block, WN_kid0(tree), actions);
05018          //  fdump_tree(stderr, WN_kid0(tree));
05019           kids_lowered =        TRUE;
05020           if(Action(LOWER_UPC_MFIELD) && 
05021              WN_operator(WN_kid1(tree)) == OPR_INTCONST) {
05022             WN_const_val(WN_kid1(tree)) = 
05023               Adjusted_Type_Size(WN_field_id(tree) == 0 ? TY_pointed(WN_ty(tree)) : Get_Field_Type(TY_pointed(WN_ty(tree)), WN_field_id(tree)));
05024           }
05025           tree = improve_Malignment(tree, WN_kid0(tree), WN_kid1(tree),
05026                                     WN_load_offset(tree));
05027           break;
05028         }  /* fall thru */
05029 
05030   case OPR_ILOAD:
05031     if (Action(LOWER_MLDID_MSTID) && WN_opcode(tree) == OPC_MMILOAD)
05032       return lower_miload(block, tree, actions);
05033 
05034     if (Action(LOWER_BIT_FIELD_ID) && WN_desc(tree) == MTYPE_BS) {
05035       lower_bit_field_id(tree);
05036       if (Action(LOWER_BITS_OP) && WN_operator(tree) == OPR_ILDBITS)
05037         return lower_load_bits (block, tree, actions);
05038     }
05039 
05040     if (Action(LOWER_SPLIT_CONST_OFFSETS))
05041     {
05042      /*
05043       * Convert
05044       *      EXPR
05045       *    ILOAD (offset>16bits)
05046       * Into
05047       *        CONST (hi)
05048       *        EXPR
05049       *      ADD
05050       *    ILOAD (lo)
05051       */
05052       WN_OFFSET  offset = WN_load_offset(tree);
05053       if (mem_offset_must_be_split(offset))
05054       {
05055         WN_kid0(tree) =  WN_Add(Pointer_type,
05056                                 WN_kid0(tree),
05057                                 WN_Intconst(Pointer_type,
05058                                             mem_offset_hi(offset)));
05059         WN_load_offset(tree) = mem_offset_lo(offset);
05060       }
05061     }
05062     else
05063     {
05064      /*
05065       * Fold
05066       *       LDA (c1) <sym>
05067       *     ILOAD (c2)
05068       * Into
05069       *       LDA (0)  <sym>
05070       *     ILOAD (c1+c2)
05071       */
05072       WN *kid = WN_kid0(tree);
05073 
05074       if (foldLdaOffset(kid, WN_load_offset(tree)))
05075       {
05076         WN_load_offset(tree) += WN_lda_offset(kid);
05077         WN_lda_offset(kid) = 0;
05078       }
05079      /*
05080       * Fold
05081       *           EXPR 
05082       *           CONST (c1)
05083       *       ADD expr
05084       *     ILOAD (c1)
05085       * Into
05086       *       EXPR
05087       *     ILOAD (c1+c2)
05088       */
05089       else if (WN_operator_is(kid, OPR_ADD) &&
05090                foldConstOffset(WN_kid1(kid), WN_load_offset(tree)))
05091       {
05092         WN_load_offset(tree) += WN_const_val(WN_kid1(kid));
05093         WN_kid0(tree) = WN_kid0(kid);
05094         //WEI: again, need to adjust field sizes here
05095         TY_IDX obj_ty = struct_addr_ty(WN_kid0(tree));
05096         if (obj_ty != 0) {
05097           //WEI: let's fix the offset here
05098           int field_id = find_field_from_offset(obj_ty, WN_load_offset(tree));
05099           WN_store_offset(tree) = Adjust_Field_Offset(obj_ty, field_id);
05100           //cout << "LOAD OFFSET: " <<  WN_load_offset(tree) << endl;
05101         }       
05102 
05103         WN_Delete(WN_kid1(kid));
05104         WN_Delete(kid);
05105       }
05106     }
05107 
05108     if(Action(LOWER_UPC_TO_INTR) ) {
05109       TY_IDX idx = WN_ty(tree);
05110       WN *ild = 0;
05111       BOOL has_off = TRUE;
05112       BOOL local_off = FALSE;
05113       WN *offt = 0;
05114       TY_IDX src_idx;
05115       if (Type_Is_Shared_Ptr(WN_load_addr_ty(tree))) {
05116         TY_IDX ptr_idx = WN_load_addr_ty(tree);
05117         Is_True(TY_kind(ptr_idx) == KIND_POINTER, ("",""));
05118         
05119         SPTR_ACCUMULATION_STATE saved_acc_state = sptr_accumulation_state;
05120         sptr_accumulation_state = ACCUMULATION;
05121         sptr_off_accumulation_stack.push(CXX_NEW(SPTR_OFFSET_TERM_STACK, Malloc_Mem_Pool));
05122         SPTR_OFFSET_TERM_STACK *term_stack = sptr_off_accumulation_stack.top();
05123         
05124         WN *kid0 = WN_kid0(tree);
05125 
05126         if((WN_operator(kid0) == OPR_LDID && !WN_offset(tree)) ||
05127            WN_operator(kid0) == OPR_ARRAY ||
05128            // the optimizer creates LDA(off, array) and the pointer arith
05129            // is performed when lowering the LDA
05130           ( WN_operator(kid0) == OPR_TAS && WN_operator(WN_kid0(kid0)) == OPR_LDA &&
05131             TY_kind(TY_pointed(WN_ty(WN_kid0(kid0)))) == KIND_ARRAY) )
05132           has_off = FALSE;
05133         
05134         if(WN_offset(tree) || WN_field_id(tree)) {
05135           // term_stack->push(WN_Intconst(Integer_type, WN_offset(tree)));
05136           offt = WN_Intconst(Integer_type,  WN_field_id(tree) > 1 ? Adjust_Field_Offset(WN_ty(tree), WN_field_id(tree)) : WN_offset(tree));
05137           WN_offset(tree) = 0;
05138           local_off = TRUE;
05139         }
05140         
05141         if(WN_operator(WN_kid0(tree)) == OPR_TAS)  
05142           WN_set_load_addr_ty(tree, WN_ty(WN_kid0(tree)));
05143 
05144   
05145         switch (WN_operator(WN_kid0(tree))) {
05146         case OPR_LDID:
05147            idx = ST_type(WN_st(WN_kid0(tree)));
05148            break;
05149         case OPR_TAS:
05150           idx = WN_ty(WN_kid0(tree));
05151           break;
05152         default:
05153           break;
05154         }
05155                     
05156         WN_kid0(tree) = lower_expr(block, WN_kid0(tree), actions);
05157 
05158         if(WN_operator(WN_kid0(tree)) == OPR_TAS) { 
05159           src_idx = WN_ty(WN_kid0(tree));
05160           WN_kid0(tree) = Strip_TAS(WN_kid0(tree));
05161         } else
05162           src_idx = idx;
05163         
05164         if(has_off) {
05165          
05166           ild = Combine_Offset_Terms(*term_stack);
05167           //    if(ild)
05168           //      fdump_tree(stderr, ild);
05169 
05170           //don't even ask why
05171           if(( TY_kind(idx) == KIND_POINTER && TY_kind(TY_pointed(idx)) != KIND_STRUCT)
05172              ||
05173              ( TY_kind(idx) == KIND_POINTER && TY_kind(TY_pointed(idx)) == KIND_STRUCT && ild)
05174              ||
05175              (TY_kind(idx) == KIND_ARRAY && TY_kind(Get_Inner_Array_Type(idx)) != KIND_STRUCT)
05176              ||
05177              (TY_kind(idx) == KIND_ARRAY && TY_kind(Get_Inner_Array_Type(idx)) == KIND_STRUCT && ild)
05178              ) {
05179             if (TY_kind(src_idx) == KIND_POINTER && 
05180                 (WN_operator(WN_kid0(tree)) == OPR_LDID &&
05181                  Types_Are_Equiv(/*TY_pointed(src_idx)*/src_idx, ST_type(WN_st(WN_kid0(tree))))
05182                  || !local_off)) {
05183               UINT esize = Get_Type_Inner_Size(idx);
05184               if(TY_kind(idx) == KIND_POINTER && TY_is_shared(TY_pointed(idx)) && 
05185                  TY_kind(TY_pointed(idx)) == KIND_POINTER)
05186                 esize = TY_size(TY_To_Sptr_Idx(idx));
05187               if(ild)
05188               WN_kid0(tree)  = WN_Create_Shared_Ptr_Arithmetic (WN_kid0(tree), ild, OPR_ADD,
05189                                                                 esize,
05190                                                                 Get_Type_Block_Size(idx),
05191                                                                 Get_Type_Block_Size(idx) <= 1);
05192               if(offt) 
05193                 ild = offt;
05194               else
05195                 has_off = FALSE;
05196             }       
05197           }
05198           
05199           if(!ild && offt)
05200             ild = offt;
05201           else if(!ild)
05202             has_off = FALSE;
05203         }
05204         
05205         sptr_accumulation_state = saved_acc_state;
05206         sptr_off_accumulation_stack.pop();
05207         CXX_DELETE(term_stack, Malloc_Mem_Pool);
05208         return WN_Create_Shared_Load(tree, 0, FALSE, 0, 0, has_off, ild);
05209       } else  if(TY_kind(idx) == KIND_STRUCT && !TY_is_shared(idx) && 
05210                  Type_Is_Shared_Ptr(TY_pointed(WN_load_addr_ty(tree)), TRUE)) {
05211         //this is the case where we load a field of a local struct, the type of
05212         //of the field being a sptr
05213         // Ty_Table[WN_ty(tree)].Print(stderr);
05214 //      Ty_Table[WN_load_addr_ty(tree)].Print(stderr);
05215 //      fdump_tree(stderr, tree);
05216         idx = TY_To_Sptr_Idx(TY_pointed(WN_load_addr_ty(tree)));
05217         if(TY_mtype(idx) == MTYPE_M) {
05218           WN_set_rtype(tree, MTYPE_M);
05219           WN_set_desc(tree, MTYPE_M);
05220           WN_set_load_addr_ty(tree,  Make_Pointer_Type(idx));
05221           WN_load_offset(tree) = Adjust_Field_Offset(WN_ty(tree),WN_field_id(tree));
05222           // Ty_Table[WN_ty(tree)].Print(stderr);
05223 //        Ty_Table[WN_load_addr_ty(tree)].Print(stderr);
05224 //        fdump_tree(stderr, tree);
05225           return tree;                  
05226         }            
05227       } else if(Type_Is_Shared_Ptr(WN_ty(tree), TRUE)) {
05228         idx = TY_To_Sptr_Idx(WN_ty(tree));
05229         WN_set_rtype(tree, TY_mtype(idx));
05230         WN_set_desc(tree,TY_mtype(idx)); 
05231       } else  if(WN_field_id(tree) > 1)
05232         WN_load_offset(tree) = Adjust_Field_Offset(TY_kind(WN_ty(tree)) == KIND_STRUCT ? WN_ty(tree) :TY_pointed(WN_ty(tree)),WN_field_id(tree));
05233     }
05234     break; /* ILOAD */
05235 
05236   case OPR_LDID: {
05237    //  WN* res = lower_TLD(block, tree, actions);
05238 //     if (res != tree) {
05239 //       return res;
05240 //     }
05241 
05242     if (Action(LOWER_RETURN_VAL) && WN_st(tree) == Return_Val_Preg)
05243       return lower_return_ldid(block, tree, actions);
05244     
05245     if (Action(LOWER_MLDID_MSTID) && WN_opcode(tree) == OPC_MMLDID)
05246       return lower_mldid(block, tree, actions);
05247     
05248     if (Action(LOWER_BIT_FIELD_ID) && WN_desc(tree) == MTYPE_BS) {
05249       lower_bit_field_id(tree);
05250       if (Action(LOWER_BITS_OP) && WN_operator(tree) == OPR_LDBITS)
05251         return lower_load_bits (block, tree, actions);
05252     }
05253 
05254     if(Action(LOWER_UPC_TO_INTR) ) {
05255       WN *ical;
05256       TY_IDX idx, src_idx;
05257       if ( TY_is_shared(ST_type(WN_st(tree)))) { //shared scalar
05258         ical = WN_Create_Shared_Load(tree);
05259       } else if (TY_kind(ST_type(WN_st(tree))) == KIND_POINTER && 
05260                  TY_is_shared(TY_pointed(ST_type(WN_st(tree)))) ) {
05261         // local ptr to shared
05262         // change the descriptors to LDID
05263         ical = WN_COPY_Tree(tree);
05264         idx = TY_To_Sptr_Idx(ST_type(WN_st(tree)));
05265         WN_set_rtype(ical, TY_mtype(idx));
05266         WN_set_desc (ical, TY_mtype(idx));
05267         WN_set_ty(ical, idx);
05268       } else {
05269         idx = WN_field_id(tree) ? get_field_type(WN_ty(tree), WN_field_id(tree)) : WN_ty(tree);
05270         if(WN_field_id(tree) && Type_Is_Shared_Ptr(idx, TRUE)) {
05271           ical = WN_COPY_Tree(tree);
05272           src_idx = TY_To_Sptr_Idx(idx);
05273           WN_set_rtype(ical, TY_mtype(src_idx));
05274           WN_set_desc (ical, TY_mtype(src_idx));
05275          //  WN_set_ty(ical, src_idx);
05276           WN_load_offset(ical) = Adjust_Field_Offset(WN_ty(tree) , WN_field_id(tree));
05277         } else if(WN_field_id(tree) > 1) { 
05278           WN_load_offset(tree) = Adjust_Field_Offset(WN_ty(tree) , WN_field_id(tree));
05279           goto skip;
05280         } else
05281           goto skip;
05282       }
05283       return ical;
05284     }
05285   skip:
05286     if ((WN_class(tree) == CLASS_CONST) && (WN_load_offset(tree) == 0))
05287     {
05288       TCON      val = WN_val(tree);
05289       TYPE_ID   valType = WN_val_type(tree);
05290       WN        *con;
05291 
05292       if (MTYPE_is_integral(type) && MTYPE_is_integral(valType))
05293       {
05294         con = WN_Intconst(type, Targ_To_Host( val));
05295         WN_Delete(tree);
05296         return con;
05297       }
05298      /*
05299       *  check for real (complex constant) conversion not handled by Targ_Conv
05300       */
05301       else if ((MTYPE_is_float(type) && MTYPE_is_float(valType))        &&
05302               !(!MTYPE_is_complex(type) && MTYPE_is_complex(valType)))
05303       {
05304         if (type != valType)
05305         {
05306           val = Targ_Conv(type, val);
05307         }
05308         con =   Make_Const(val);
05309         WN_Delete(tree);
05310         return con;
05311       }
05312     }
05313     {
05314       PREG_NUM last_preg = Get_Preg_Num(PREG_Table_Size(CURRENT_SYMTAB));
05315       if ((WN_class(tree) == CLASS_PREG) &&
05316           (WN_load_offset(tree) > last_preg))
05317       {
05318           DevWarn("lower_expr() pregno %d > SYMTAB_last_preg(%d)",
05319                   WN_load_offset(tree), last_preg);
05320       }
05321     }
05322    /*
05323     * Exposes the LDA for RVI usage
05324     */
05325     if (Action(LOWER_SPLIT_SYM_ADDRS))
05326     {
05327       WN        *iload;
05328       iload = lower_split_sym_addrs(tree, WN_load_offset(tree), actions);
05329       if (iload)
05330       {
05331         return lower_expr(block, iload, actions);
05332       }
05333     }
05334     if ( Action(LOWER_FORMAL_REF) && WN_class(tree) == CLASS_VAR)
05335     {
05336       WN           *iload;
05337 
05338       iload = lower_formal_ref(tree, WN_load_offset(tree),
05339                                WN_st(tree), actions);
05340       if (iload)
05341       {
05342         return lower_expr(block, iload, actions);
05343       }
05344     }
05345     if ( Action(LOWER_UPLEVEL))
05346       {
05347         ST *sym = WN_st(tree);
05348         
05349         if (ST_is_uplevelTemp(sym))
05350           {
05351             WN     *iload;
05352             
05353             iload = lower_uplevel_reference(tree, WN_load_offset(tree), actions);
05354             tree = lower_expr(block, iload, actions);
05355             return tree;
05356           }
05357       }
05358     break;
05359   }
05360   case OPR_ILDBITS:
05361   case OPR_LDBITS:
05362     if (Action(LOWER_BITS_OP))
05363       return lower_load_bits (block, tree, actions);
05364     break;
05365     
05366   case OPR_LDA:
05367    /* 
05368     *  use of LDA should mark STFL_ADDR_USED_LOCALLY
05369     */ 
05370     {
05371       // WN* res = lower_TLD_lda(block, tree, actions);
05372 //       if (res != tree) {
05373 //      tree = res;
05374 //      kids_lowered = true;
05375 //      break;
05376 //       }
05377       
05378       
05379       ST *sym = WN_st(tree); 
05380  
05381       // if ((ST_class(sym) == CLASS_VAR) ||
05382       //     (ST_class(sym) == CLASS_FUNC)) {
05383       //   Do nothing here. ADDR flags should only grow more
05384       //   optimistic; they should never become more conservative,
05385       //   because the program's semantics cannot grow worse as we
05386       //   compile it.
05387       // }
05388 
05389       if (ST_class(sym) == CLASS_BLOCK && STB_merge(sym))
05390       {
05391         DevWarn("LDA (%s) potential bad exposed use of a mergeable symbol",
05392                 ST_name(sym));
05393       }
05394     }
05395     if (Action(LOWER_SPLIT_SYM_ADDRS))
05396     {
05397       WN  *lda;
05398       lda =     lower_split_sym_addrs(tree, WN_lda_offset(tree), actions);
05399       if (lda)
05400       {
05401         return lower_expr(block, lda, actions);
05402       }
05403     }
05404     if ( Action(LOWER_FORMAL_REF) && WN_class(tree) == CLASS_VAR)
05405     {
05406       WN           *ldid;
05407 
05408       ldid =    lower_formal_ref(tree, WN_lda_offset(tree), WN_st(tree),
05409                                  actions);
05410       if (ldid)
05411       {
05412         return lower_expr(block, ldid, actions);
05413       }
05414     }
05415     if ( Action(LOWER_UPLEVEL))
05416     {
05417       ST *sym = WN_st(tree);
05418 
05419       if (ST_is_uplevelTemp(sym))
05420       {
05421         WN         *ldid;
05422 
05423         ldid = lower_uplevel_reference(tree, WN_lda_offset(tree), actions);
05424         tree = lower_expr(block, ldid, actions);
05425         return tree;
05426       }
05427     }
05428 
05429     if ( Action(LOWER_UPC_TO_INTR) ) {
05430       TY_IDX tidx = WN_ty(tree);
05431       
05432       if ( (TY_kind(tidx) == KIND_POINTER && TY_is_shared(TY_pointed(tidx))) ||
05433            (TY_kind(tidx) == KIND_ARRAY && TY_is_shared(TY_etype(tidx))) ){
05434         WN *ld; 
05435         TY_IDX idx1 = TY_To_Sptr_Idx(TY_pointed(tidx));
05436         ld  = WN_Ldid(TY_mtype(idx1), 0, WN_st(tree), idx1);
05437         if (WN_offset(tree) && TY_kind(TY_pointed(tidx))  != KIND_STRUCT)
05438         {
05439           
05440           ld = WN_Create_Shared_Ptr_Arithmetic(ld, 
05441                                                WN_Intconst(Integer_type,
05442                                                            WN_offset(tree)),
05443                                                OPR_ADD,
05444                                                Get_Type_Inner_Size(tidx),
05445                                                Get_Type_Block_Size(tidx)); 
05446         } 
05447         return ld;
05448       } else {
05449         tidx = TY_pointed(tidx);
05450         if(WN_offset(tree) && TY_kind(tidx) == KIND_STRUCT) {
05451           WN_load_offset(tree) = 0;
05452         }
05453         
05454       }
05455     }
05456     
05457     break;
05458 
05459   case OPR_CVT:
05460   case OPR_TRUNC:
05461   case OPR_RND:
05462     if (Action(LOWER_CVT))
05463     {
05464       tree = lower_cvt(block, tree, actions);
05465       kids_lowered = TRUE;
05466     } else if(Action(LOWER_UPC_TO_INTR)) {
05467       TY_IDX ty_idx = 0;
05468       switch (WN_operator(WN_kid0(tree))) {
05469       case OPR_LDID:
05470       case OPR_TAS:
05471         ty_idx = WN_ty(WN_kid0(tree));
05472         break;
05473       case OPR_COMMA:
05474       
05475       default:
05476 //      Is_True(0,("",""));
05477         break;
05478       }
05479       if(Type_Is_Shared_Ptr(ty_idx, TRUE)) 
05480         return WN_Convert_Shared_To_Local(lower_expr(block, WN_kid0(tree), actions));
05481     }
05482     break;
05483 
05484   case OPR_TAS:
05485 
05486     /* If the operand of the TAS is a load from memory, try to
05487      * replace with a load matching the result type of the TAS.
05488      * Doing so may avoid a move from one register set to another.
05489      */
05490     if (Action(LOWER_TO_CG))
05491     {
05492       WN *load = WN_kid0(tree);
05493       if (   OPERATOR_is_load(WN_operator(load))
05494           && (!WN_has_sym(load) || WN_class(load) != CLASS_PREG))
05495       {
05496         TYPE_ID tas_rtype = WN_rtype(tree);
05497         if (MTYPE_byte_size(tas_rtype) == MTYPE_byte_size(WN_desc(load))) {
05498           WN_set_rtype(load, tas_rtype);
05499           WN_set_desc(load, tas_rtype);
05500           WN_Delete(tree);
05501           return lower_expr(block, load, actions);
05502         }
05503       }
05504     }
05505     
05506     // for TAS of shared ptr - need to do the lowering here.
05507     //Otherwise the regular code calls the whirl simplifyer that
05508     //deletes TAS when rtypes match.
05509     if (WN_Type_Is_Shared_Ptr(tree)) {
05510       if(Action(LOWER_UPC_TO_INTR)) {
05511         // the optimizer creates TAS(TAS ...
05512         // when doing copy propagation . Strip all inner TASes,
05513         // but save the outermost one for StoP conversion
05514         //
05515         WN *kid0 = WN_kid0(tree);
05516         TY_IDX kid_idx = WN_ty(kid0);
05517         kid0 = Strip_TAS(kid0);
05518         UINT field_id;
05519         if(WN_operator(WN_kid0(tree)) != OPR_TAS || WN_ty(kid0) != 0) { 
05520           kid_idx = WN_ty(kid0);
05521           if(OPERATOR_is_load(WN_operator(kid0)) && WN_field_id(kid0)) {
05522             switch(WN_operator(kid0)) {
05523             case OPR_LDID:
05524             case OPR_ILOAD:
05525               kid_idx = Get_Field_Type(kid_idx, WN_field_id(kid0));
05526               break;
05527             default:
05528               Is_True(0,("",""));
05529             }
05530           }
05531         }
05532         WN_kid0(tree) = kid0;
05533 
05534 
05535         TY_IDX tas_idx = WN_ty(tree);
05536         INTRINSIC iop;
05537         BOOL spill = (WN_operator(kid0) == OPR_LDID &&  ST_class(WN_st(kid0)) == CLASS_PREG);
05538  //     fdump_tree(stderr, tree);
05539         
05540         if(Type_Is_Shared_Ptr(kid_idx, TRUE) && Need_StoP_Cvt(kid_idx, tas_idx, &iop)) 
05541           {     
05542            //  Ty_Table[kid_idx].Print(stderr);
05543 //          Ty_Table[tas_idx].Print(stderr);
05544             WN *res = lower_expr(block, kid0, actions);
05545             if(WN_operator(res) == OPR_COMMA || spill)
05546               res = Spill_Shared_Load(res);
05547             return  WN_Create_StoP_Cvt(res, iop);
05548           } 
05549       }
05550       //WEI: don't think we need the TAS anymore 
05551       //return lower_expr(block, WN_kid0(tree), actions);
05552       WN_kid0(tree) = lower_expr(block, WN_kid0(tree), actions);
05553      //  if(WN_rtype(tree) != WN_rtype(WN_kid0(tree)))
05554 //      return WN_kid0(tree);
05555 //       else 
05556         return tree;
05557     }
05558       
05559     break;
05560 
05561   case OPR_IMAGPART:
05562     if (Action(LOWER_COMPLEX))
05563     {
05564       WN        *realexp, *imagexp;
05565       lower_complex_expr(block, WN_kid0(tree), actions, &realexp, &imagexp);
05566       WN_Delete(tree);
05567       tree = lower_expr(block, imagexp, actions);
05568     }
05569     break;
05570 
05571   case OPR_REALPART:
05572     if (Action(LOWER_COMPLEX))
05573     {
05574       WN        *realexp, *imagexp;
05575 
05576       lower_complex_expr(block, WN_kid0(tree), actions, &realexp, &imagexp);
05577       WN_Delete(tree);
05578       tree = lower_expr(block, realexp, actions);
05579     }
05580     break;
05581     
05582   case OPR_EQ:
05583       if (Action(LOWER_COMPLEX) && MTYPE_is_complex(WN_desc(tree)))
05584     {
05585       /*
05586        *  x == y
05587        *    R(x)==R(y) && I(x)==I(y)
05588        */
05589       WN        *rx, *ry, *ix, *iy;
05590       TYPE_ID   realTY = Mtype_complex_to_real( WN_desc(tree));
05591 
05592       lower_complex_expr(block, WN_kid0(tree), actions, &rx, &ix);
05593       lower_complex_expr(block, WN_kid1(tree), actions, &ry, &iy);
05594  
05595       tree = WN_LAND(WN_EQ(realTY, rx, ry),
05596                      WN_EQ(realTY, ix, iy));
05597 
05598       return lower_expr(block, tree, actions);
05599     }
05600     if(Action(LOWER_UPC_TO_INTR)) {
05601       if(WN_Type_Is_Shared_Ptr(WN_kid0(tree)) || 
05602          WN_Type_Is_Shared_Ptr(WN_kid1(tree))) {
05603         
05604         TY_IDX idx0 = WN_ty(WN_kid0(tree));
05605         TY_IDX idx1 = WN_ty(WN_kid1(tree));
05606         WN *kid0 = lower_expr(block, WN_kid0(tree), actions);
05607         WN *kid1 = lower_expr(block, WN_kid1(tree), actions);
05608         if(Type_Is_Shared_Ptr(idx0, TRUE) && Type_Is_Shared_Ptr(idx1, TRUE)) {
05609           tree = WN_Create_PtrEq_Test(OPR_EQ, kid0, kid1, idx0, idx1);
05610         } else if(Type_Is_Shared_Ptr(idx1, TRUE) || Type_Is_Shared_Ptr(idx0, TRUE)) {
05611           Is_True(WN_operator(kid0) == OPR_INTCONST ||
05612                   WN_operator(kid1) == OPR_INTCONST || 
05613                   WN_operator(kid0) == OPR_LDID ||
05614                   WN_operator(kid1) == OPR_LDID,
05615                   ("Mismatching operators for shared pointer operation",""));
05616           tree = WN_Create_PtrEq_Test(OPR_EQ, kid0, kid1, idx0, idx1);
05617         } else {
05618             WN_kid0(tree) = kid0;
05619             WN_kid1(tree) = kid1;
05620             kids_lowered = TRUE;
05621           }  
05622         return tree;
05623       }
05624     }
05625     break;
05626 
05627   case OPR_NE:
05628       if (Action(LOWER_COMPLEX) && MTYPE_is_complex(WN_desc(tree)))
05629         {
05630           /*
05631            *  x != y
05632            *    ! ( R(x)==R(y)  &&  I(x)==I(y) )
05633            */
05634           WN    *rx, *ry, *ix, *iy;
05635           TYPE_ID       realTY = Mtype_complex_to_real( WN_desc(tree));
05636           
05637           lower_complex_expr(block, WN_kid0(tree), actions, &rx, &ix);
05638           lower_complex_expr(block, WN_kid1(tree), actions, &ry, &iy);
05639           
05640           tree = WN_LNOT(WN_LAND(WN_EQ(realTY, rx, ry),
05641                                  WN_EQ(realTY, ix, iy)));
05642           
05643           return lower_expr(block, tree, actions);
05644         }
05645       if(Action(LOWER_UPC_TO_INTR)) {
05646         if(WN_Type_Is_Shared_Ptr(WN_kid0(tree)) || 
05647            WN_Type_Is_Shared_Ptr(WN_kid1(tree))) {
05648           
05649           TY_IDX idx0 = WN_ty(WN_kid0(tree));
05650           TY_IDX idx1 = WN_ty(WN_kid1(tree));
05651           WN *kid0 = lower_expr(block, WN_kid0(tree), actions);
05652           WN *kid1 = lower_expr(block, WN_kid1(tree), actions);
05653           if(Type_Is_Shared_Ptr(idx0, TRUE) && Type_Is_Shared_Ptr(idx1, TRUE)) {
05654             tree = WN_Create_PtrEq_Test(OPR_NE, kid0, kid1, idx0, idx1);
05655           } else if(Type_Is_Shared_Ptr(idx1, TRUE) || Type_Is_Shared_Ptr(idx0, TRUE)) {
05656             Is_True( (WN_operator(kid0) == OPR_INTCONST && WN_const_val(kid0) == 0)  ||
05657                      (WN_operator(kid1) == OPR_INTCONST &&  WN_const_val(kid1) == 0) ||
05658                      WN_operator(kid0) == OPR_LDID ||
05659                      WN_operator(kid1) == OPR_LDID,
05660                      ("Mismatching operators for shared pointer operation",""));
05661             tree = WN_Create_PtrEq_Test(OPR_NE, kid0, kid1, idx0, idx1);
05662           } else {
05663             WN_kid0(tree) = kid0;
05664             WN_kid1(tree) = kid1;
05665             kids_lowered = TRUE;
05666           }  
05667           return tree;
05668         }
05669     }
05670     break;
05671 
05672   case OPR_MADD:
05673     if (Action(LOWER_QUAD) && MTYPE_is_quad(type))
05674     {
05675      /*
05676       *   kid1 * kid2 + kid0
05677       */
05678       WN        *wn;
05679 
05680       wn = WN_Add(type,
05681                   WN_Mpy(type, WN_kid1(tree), WN_kid2(tree)),
05682                   WN_kid0(tree));
05683       WN_Delete(tree);
05684 
05685       tree = wn;
05686     }
05687     break;
05688 
05689   case OPR_MSUB:
05690     if (Action(LOWER_QUAD) && MTYPE_is_quad(type))
05691     {
05692      /*
05693       *   kid1 * kid2 - kid0
05694       */
05695       WN        *wn;
05696 
05697       wn = WN_Sub(type,
05698                   WN_Mpy(type, WN_kid1(tree), WN_kid2(tree)),
05699                   WN_kid0(tree));
05700       WN_Delete(tree);
05701 
05702       tree = wn;
05703     }
05704     break;
05705 
05706   case OPR_NMADD:
05707     if (Action(LOWER_QUAD) && MTYPE_is_quad(type))
05708     {
05709      /*
05710       *   - (kid1 * kid2 + kid0)
05711       */
05712       WN        *wn, *madd;
05713 
05714       madd = WN_Add(type,
05715                     WN_Mpy(type, WN_kid1(tree), WN_kid2(tree)),
05716                     WN_kid0(tree));
05717 
05718       wn = WN_Neg(type, madd);
05719       WN_Delete(tree);
05720 
05721       tree = wn;
05722     }
05723     break;
05724 
05725   case OPR_NMSUB:
05726     if (Action(LOWER_QUAD) && MTYPE_is_quad(type))
05727     {
05728      /*
05729       *   - (kid1 * kid2 - kid0)  -->   (kid0 - kid1 * kid2)
05730       */
05731       WN        *wn;
05732 
05733       wn = WN_Sub(type,
05734                   WN_kid0(tree),
05735                   WN_Mpy(type, WN_kid1(tree), WN_kid2(tree)));
05736       WN_Delete(tree);
05737 
05738       tree = wn;
05739     }
05740     break;
05741 
05742   case OPR_RSQRT:
05743     tree = lower_rsqrt(block, tree, actions);
05744     break;
05745 
05746   case OPR_RECIP:
05747     tree = lower_recip(block, tree, actions);
05748     break;
05749 
05750   case OPR_SELECT:
05751     {
05752       WN * const kid0 = WN_kid0(tree);  // the condition expression
05753       if (WN_operator_is(kid0, OPR_INTCONST))
05754       {
05755         INT64 flag = WN_const_val(kid0);
05756         WN * const kid = flag ? WN_kid1(tree) : WN_kid2(tree);
05757         return lower_expr(block, kid, actions);
05758       } else if (WN_operator(kid0) == OPR_LNOT) {
05759         // swap the select inputs and replace the condition with
05760         // operand of the LNOT. Then lower the whole tree again
05761         // as there may be further lowerings that may occur with the
05762         // new operands.
05763         WN * const new_kid1 = WN_kid2(tree);
05764         WN * const new_kid2 = WN_kid1(tree);
05765         WN * const new_kid0 = WN_kid0(kid0);
05766         TYPE_ID new_desc = (WN_rtype(new_kid0) == MTYPE_B) ? MTYPE_B : MTYPE_V;
05767         WN_kid0(tree) = new_kid0;
05768         WN_kid1(tree) = new_kid1;
05769         WN_kid2(tree) = new_kid2;
05770         WN_set_desc(tree, new_desc);
05771         WN_Delete(kid0);
05772         return lower_expr(block, tree, actions);
05773       }
05774     }
05775     break;
05776 
05777   case OPR_PAREN:
05778     if (Roundoff_Level > ROUNDOFF_ASSOC)
05779     {
05780      /*
05781       *  At suitable roundoff we may remove these parens
05782       *  This will allow better MADD generation latter (pv 316380)
05783       */
05784       WN *kid0 = WN_kid0(tree);
05785 
05786       WN_Delete(tree);
05787       return lower_expr(block, kid0, actions);
05788     }
05789     break;
05790 
05791   case OPR_DIV:
05792   case OPR_REM:
05793   case OPR_MOD:
05794 
05795     {
05796 
05797       /* If not inlining divides, then generate an INTRINSIC_OP that is
05798        * later lowered to a call
05799        */
05800       TYPE_ID rtype = OPCODE_rtype(WN_opcode(tree));
05801       if (Should_Call_Divide(rtype) && !Is_Fast_Divide(tree)) {
05802 
05803 #ifdef EMULATE_LONGLONG
05804         if (rtype == MTYPE_I8 || rtype == MTYPE_U8) {
05805           FmtAssert (OPCODE_rtype(WN_opcode(WN_kid0(tree))) == rtype,
05806                      ("DIV/REM/MOD: kid0 should be %d, is %d",
05807                      rtype, OPCODE_rtype(WN_opcode(WN_kid0(tree)))));
05808           FmtAssert (OPCODE_rtype(WN_opcode(WN_kid1(tree))) == rtype,
05809                      ("DIV/REM/MOD: kid1 should be %d, is %d",
05810                      rtype, OPCODE_rtype(WN_opcode(WN_kid1(tree)))));
05811         }
05812 #endif
05813 
05814         WN *kids[2];
05815         WN *iwn;
05816         LEAF tmpY;
05817         INTRINSIC intrinsic;
05818         BOOL is_unsigned = MTYPE_is_unsigned(rtype);
05819         BOOL is_float = MTYPE_is_float(rtype);
05820         BOOL is_double = MTYPE_is_size_double(rtype);
05821         switch (WN_operator(tree)) {
05822         case OPR_DIV:
05823           if (is_float) {
05824             intrinsic = (is_double ? INTRN_DIVDF3 : INTRN_DIVSF3);
05825           } else if (is_double) {
05826             intrinsic = (is_unsigned ? INTRN_UDIVDI3 : INTRN_DIVDI3);
05827           } else {
05828             intrinsic = (is_unsigned ? INTRN_UDIVSI3 : INTRN_DIVSI3);
05829           }
05830           break;
05831         case OPR_MOD:
05832           FmtAssert(!is_float, ("Unexpected MOD operator on float"));
05833           // Unsigned MOD is the same as REM.
05834           // Signed MOD is a REM followed by an adjustment which
05835           // uses the divisor, so save it to a temp and replace the
05836           // divisor operand of the tree with a load from the temp.
05837           if (!is_unsigned) {
05838             tmpY = Make_Leaf(block, WN_kid1(tree), type);
05839             WN_kid1(tree) = Load_Leaf(tmpY);
05840           }
05841           /*FALLTHROUGH*/
05842         case OPR_REM:
05843           FmtAssert(!is_float, ("Unexpected REM operator on float"));
05844           if (is_double) {
05845             intrinsic = (is_unsigned ? INTRN_UMODDI3 : INTRN_MODDI3);
05846           } else {
05847             intrinsic = (is_unsigned ? INTRN_UMODSI3 : INTRN_MODSI3);
05848           }
05849           break;
05850         default:
05851           FmtAssert (FALSE, ("Unexpected division operator"));
05852           /*NOTREACHED*/
05853         }
05854         kids[0] = WN_CreateParm (rtype,
05855                                  lower_expr(block, WN_kid0(tree), actions),
05856                                  Be_Type_Tbl(rtype),
05857                                  WN_PARM_BY_VALUE | WN_PARM_READ_ONLY);
05858         kids[1] = WN_CreateParm (rtype, 
05859                                  lower_expr(block, WN_kid1(tree), actions),
05860                                  Be_Type_Tbl(rtype),
05861                                  WN_PARM_BY_VALUE | WN_PARM_READ_ONLY);
05862         iwn = WN_Create_Intrinsic(OPCODE_make_op(OPR_INTRINSIC_OP,
05863                                                  rtype, MTYPE_V),
05864                                   intrinsic, 2, kids);
05865 
05866         if (WN_operator(tree) == OPR_MOD && !is_unsigned) {
05867           // For signed MOD, we need to add the divisor to the result
05868           // of the REM if both of the operands are negative.
05869           WN *t2, *t3, *t4;
05870           PREG_NUM t1;
05871           t1 = AssignExpr(block, iwn, type);
05872           t2 = WN_Bxor(type, WN_LdidPreg(type, t1), Load_Leaf(tmpY));
05873           t3 = WN_Ashr(type, t2, WN_Intconst(type, MTYPE_size_reg(type) - 1));
05874           t4 = WN_Band(type, Load_Leaf(tmpY), t3);
05875           iwn = WN_Add(type, WN_LdidPreg(type, t1), t4);
05876           iwn = lower_expr(block, iwn, actions);
05877         }
05878 
05879         WN_Delete(tree);
05880         return iwn;
05881       }
05882     }
05883 
05884     if (Action(LOWER_COMPLEX) && MTYPE_is_complex(WN_rtype(tree))) {
05885         // complex div creates if-then-else structure,
05886         // so want to expand this early, then just return C*LDID preg here
05887         // (e.g. in case is under a PARM node, and is not first parm).
05888         // Note that fortran fe moves this out from under call, 
05889         // but C doesn't.  Apparently only get here for C PARM case.
05890         TYPE_ID cdiv_mtype = WN_rtype(tree);
05891         // using a preg causes wopt to get confused and not
05892         // connect the F* preg numbers with the C* preg number.
05893         // so use temp symbol instead.
05894         TY_IDX cdiv_ty = MTYPE_To_TY(cdiv_mtype);
05895         ST *cdiv_st = Gen_Temp_Symbol (cdiv_ty, ".complex_div");
05896         WN *stid = WN_Stid(cdiv_mtype, 0, cdiv_st, cdiv_ty, tree);
05897         WN_Set_Linenum (stid, current_srcpos);
05898         stid = lower_store(block, stid, actions);
05899         WN_INSERT_BlockLast(block, stid);
05900         WN *ldid = WN_Ldid(cdiv_mtype, 0, cdiv_st, cdiv_ty);
05901         return ldid;
05902     }
05903     break;
05904 
05905   case OPR_COMMA:
05906     {
05907       WN *commaBlock;
05908       commaBlock = lower_block(WN_kid0(tree), actions);
05909       
05910       //during UPC lowering we create comma operators that
05911       // are otherwise illegal when compiling a regular file
05912       // through the code gen
05913       if (!Action(LOWER_UPC_TO_INTR) && !Action(LOWER_UPC_INTRINSIC))
05914         DevWarn("lower_expr(): comma operator seen, line %d",
05915                 Srcpos_To_Line(current_srcpos));
05916 
05917       WN_INSERT_BlockLast(block, commaBlock);
05918     }
05919     return lower_expr(block, WN_kid1(tree), actions);
05920 
05921   case OPR_CSELECT:
05922    /*
05923     *  
05924     */
05925     if (Action(LOWER_SHORTCIRCUIT))
05926     {
05927       /*******************************************************************
05928 
05929       DevWarn("lower_expr(): cselect operator seen, line %d",
05930               Srcpos_To_Line(current_srcpos));
05931       *******************************************************************/
05932 
05933       if (expr_is_speculative(tree))
05934       {
05935         WN *select = WN_Select(type, WN_kid0(tree), WN_kid1(tree),
05936                                WN_kid2(tree));
05937   
05938         WN_Delete(tree);
05939         return select;
05940       }
05941       else
05942       {
05943         PREG_NUM  tmpN;
05944         WN *if_tree, *if_then, *if_else, *stid;
05945         WN *body = WN_CreateBlock();
05946 
05947         if_then = WN_CreateBlock();
05948         tmpN = AssignExpr(if_then, WN_kid1(tree), type);
05949 
05950         if_else = WN_CreateBlock();
05951         stid = WN_StidIntoPreg(type, tmpN, MTYPE_To_PREG(type), WN_kid2(tree));
05952         WN_INSERT_BlockLast(if_else, stid);
05953 
05954         if_tree = WN_CreateIf( WN_kid0(tree), if_then, if_else );
05955         if ( Cur_PU_Feedback )
05956           Cur_PU_Feedback->FB_lower_branch( tree, if_tree );
05957         WN_INSERT_BlockLast( block, lower_if( body, if_tree, actions ) );
05958 
05959         return WN_LdidPreg(type, tmpN);
05960       }
05961     }
05962     break;
05963 
05964   case OPR_CAND:
05965   case OPR_CIOR:
05966    /*
05967     *  return boolean 0/1 (build CSELECT)
05968     */
05969     if (Action(LOWER_SHORTCIRCUIT))
05970     {
05971       if (expr_is_speculative(tree))
05972       {
05973         WN *cond;
05974 
05975         if (WN_operator_is(tree, OPR_CAND))
05976           cond = WN_LAND( WN_kid0(tree), WN_kid1(tree));
05977         else
05978           cond = WN_LIOR( WN_kid0(tree), WN_kid1(tree));
05979 
05980         WN_Delete(tree);
05981         return lower_expr(block, cond, actions);
05982       }
05983       else
05984       {
05985         WN *select = WN_Cselect(type,
05986                                 tree,   
05987                                 WN_Intconst(Boolean_type, 1),
05988                                 WN_Intconst(Boolean_type, 0));
05989         return lower_expr(block, select, actions);
05990       }
05991     }
05992     break;
05993   }
05994 
05995   
05996   if (Action(LOWER_QUAD))
05997   {
05998     if (WN_desc(tree) == MTYPE_FQ)
05999     {
06000       switch (WN_operator(tree))
06001       {
06002       case OPR_CONST:
06003       case OPR_LDID:
06004       case OPR_ILOAD:
06005         break;
06006       case OPR_EQ:
06007       case OPR_NE:
06008       case OPR_LE:
06009       case OPR_LT:
06010       case OPR_GT:
06011       case OPR_GE:
06012       case OPR_CVT:
06013       case OPR_TRUNC:
06014       case OPR_RND:
06015       case OPR_CEIL:
06016       case OPR_FLOOR:
06017         tree = lower_emulation(block, tree, actions,intrinsic_lowered);
06018         break;
06019       default:
06020         break;
06021       }
06022     }
06023     if (WN_rtype(tree) == MTYPE_FQ)
06024     {
06025       switch (WN_operator(tree))
06026       {
06027       case OPR_CONST:
06028       case OPR_LDID:
06029       case OPR_ILOAD:
06030         break;
06031 
06032       case OPR_SELECT:
06033       case OPR_NEG:
06034       case OPR_ABS:
06035       case OPR_SQRT:
06036       case OPR_ADD:
06037       case OPR_SUB:
06038       case OPR_MPY:
06039       case OPR_DIV:
06040       case OPR_MOD:
06041       case OPR_REM:
06042       case OPR_MAX:
06043       case OPR_MIN:
06044       case OPR_CVT:
06045       case OPR_TRUNC:
06046       case OPR_RND:
06047         tree = lower_emulation(block, tree, actions, intrinsic_lowered);
06048         break;
06049       default:
06050         break;
06051       }
06052     }
06053   }
06054 
06055   if (WN_nary_intrinsic(tree))
06056   {
06057     tree = WN_NaryToExpr(tree);
06058   }
06059 
06060   /* Lower kids if not done already. */
06061   if (! kids_lowered)
06062   {
06063      INT16 i;
06064      for (i = 0; i < WN_kid_count(tree); i++)
06065        WN_kid(tree,i) = lower_expr(block, WN_kid(tree,i), actions);
06066      tree = WN_Simplify_Rebuild_Expr_Tree(tree,alias_manager);
06067   }
06068 
06069   return tree;
06070 }
06071 
06072 
06073 /* ====================================================================
06074  *
06075  *  static TY_IDX coerceTY(TY_IDX type, TYPE_ID btype)
06076  *
06077  * return TY corresponding to the btype
06078  * (type might be pointer -> btype)
06079  *
06080  * ==================================================================== */
06081 
06082 static TY_IDX coerceTY(TY_IDX type, TYPE_ID btype)
06083 {
06084   TY &ty = Ty_Table[type];
06085 
06086   if (TY_is_pointer(ty))
06087     return Make_Pointer_Type(coerceTY(TY_pointed(ty), btype));
06088 
06089   return MTYPE_To_TY(btype);
06090 }
06091 
06092 
06093 
06094 
06095 /* ====================================================================
06096  *
06097  *  static ST * coerceST(const ST *st, TYPE_ID type)
06098  *
06099  * return ST corresponding to the type
06100  *
06101  * ==================================================================== */
06102 
06103 static ST *coerceST(const ST *st, TYPE_ID type)
06104 {
06105   if (ST_class(st) == CLASS_PREG)
06106   {
06107    /*
06108     *  for now, only pregs must correspond to the type
06109     */
06110     return MTYPE_To_PREG(type);
06111   }
06112 
06113   return (ST *) st;
06114 }
06115 
06116 static ST *coerceST(const ST &st, TYPE_ID type)
06117 {
06118   if (ST_class(&st) == CLASS_PREG)
06119   {
06120    /*
06121     *  for now, only pregs must correspond to the type
06122     */
06123     return MTYPE_To_PREG(type);
06124   }
06125 
06126   return (ST *) &st;
06127 }
06128 
06129 
06130 /* ====================================================================
06131  *
06132  * static BOOL WN_StoreIsUnused(WN *tree)
06133  *
06134  * Find if store has been marked by IPA as unused
06135  * This may require traversal of the address expression to find
06136  * an LDA or ARRAY
06137  * ==================================================================== */
06138 static BOOL WN_StoreIsUnused(WN *tree)
06139 {
06140   ST  *sym;
06141 
06142   switch(WN_operator(tree))
06143   {
06144   case OPR_LDA:
06145   case OPR_STID:
06146     sym = WN_st(tree);
06147 
06148     if (ST_class(sym) != CLASS_PREG  &&
06149         ST_class(sym) != CLASS_BLOCK &&
06150         ST_is_not_used(sym))
06151       return TRUE;
06152     break;
06153 
06154   case OPR_ARRAY:
06155     return WN_StoreIsUnused(WN_array_base(tree));
06156   }
06157 
06158   return FALSE;
06159 }
06160 
06161 /* ====================================================================
06162  *
06163  * WN *add_fake_parm(WN *o_call, WN *fake_actual)
06164  *
06165  * Add the fake actual parameter as the first parameter to the original call.
06166  * All original parameters are shifted down by 1.
06167  *
06168  * ==================================================================== */
06169 static WN *add_fake_parm(WN *o_call, WN *fake_actual, TY_IDX ty_idx)
06170 {
06171   WN *n_call;
06172   if (WN_operator(o_call) == OPR_ICALL)
06173     n_call = WN_Icall(MTYPE_V, MTYPE_V, WN_kid_count(o_call)+1, WN_ty(o_call));
06174   else
06175     n_call = WN_generic_call(WN_operator(o_call), MTYPE_V, MTYPE_V, 
06176                              WN_kid_count(o_call)+1, WN_st_idx(o_call));
06177   WN_call_flag(n_call) = WN_call_flag(o_call);
06178   WN_Set_Linenum(n_call, WN_Get_Linenum(o_call));
06179   if ( Cur_PU_Feedback ) {
06180     Cur_PU_Feedback->FB_lower_call( o_call, n_call );
06181   }
06182   WN_kid0(n_call) = WN_CreateParm(Pointer_Mtype, fake_actual, ty_idx,
06183                               WN_PARM_BY_REFERENCE | WN_PARM_PASSED_NOT_SAVED);
06184   for (INT32 i = 0; i < WN_kid_count(o_call); i++)
06185     WN_kid(n_call, i+1) = WN_COPY_Tree(WN_kid(o_call, i));
06186   return n_call;
06187 }
06188 
06189 /* ====================================================================
06190  *
06191  * WN *lower_return_mstid(WN *block, WN *tree, LOWER_ACTIONS actions)
06192  *
06193  * "tree" must be an MSTID whose kid is MLDID of Return_Val_Preg (-1).
06194  * Perform lowering of MSTID whose rhs is Return_Val_Preg; translate to
06195  * either MSTORE or a sequence of STIDs.
06196  *
06197  * ==================================================================== */
06198 static WN *lower_return_mstid(WN *block, WN *tree, LOWER_ACTIONS actions)
06199 {
06200   TYPE_ID mtype;
06201   ST *preg_st;
06202   WN *n_rhs;
06203   WN *wn = NULL;        // init to prevent upward-exposed use
06204   RETURN_INFO return_info = Get_Return_Info(WN_ty(tree), Complex_Not_Simulated);
06205   if (RETURN_INFO_return_via_first_arg(return_info)) { // fake first parm
06206     // get the previous MCALL statement
06207     WN *call = WN_last(block);
06208     Is_True(WN_operator(call) == OPR_CALL || WN_operator(call) == OPR_ICALL ||
06209             WN_operator(call) == OPR_PICCALL,
06210             ("statement preceding MMLDID of Return_Val_Preg must be a call"));
06211     Is_True(WN_rtype(call) == MTYPE_M,
06212             ("call preceding MMLDID of Return_Val_Preg not type M"));
06213     WN *awn = WN_CreateLda(OPR_LDA, Pointer_Mtype, MTYPE_V, 
06214                            WN_store_offset(tree), 
06215                            Make_Pointer_Type(WN_ty(tree)), WN_st_idx(tree));
06216     awn = lower_expr(block, awn, actions);
06217     WN *n_call = add_fake_parm(call, awn, WN_ty(awn));
06218     WN_DELETE_FromBlock(block, call);
06219     WN_INSERT_BlockLast(block, n_call); 
06220 
06221     WN_DELETE_Tree(tree);
06222     return NULL; // original MSTID disappears
06223   }
06224   else { // return via 1 or more return registers
06225     for (INT32 i = 0; i < RETURN_INFO_count(return_info); i++) {
06226       if (i != 0)
06227         WN_INSERT_BlockLast (block, wn); // insert the last STID created 
06228       mtype = RETURN_INFO_mtype(return_info, i);
06229       preg_st = MTYPE_is_float(mtype) ? Float_Preg : Int_Preg;
06230       n_rhs = WN_CreateLdid(OPR_LDID, mtype, mtype, 
06231                             RETURN_INFO_preg(return_info, i), preg_st,
06232                             Be_Type_Tbl(mtype));
06233       if (TY_align(ST_type(WN_st(tree))) < MTYPE_alignment(mtype)) {
06234         // shared_ptr_idx and pshared_ptr_idx are opaque types
06235         // when the type does not fit in a register we are conservative
06236         // and asume an alignment of 1
06237         if(ST_type(WN_st(tree)) != shared_ptr_idx && ST_type(WN_st(tree)) != pshared_ptr_idx)
06238           DevWarn("return_info struct alignment is smaller than register size, may produce wrong results");
06239       }
06240       wn = WN_CreateStid(OPR_STID, MTYPE_V, mtype, 
06241                          WN_store_offset(tree)+i*MTYPE_byte_size(mtype),
06242                          WN_st_idx(tree), Be_Type_Tbl(mtype), n_rhs);
06243       wn  = lower_store (block, wn, actions);
06244       WN_Set_Linenum (wn, WN_Get_Linenum(tree));
06245     }
06246     WN_DELETE_Tree(tree);
06247     return wn;
06248   }
06249 }
06250 
06251 /* ====================================================================
06252  *
06253  * WN *lower_return_mistore(WN *block, WN *tree, LOWER_ACTIONS actions)
06254  *
06255  * "tree" must be an MISTORE whose rhs is MLDID of Return_Val_Preg (-1).
06256  * Perform lowering of MISTORE whose rhs is Return_Val_Preg; translate to
06257  * either MSTORE or a sequence of ISTOREs.
06258  *
06259  * ==================================================================== */
06260 static WN *lower_return_mistore(WN *block, WN *tree, LOWER_ACTIONS actions)
06261 {
06262   TYPE_ID mtype;
06263   ST *preg_st;
06264   WN *n_rhs;
06265   WN *wn = NULL;        // init to prevent upward-exposed use
06266   RETURN_INFO return_info = Get_Return_Info(WN_ty(tree), Complex_Not_Simulated);
06267   if (RETURN_INFO_return_via_first_arg(return_info)) { // fake first parm
06268     // get the previous MCALL statement
06269     WN *call = WN_last(block);
06270     Is_True(WN_operator(call) == OPR_CALL || WN_operator(call) == OPR_ICALL ||
06271             WN_operator(call) == OPR_PICCALL,
06272             ("statement preceding MMLDID of Return_Val_Preg must be a call"));
06273     Is_True(WN_rtype(call) == MTYPE_M,
06274             ("call preceding MMLDID of Return_Val_Preg not type M"));
06275     WN *awn = WN_COPY_Tree(WN_kid1(tree));
06276     if (WN_store_offset(tree) != 0) { // generate an ADD node for the offset
06277       WN *iwn = WN_CreateIntconst(OPR_INTCONST, Pointer_Mtype, MTYPE_V, 
06278                                   WN_store_offset(tree));
06279       awn = WN_CreateExp2(OPR_ADD, Pointer_Mtype, Pointer_Mtype, awn, iwn);
06280     }
06281     awn = lower_expr(block, awn, actions);
06282     WN *n_call = add_fake_parm(call, awn, WN_ty(tree));
06283     WN_DELETE_FromBlock(block, call);
06284     WN_INSERT_BlockLast(block, n_call); 
06285 
06286     WN_DELETE_Tree(tree);
06287     return NULL; // original MSTID disappears
06288   }
06289   else { // return via 1 or more return registers
06290     WN *base_expr;
06291     for (INT32 i = 0; i < RETURN_INFO_count(return_info); i++) {
06292       if (i != 0)
06293         WN_INSERT_BlockLast (block, wn); // insert the last STID created 
06294       mtype = RETURN_INFO_mtype(return_info, i);
06295       preg_st = MTYPE_is_float(mtype) ? Float_Preg : Int_Preg;
06296       n_rhs = WN_CreateLdid(OPR_LDID, mtype, mtype, 
06297                             RETURN_INFO_preg(return_info, i), preg_st,
06298                             Be_Type_Tbl(mtype));
06299       base_expr = WN_COPY_Tree(WN_kid1(tree));
06300       wn = WN_CreateIstore(OPR_ISTORE, MTYPE_V, mtype, 
06301                            WN_store_offset(tree)+i*MTYPE_byte_size(mtype),
06302                            Be_Type_Tbl(mtype), n_rhs, base_expr);
06303       wn  = lower_store (block, wn, actions);
06304       WN_Set_Linenum (wn, WN_Get_Linenum(tree));
06305     }
06306     WN_DELETE_Tree(tree);
06307     return wn;
06308   }
06309 }
06310 
06311 /* ====================================================================
06312  *
06313  * WN *lower_mstid(WN *block, WN *tree, LOWER_ACTIONS actions)
06314  *
06315  * Perform lowering (see WN_Lower description) on MSTID nodes returning
06316  * an equivalent MSTORE node.
06317  *
06318  * ==================================================================== */
06319 
06320 static WN *lower_mstid(WN *block, WN *tree, LOWER_ACTIONS actions)
06321 {
06322   TY_IDX ty_idx  = WN_ty(tree);
06323   TY_IDX pty_idx = WN_field_id(tree) == 0 ? 0 : get_field_type (ty_idx, WN_field_id(tree));
06324   UINT64 size    = pty_idx  == 0 ?  TY_size(ty_idx):  TY_size(pty_idx );
06325 
06326   
06327   if(Action(LOWER_UPC_MFIELD) && pty_idx && Type_Is_Shared_Ptr(pty_idx))
06328     size = TY_size(TY_To_Sptr_Idx(pty_idx));
06329   
06330   WN*    wn;
06331   WN*    awn;
06332   WN*    swn;
06333   WN *rhs = WN_kid0(tree);
06334 
06335 
06336 
06337   // if it is ptr to shared patch both the STID and the LDID to 
06338   // have the mtype corresponding to the shared_ptr_type 
06339   if(Type_Is_Shared_Ptr(ty_idx) && WN_operator(rhs) == OPR_LDID &&
06340      WN_st(rhs) == Return_Val_Preg ) {
06341     ty_idx = TY_To_Sptr_Idx(ty_idx);
06342     TYPE_ID rtype = TY_mtype(ty_idx);
06343     WN_set_desc(tree, rtype);
06344    //  WN_set_rtype(tree, rtype);
06345     WN_set_ty(tree, ty_idx);
06346     
06347     WN_set_desc(rhs, rtype);
06348     WN_set_rtype(rhs, rtype);
06349     WN_set_ty(rhs, TY_To_Sptr_Idx(WN_ty(rhs)));
06350   }  
06351 
06352 
06353   Is_True((WN_operator(tree) == OPR_STID && WN_desc(tree) == MTYPE_M),
06354           ("expected mstid node, not %s", OPCODE_name(WN_opcode(tree))));
06355 
06356   pty_idx = Make_Pointer_Type (ty_idx, FALSE);
06357 
06358   if (WN_opcode(rhs) == OPC_MMLDID && WN_st(rhs) == Return_Val_Preg) {
06359     // handle lowering of MLDID of Return_Val_Preg followed by MSTID
06360     Is_True(Action(LOWER_RETURN_VAL),
06361             ("LOWER_RETURN_VAL action must be specified"));
06362     return lower_return_mstid(block, tree, actions);
06363   }
06364 
06365   awn = WN_CreateLda (OPR_LDA, Pointer_Mtype, MTYPE_V, 0// WN_store_offset(tree)
06366 ,
06367                       pty_idx, WN_st(tree));
06368   swn = WN_CreateIntconst (OPC_U4INTCONST, size);
06369   wn  = WN_CreateMstore (WN_store_offset(tree)// 0
06370                          , pty_idx, WN_kid0(tree), awn, swn);
06371   WN_set_field_id(wn, WN_field_id(tree));
06372   // if(Action(LOWER_UPC_MFIELD))
06373 //     return wn;
06374  wn  = lower_store (block, wn, actions);
06375 
06376   WN_Delete(tree);
06377   return wn;
06378 }
06379 
06380 
06381 /* ====================================================================
06382  *
06383  * WN *lower_mistore(WN *block, WN *tree, LOWER_ACTIONS actions)
06384  *
06385  * Perform lowering (see WN_Lower description) on MISTORE nodes returning
06386  * an equivalent MSTORE node.
06387  *
06388  * ==================================================================== */
06389 
06390 static WN *lower_mistore(WN *block, WN *tree, LOWER_ACTIONS actions)
06391 {
06392   TY_IDX pty_idx  = WN_ty(tree);
06393   TY_IDX ty_idx  = TY_pointed(pty_idx);
06394 
06395   if (WN_field_id (tree) != 0)
06396     ty_idx = get_field_type (ty_idx, WN_field_id (tree));
06397   
06398   UINT64 size    = TY_size(Ty_Table[ty_idx]);
06399   if(Action(LOWER_UPC_MFIELD) && WN_field_id(tree) && Type_Is_Shared_Ptr(ty_idx))
06400     size = TY_size(TY_To_Sptr_Idx(ty_idx));
06401   WN*    wn;
06402   WN*    swn;
06403 
06404   Is_True((WN_operator(tree) == OPR_ISTORE && WN_desc(tree) == MTYPE_M),
06405           ("expected mistore node, not %s", OPCODE_name(WN_opcode(tree))));
06406   Is_True(TY_kind(pty_idx) == KIND_POINTER,
06407           ("type specified in MISTORE not pointer"));
06408 //Is_True(size > 0, ("type in MISTORE cannot be zero size"));
06409   if (size == 0)
06410     DevWarn ("type in MISTORE cannot be zero size");
06411   WN *rhs = WN_kid0(tree);
06412   if (WN_opcode(rhs) == OPC_MMLDID && WN_st(rhs) == Return_Val_Preg) {
06413     // handle lowering of MLDID of Return_Val_Preg followed by MISTORE
06414     Is_True(Action(LOWER_RETURN_VAL),
06415             ("LOWER_RETURN_VAL action must be specified"));
06416     return lower_return_mistore(block, tree, actions);
06417   }
06418 
06419   swn = WN_CreateIntconst(OPC_U4INTCONST, size);
06420   wn  = WN_CreateMstore(WN_offset(tree), pty_idx, 
06421                         WN_COPY_Tree(WN_kid0(tree)),
06422                         WN_COPY_Tree(WN_kid1(tree)), swn);
06423   WN_set_field_id(wn, WN_field_id(tree));
06424   wn  = lower_store(block, wn, actions);
06425 
06426   WN_DELETE_Tree (tree);
06427   return wn;
06428 }
06429 
06430 /*
06431  * See if the given expr is of the form
06432  *   
06433  *   LDID struct
06434  *   EXPR
06435  * ADD
06436  * (this happens for expr like foo->x[i])
06437  *
06438  *  If so, return the type of the struct, ow return 0
06439  */
06440 static TY_IDX struct_addr_ty(WN* tree) {
06441 
06442   if (WN_operator(tree) == OPR_ADD &&
06443       WN_operator(WN_kid0(tree)) == OPR_LDID) {
06444     TY_IDX addr_ty = WN_ty(WN_kid0(tree));
06445     if (TY_kind(addr_ty) == KIND_POINTER &&
06446         TY_kind(TY_pointed(addr_ty)) == KIND_STRUCT) {
06447       return TY_pointed(addr_ty);
06448     }
06449   }
06450   return 0;
06451 }
06452 
06453 static int find_field_from_offset(TY_IDX ty, unsigned int offset) { 
06454   
06455   Is_True(TY_kind(ty) == KIND_STRUCT, ("TY is not a struct", ""));
06456   int cur_field = 1;
06457   FLD_ITER fld_iter = Make_fld_iter(TY_fld(ty));
06458   do {
06459     FLD_HANDLE fld(fld_iter);
06460     if (FLD_ofst(fld) == offset) {
06461       return cur_field;
06462     } 
06463     if (FLD_ofst(fld) > offset) {
06464       fprintf(stderr, "can't find field with exact same offset in find_field_from_offset\n");
06465       return cur_field - 1;
06466     }
06467     TY_IDX fld_ty = FLD_type(fld);
06468     if (TY_kind(fld_ty) == KIND_STRUCT && !is_upcr_ptr(fld_ty) &&
06469         TY_fld(fld_ty) != FLD_HANDLE() && offset < (FLD_ofst(fld) + TY_size(fld_ty)) ) {
06470       return cur_field + find_field_from_offset(fld_ty, offset - FLD_ofst(fld));
06471     }
06472     cur_field++;
06473   } while (!FLD_last_field(fld_iter++));
06474   return -1;
06475 }
06476 
06477 
06478 /* ====================================================================
06479  *
06480  * WN *lower_store(block, WN *tree, LOWER_ACTIONS actions)
06481  *
06482  * Perform lowering (see WN_Lower description) on store statement <tree>,
06483  * returning lowered tree.
06484  *
06485  * ==================================================================== */
06486 
06487 static WN *lower_store(WN *block, WN *tree, LOWER_ACTIONS actions)
06488 {
06489   BOOL kids_lowered = FALSE;    /* becomes TRUE when kids are lowered */
06490 
06491   Is_True(OPCODE_is_store(WN_opcode(tree)),
06492           ("expected store node, not %s", OPCODE_name(WN_opcode(tree))));
06493 
06494   /* If the store is to memory and the expression begins with a TAS, try to
06495    * replace with a store matching the result type of the TAS's expression.
06496    * Doing so may avoid a move from one register set to another.
06497    */
06498   if (Action(LOWER_TO_CG))
06499   {
06500     WN *tas = WN_kid0(tree);
06501     if (   WN_operator(tas) == OPR_TAS
06502         && (!WN_has_sym(tree) || WN_class(tree) != CLASS_PREG))
06503     {
06504       WN *tas_kid0 = WN_kid0(tas);
06505       TYPE_ID tas_kid0_rtype = WN_rtype(tas_kid0);
06506       if (MTYPE_byte_size(WN_rtype(tas)) == MTYPE_byte_size(tas_kid0_rtype)) {
06507         WN_set_desc(tree, tas_kid0_rtype);
06508         WN_kid0(tree) = tas_kid0;
06509         WN_Delete(tas);
06510       }
06511     }
06512   }
06513 
06514   /*
06515    * create any maps that need to be present
06516    */
06517   lower_map(tree, actions);
06518 
06519 
06520   /* Note: We must split constant offsets after lowering complex stores
06521    * and splitting symbol addresses since these may create new offsets
06522    * that need to be split.
06523    */
06524   
06525   switch (WN_operator(tree))
06526   {
06527   case OPR_ISTORE: {
06528     if (WN_StoreIsUnused(WN_kid1(tree)))
06529     {
06530       WN        *eval;
06531 
06532       eval = lower_eval(block, WN_CreateEval(WN_kid0(tree)), actions);
06533 
06534       WN_Delete(tree);
06535 
06536       return eval;
06537     }
06538 
06539     if (Action(LOWER_MLDID_MSTID) && WN_desc(tree) == MTYPE_M)
06540       return lower_mistore(block, tree, actions);
06541 
06542     if (Action(LOWER_BIT_FIELD_ID) && WN_desc(tree) == MTYPE_BS) {
06543       lower_bit_field_id(tree);
06544       if (Action(LOWER_BITS_OP) && WN_operator (tree) == OPR_ISTBITS)
06545         return lower_store_bits (block, tree, actions);
06546     }
06547 
06548     if (Action(LOWER_COMPLEX) && MTYPE_is_complex(WN_desc(tree)))
06549     {
06550       WN        *realstore, *imagstore;
06551       LEAF      realexpN, imagexpN;
06552       WN_OFFSET offset = WN_store_offset(tree);
06553       TYPE_ID   realTY = Mtype_complex_to_real( WN_desc(tree));
06554       {
06555        /*
06556         * create the real/imaginary stores
06557         * load the temporary values into a preg before the store (pv314583)
06558         * as the store may interfere with the expression.
06559         */
06560         WN      *realexp, *imagexp;
06561 
06562         lower_complex_expr(block, WN_kid0(tree), actions, &realexp, &imagexp);
06563         
06564         realexpN = Make_Leaf(block, realexp, realTY);
06565         imagexpN = Make_Leaf(block, imagexp, realTY);
06566       }
06567 
06568       if (Action(LOWER_BASE_INDEX))
06569       {
06570         WN      *base, *index, *addr;
06571         LEAF    indexN;
06572 
06573         base = index=   NULL;
06574         lower_to_base_index(WN_kid1(tree), &base, &index) ;
06575 
06576         base = lower_expr(block, base, actions);
06577         index = lower_expr(block, index, actions);
06578 
06579         indexN = Make_Leaf(block, index, Pointer_type);
06580 
06581         addr = WN_Add(Pointer_type,
06582                       Load_Leaf(indexN),
06583                       lower_copy_tree(base, actions));
06584 
06585         realstore = WN_Istore(realTY,
06586                               offset,
06587                               coerceTY(WN_ty(tree), realTY),
06588                               addr,
06589                               Load_Leaf(realexpN));
06590 
06591         addr = WN_Add(Pointer_type, Load_Leaf(indexN), base);
06592 
06593         imagstore = WN_Istore(realTY,
06594                               coerceOFFSET(tree, realTY, offset),
06595                               coerceTY(WN_ty(tree), realTY),
06596                               addr,
06597                               Load_Leaf(imagexpN));
06598       }
06599       else
06600       {
06601         WN      *addr;
06602         LEAF    addrN;
06603 
06604         addr = lower_expr(block, WN_kid1(tree), actions);
06605         addrN = Make_Leaf(block, addr, Pointer_type);
06606 
06607         realstore =  WN_Istore(realTY,
06608                                offset,
06609                                coerceTY(WN_ty(tree), realTY),
06610                                Load_Leaf(addrN),
06611                                Load_Leaf(realexpN));
06612 
06613         imagstore =  WN_Istore(realTY,
06614                                coerceOFFSET(tree, realTY, offset),
06615                                coerceTY(WN_ty(tree), realTY),
06616                                Load_Leaf(addrN),
06617                                Load_Leaf(imagexpN));
06618       }
06619       realstore = lower_store(block, realstore, actions);
06620       WN_Set_Linenum (realstore, WN_Get_Linenum(tree));
06621       WN_INSERT_BlockLast(block, realstore);
06622 
06623       imagstore = lower_store(block, imagstore, actions);
06624       lower_complex_maps(tree, realstore, imagstore, actions);
06625       WN_Delete(tree);
06626 
06627       return imagstore;
06628     }
06629     else if (Action(LOWER_QUAD) && MTYPE_is_quad(WN_desc(tree)))
06630     {
06631       WN        *hi, *lo, *hipart, *lopart;
06632       TYPE_ID   realTY = MTYPE_F8;
06633       WN_OFFSET offset = WN_load_offset(tree);
06634 
06635       lower_quad_expr(block, WN_kid0(tree), actions, &hi, &lo);
06636 
06637       if (Action(LOWER_BASE_INDEX))
06638       {
06639         WN      *addr, *base, *index;
06640         LEAF    indexN;
06641 
06642         base = index = NULL;
06643         lower_to_base_index(WN_kid1(tree), &base, &index) ;
06644 
06645         base  = lower_expr(block, base, actions);
06646         index = lower_expr(block, index, actions);
06647 
06648         indexN = Make_Leaf(block, index, Pointer_type);
06649 
06650         addr   = WN_Add(Pointer_type,
06651                         Load_Leaf(indexN),
06652                         lower_copy_tree(base, actions));
06653 
06654         hipart = WN_Istore(realTY,
06655                            offset,
06656                            coerceTY(WN_ty(tree), realTY),
06657                            addr,
06658                            hi);
06659 
06660         addr   = WN_Add(Pointer_type, Load_Leaf(indexN), base);
06661 
06662         lopart = WN_Istore(realTY,
06663                            coerceOFFSET(tree, realTY, offset),
06664                            coerceTY(WN_ty(tree), realTY),
06665                            addr,
06666                            lo);
06667       }
06668       else
06669       {
06670         WN      *addr;
06671         LEAF    addrN;
06672 
06673         addr   = lower_expr(block, WN_kid1(tree), actions);
06674 
06675         addrN  = Make_Leaf(block, addr, Pointer_type);
06676 
06677         hipart = WN_Istore(realTY,
06678                            offset,
06679                            coerceTY(WN_ty(tree), realTY),
06680                            Load_Leaf(addrN),
06681                            hi);
06682 
06683         lopart = WN_Istore(realTY,
06684                            coerceOFFSET(tree, realTY, offset),
06685                            coerceTY(WN_ty(tree), realTY),
06686                            Load_Leaf(addrN),
06687                            lo);
06688       }
06689       hipart = lower_store(block, hipart, actions);
06690       WN_Set_Linenum (hipart, WN_Get_Linenum(tree));
06691       WN_INSERT_BlockLast(block, hipart);
06692 
06693       lopart = lower_store(block, lopart, actions);
06694       lower_quad_maps(tree, hipart, lopart, actions);
06695       WN_Delete(tree);
06696       return lopart;
06697     }
06698     else if (Action(LOWER_SPLIT_CONST_OFFSETS))
06699     {
06700       /*
06701        * Split
06702        *       ADDR
06703        *     ISTORE (offset>16bits)
06704        * into
06705        *         ADDR
06706        *         CONST (hi)
06707        *       ADD
06708        *     ISTORE (lo)
06709        */
06710       WN_OFFSET offset = WN_store_offset(tree);
06711 
06712       if (mem_offset_must_be_split(offset))
06713       {
06714         WN_kid1(tree) = WN_Add(Pointer_type, WN_kid1(tree),
06715                                WN_Intconst(Pointer_type,
06716                                            mem_offset_hi(offset)));
06717         WN_store_offset(tree) = mem_offset_lo(offset);
06718       }
06719     }
06720     else {
06721      /*
06722       * Split
06723       *       LDA  (c1) <sym> 
06724       *     ISTORE (c2)
06725       * into
06726       *       LDA  (0) <sym>
06727       *     ISTORE (c1+c2)
06728       *
06729       * provided sym is not a PREG.
06730       */
06731       WN  *addr_kid = WN_kid1(tree);
06732 
06733       if (foldLdaOffset(addr_kid, WN_store_offset(tree)))
06734       {
06735         WN_store_offset(tree) += WN_lda_offset(addr_kid);
06736         WN_lda_offset(addr_kid) = 0;
06737       }
06738      /*
06739       * Fold
06740       *         EXPR
06741       *         CONST (c1)
06742       *       ADD
06743       *     ISTORE c2
06744       * Into
06745       *       EXPR
06746       *     ISTORE c1+c2
06747       */
06748       if (WN_operator_is(addr_kid, OPR_ADD) &&
06749           foldConstOffset(WN_kid1(addr_kid), WN_store_offset(tree)))
06750       {
06751         WN_store_offset(tree) += WN_const_val(WN_kid1(addr_kid));
06752         WN_kid1(tree) = WN_kid0(addr_kid);
06753         TY_IDX obj_ty = struct_addr_ty(WN_kid1(tree));
06754         if (obj_ty != 0) {
06755           //WEI: let's fix the offset here
06756           int field_id = find_field_from_offset(obj_ty, WN_store_offset(tree));
06757           WN_store_offset(tree) = Adjust_Field_Offset(obj_ty, field_id);
06758           //cout << "STORE OFFSET: " <<  WN_store_offset(tree) << endl;
06759         }
06760         WN_Delete(WN_kid1(addr_kid));
06761         WN_Delete(addr_kid);
06762       }
06763     } 
06764     if ( Action(LOWER_UPC_TO_INTR) ) {
06765  
06766       TY_IDX idx = WN_ty(tree);
06767       TY_IDX dst_idx = 0;
06768       if(Type_Is_Shared_Ptr(idx)) {
06769         TY_IDX src_idx = WN_ty(WN_kid1(tree));
06770         WN *ist;
06771         BOOL do_arith = TRUE;
06772         BOOL is_field = FALSE;
06773         WN *offt = 0;
06774 
06775         SPTR_ACCUMULATION_STATE saved_acc_state = sptr_accumulation_state;
06776         sptr_accumulation_state = ACCUMULATION;
06777         sptr_off_accumulation_stack.push(CXX_NEW(SPTR_OFFSET_TERM_STACK, Malloc_Mem_Pool));
06778         SPTR_OFFSET_TERM_STACK *term_stack = sptr_off_accumulation_stack.top();
06779         WN *kid1 = WN_kid1(tree);
06780         
06781         if((WN_operator(kid1) == OPR_LDID && !WN_offset(tree)) ||
06782            WN_operator(kid1) == OPR_ARRAY ||
06783            // the optimizer creates LDA(off, array) and the pointer arith
06784            // is performed when lowering the LDA
06785           ( WN_operator(kid1) == OPR_TAS && WN_operator(WN_kid0(kid1)) == OPR_LDA &&
06786            TY_kind(TY_pointed(WN_ty(WN_kid0(kid1)))) == KIND_ARRAY) )
06787           do_arith = FALSE;
06788         
06789         if(WN_offset(tree)) {
06790           offt = WN_Intconst(Integer_type, 
06791                              WN_field_id(tree) > 1 ? Adjust_Field_Offset(TY_pointed(WN_ty(tree)), WN_field_id(tree)) : WN_offset(tree));
06792           WN_offset(tree) = 0;
06793         }
06794 
06795         dst_idx = (OPERATOR_is_load(WN_operator(WN_kid0(tree)))  || 
06796                    WN_operator(WN_kid0(tree)) == OPR_TAS) ? 
06797                    WN_ty(WN_kid0(tree)) : dst_idx;
06798         sptr_accumulation_state = NO_ACCUMULATION;
06799         WN_kid0(tree) = lower_expr(block, WN_kid0(tree), actions);
06800         
06801         sptr_accumulation_state = ACCUMULATION;
06802         WN_kid1(tree) = lower_expr(block, WN_kid1(tree), actions);      
06803         
06804 
06805         INTRINSIC iop;
06806         if(src_idx && dst_idx &&
06807            Type_Is_Shared_Ptr(src_idx, TRUE) && 
06808            Type_Is_Shared_Ptr(dst_idx, TRUE) &&
06809            Need_StoP_Cvt(dst_idx, src_idx, &iop)) {
06810           WN_kid0(tree) = WN_Create_StoP_Cvt(WN_kid0(tree), iop);
06811         }
06812         
06813         if(WN_operator(WN_kid1(tree)) == OPR_TAS) {
06814           dst_idx =  WN_ty(WN_kid1(tree));
06815           WN_set_ty(tree, dst_idx);
06816           WN_kid1(tree) = Strip_TAS(WN_kid1(tree));
06817         } else 
06818           dst_idx = WN_ty(tree);
06819         
06820         //fprintf(stderr, "Store after lowering : kid0\n");
06821         //fdump_tree(stderr,WN_kid0(tree));
06822         //fprintf(stderr, "Store after lowering : kid1\n");
06823         //fdump_tree(stderr,WN_kid1(tree));     
06824 
06825         if (do_arith) {
06826           ist = Combine_Offset_Terms(*term_stack);
06827           if (WN_operator(WN_kid1(tree)) == OPR_LDID) {
06828             src_idx = ST_type(WN_st(WN_kid1(tree)));
06829             is_field = WN_field_id(tree)-1;
06830           } else if (WN_operator(WN_kid1(tree)) == OPR_COMMA) {
06831             Is_True(src_idx, ("",""));
06832           } else 
06833             Is_True(src_idx,("",""));
06834             
06835           UINT esize = Get_Type_Inner_Size(idx);
06836           //for accesses to fields of shared structs, dst_idx = shared [] char
06837           // and the ptr arithmetic needs to have the elem size 1;
06838           if(dst_idx && Type_Is_Shared_Ptr(dst_idx, TRUE) && 
06839              TY_size(TY_pointed(dst_idx)) == 1 && Get_Type_Block_Size(dst_idx) == 0) {
06840             Is_True(Get_Type_Block_Size(idx) == 0, ("",""));
06841             esize = 1;
06842           } //how the heck can I tell the difference between shared struct { shared int *p ..}
06843             // and shared struct { int *p ..}
06844           if(TY_kind(idx) == KIND_POINTER && TY_is_shared(TY_pointed(idx)) && 
06845              TY_kind(TY_pointed(idx)) == KIND_POINTER)
06846             esize = TY_size(TY_To_Sptr_Idx(idx));
06847 
06848           if(ist && TY_kind(dst_idx) == KIND_POINTER  &&
06849              Types_Are_Equiv(/*TY_pointed(dst_idx)*/ dst_idx, src_idx) /*&& !is_field */) {
06850             WN_kid1(tree)  = WN_Create_Shared_Ptr_Arithmetic (WN_kid1(tree), ist, OPR_ADD,
06851                                                               esize,
06852                                                               Get_Type_Block_Size(idx),
06853                                                               Get_Type_Block_Size(idx) <= 1);
06854             
06855             if(offt) {
06856               ist = offt;
06857             } else 
06858               do_arith = FALSE;
06859             
06860           } else if(offt)
06861             ist = offt;
06862         } 
06863 
06864         sptr_accumulation_state = saved_acc_state;
06865         sptr_off_accumulation_stack.pop();
06866         CXX_DELETE(term_stack, Malloc_Mem_Pool);
06867         
06868         if(!ist)
06869           do_arith = FALSE;
06870         ist = WN_Create_Shared_Store (tree, FALSE, 0, do_arith /*True*/, ist);
06871         WN_Delete(tree);
06872         return ist;
06873       } else if (WN_Type_Is_Shared_Ptr(WN_kid0(tree)) || WN_operator(WN_kid0(tree)) == OPR_TAS)
06874         {
06875           
06876           WN *kid0 = lower_expr(block,
06877                                 WN_operator(WN_kid0(tree)) == OPR_TAS ? WN_kid0(WN_kid0(tree)) :
06878                                 WN_kid0(tree),
06879                                 actions);
06880           if (TY_kind(WN_object_ty(WN_kid0(tree))) == KIND_SCALAR)
06881             WN_kid0(tree) = kid0;
06882           else {
06883             if(OPERATOR_is_load(WN_operator(WN_kid0(tree))) && WN_field_id(WN_kid0(tree)))
06884               WN_kid0(tree) = kid0;
06885             else {
06886               idx = WN_field_id(tree) ?  
06887                 get_field_type(TY_pointed(WN_ty(tree)), WN_field_id(tree)) :
06888                 WN_ty(tree) ;
06889               if(!Type_Is_Shared_Ptr(idx)) {
06890                 if(!(TY_kind(idx) == KIND_POINTER && Type_Is_Shared_Ptr(TY_pointed(idx), TRUE)))
06891                   //test to see that we do not assign a shared ptr into a deref of a
06892                   //local ptr to shared ptr
06893                   WN_kid0(tree) = WN_Convert_Shared_To_Local(kid0, WN_ty(tree), 0);
06894                 else WN_kid0(tree) = kid0;
06895               } else  if(WN_field_id(tree) && !Type_Is_Shared_Ptr(WN_ty(tree)) &&  
06896                        Type_Is_Shared_Ptr(idx, TRUE)){
06897                 //this is the case where we store into a field of a local struct, the type of
06898                 //of the field being a sptr
06899                 dst_idx = TY_To_Sptr_Idx(idx);
06900                 INTRINSIC iop = INTRINSIC_LAST;
06901                 if((Type_Is_Shared_Ptr(WN_ty(kid0)) &&
06902                     Need_StoP_Cvt(WN_ty(kid0), idx, &iop) ) ||
06903                    Need_StoP_Cvt(WN_ty(WN_kid0(tree)), idx, &iop))
06904                   kid0 = WN_Create_StoP_Cvt(Strip_TAS(kid0), iop);
06905                 
06906                 if(TY_mtype(dst_idx) == MTYPE_M) {
06907                   WN_set_rtype(tree, MTYPE_V);
06908                   WN_set_desc(tree, MTYPE_M);
06909                   WN_store_offset(tree) = Adjust_Field_Offset(TY_pointed(WN_ty(tree)),
06910                                                                WN_field_id(tree));
06911                   // WN_set_ty(tree, Make_Pointer_Type(dst_idx));
06912                  
06913                   WN_kid0(tree) = kid0;
06914                 }            
06915               } 
06916             }
06917           }
06918           WN_kid1(tree) = lower_expr(block, WN_kid1(tree), actions);
06919           return tree;
06920         } else if(WN_field_id(tree) > 1) 
06921           WN_store_offset(tree) = Adjust_Field_Offset(TY_pointed(WN_ty(tree)),
06922                                                                WN_field_id(tree));
06923     }
06924     break;
06925   } 
06926   case OPR_STID:
06927     {
06928       PREG_NUM last_preg = Get_Preg_Num (PREG_Table_Size(CURRENT_SYMTAB));
06929 
06930       if ((WN_class(tree) == CLASS_PREG) &&
06931           (WN_store_offset(tree) > last_preg))
06932       {
06933           DevWarn("lower_store() pregno %d > SYMTAB_last_preg(%d)",
06934                   WN_load_offset(tree), last_preg);
06935       }
06936     }
06937 
06938     if (WN_StoreIsUnused(tree))
06939     {
06940       WN        *eval;
06941 
06942       eval = lower_eval(block, WN_CreateEval(WN_kid0(tree)), actions);
06943 
06944       WN_Delete(tree);
06945 
06946       return eval;
06947     }
06948 
06949     if (Action(LOWER_MLDID_MSTID) && WN_desc(tree) == MTYPE_M)
06950       return lower_mstid(block, tree, actions);
06951 
06952     if (Action(LOWER_MLDID_MSTID) && WN_Type_Is_Shared_Ptr(tree) && 
06953         TY_mtype(TY_To_Sptr_Idx(WN_ty(tree))) == MTYPE_M && 
06954         WN_operator(WN_kid0(tree)) == OPR_LDID && WN_st(WN_kid0(tree)) == Return_Val_Preg) 
06955       return lower_mstid(block, tree, actions);
06956     
06957     if (Action(LOWER_BIT_FIELD_ID) && WN_desc(tree) == MTYPE_BS) {
06958       lower_bit_field_id(tree);
06959       if (Action(LOWER_BITS_OP) && WN_operator (tree) == OPR_STBITS)
06960         return lower_store_bits (block, tree, actions);
06961     }
06962 
06963     if (Action(LOWER_COMPLEX) && MTYPE_is_complex(WN_desc(tree)))
06964     {
06965       WN        *realexp, *imagexp;
06966       TYPE_ID   realTY;
06967 
06968       realTY =  Mtype_complex_to_real( WN_desc(tree));
06969       lower_complex_expr(block, WN_kid0(tree), actions, &realexp, &imagexp);
06970 
06971      /*
06972       * create the real/imaginary stores
06973       * load the temporary values into a preg before the store (pv314583)
06974       * as the store may interfere with the expression.
06975       */
06976       {
06977         WN_OFFSET       offset = WN_store_offset(tree);
06978         PREG_NUM        realexpN, imagexpN;
06979         WN              *wn;
06980         WN *realexp_copy,*imagexp_copy;
06981 
06982         if (WN_operator(realexp) == OPR_CONST) {
06983            realexp_copy = realexp;
06984         } else {
06985            realexpN = AssignExpr(block, realexp, realTY);
06986            realexp_copy = WN_LdidPreg(realTY, realexpN);
06987         }
06988 
06989         if (WN_operator(imagexp) == OPR_CONST) {
06990            imagexp_copy = imagexp;
06991         } else {
06992            imagexpN = AssignExpr(block, imagexp, realTY);
06993            imagexp_copy = WN_LdidPreg(realTY, imagexpN);
06994         }
06995 
06996         wn = WN_Stid(realTY,
06997                      offset, 
06998                      coerceST(WN_st(tree), realTY),
06999                      MTYPE_To_TY(realTY),
07000                      realexp_copy);
07001 
07002         realexp = lower_store(block, wn, actions);
07003         WN_Set_Linenum (realexp, WN_Get_Linenum(tree));
07004         WN_INSERT_BlockLast(block, realexp);
07005 
07006         wn = WN_Stid(realTY,
07007                      coerceOFFSET(tree, realTY, offset),
07008                      coerceST(WN_st(tree), realTY),
07009                      MTYPE_To_TY(realTY),
07010                      imagexp_copy);
07011 
07012         imagexp = lower_store(block, wn, actions);
07013 
07014         lower_complex_maps(tree, realexp, imagexp, actions);
07015 
07016         WN_Delete(tree);
07017 
07018         return imagexp;
07019       }
07020     }
07021 
07022     else if (Action(LOWER_QUAD) && MTYPE_is_quad(WN_desc(tree)))
07023     {
07024       WN_OFFSET offset = WN_store_offset(tree);
07025       WN        *hiexp, *loexp, *wn, *hipart, *lopart;
07026       TYPE_ID   realTY = MTYPE_F8;
07027 
07028       lower_quad_expr(block, WN_kid0(tree), actions, &hiexp, &loexp);
07029 
07030       /*
07031        * create the hi/lo stores
07032        */
07033       wn = WN_Stid(realTY, 
07034                    offset, 
07035                    coerceST(WN_st(tree), realTY),
07036                    MTYPE_To_TY(realTY), hiexp);
07037 
07038       hipart = lower_store(block, wn, actions);
07039       WN_Set_Linenum (hipart, WN_Get_Linenum(tree));
07040       WN_INSERT_BlockLast(block, hipart);
07041 
07042       wn = WN_Stid(realTY,
07043                    coerceOFFSET(tree, realTY, offset),
07044                    coerceST(WN_st(tree), realTY),
07045                    MTYPE_To_TY(realTY), loexp);
07046       lopart = lower_store(block, wn, actions);
07047 
07048       lower_quad_maps(tree, hipart, lopart, actions);
07049 
07050       WN_Delete(tree);
07051 
07052       return lopart;
07053     }
07054 
07055     if (Action(LOWER_SPLIT_SYM_ADDRS))
07056     {
07057      /*
07058       * Convert   (STID (offset) <sym>) into
07059       *       LDA (0) <base> 
07060       *     ISTORE (offs+ofst)          
07061       */
07062       WN  *istore;
07063 
07064       istore =  lower_split_sym_addrs(tree, WN_store_offset(tree), actions);
07065       if (istore)
07066       {
07067         return lower_store(block, istore, actions);
07068       }
07069     }
07070 
07071     if ( Action(LOWER_FORMAL_REF) && WN_class(tree) == CLASS_VAR)
07072     {
07073       WN  *istore;
07074 
07075       istore =  lower_formal_ref(tree, WN_store_offset(tree),
07076                                  WN_st(tree), actions);
07077       if (istore)
07078       {
07079         return lower_store(block, istore, actions);
07080       }
07081     }
07082 
07083     if ( Action(LOWER_UPLEVEL))
07084     {
07085      ST *sym = WN_st(tree);
07086 
07087       if (ST_is_uplevelTemp(sym))
07088       {
07089         WN         *istore;
07090 
07091         istore = lower_uplevel_reference(tree, WN_store_offset(tree), actions);
07092         return lower_store(block, istore, actions);
07093       }
07094     }
07095     
07096     if(Action(LOWER_UPC_TO_INTR)){
07097       INTRINSIC iop = INTRINSIC_LAST;
07098       if( TY_is_shared(ST_type(WN_st(tree)))) {
07099         WN_kid0(tree)  = lower_expr(block, WN_kid0(tree), actions);
07100         if(WN_operator(WN_kid0(tree)) == OPR_COMMA)
07101           WN_kid0(tree) = Spill_Shared_Load(WN_kid0(tree));
07102         TY_IDX rhs_idx = WN_ty(WN_kid0(tree));
07103         bool both_shared = false;
07104         //      if (rhs_idx == shared_ptr_idx || rhs_idx == pshared_ptr_idx) {
07105         //WEI: in this case both sides are shared, and we want to do a memcpy
07106         //       both_shared = true;
07107         //      }
07108         WN *ical = WN_Create_Shared_Store(tree, both_shared);
07109         WN_Delete(tree);
07110         kids_lowered = TRUE;
07111         return ical;
07112       } else if (TY_kind(WN_ty(tree)) == KIND_POINTER && TY_is_shared(TY_pointed(WN_ty(tree))) ||
07113                  TY_kind(WN_ty(tree)) == KIND_ARRAY && TY_is_shared(TY_etype(WN_ty(tree))) ) {
07114         //WEI: set to correct type
07115         TY_IDX base_idx = TY_kind(WN_ty(tree)) == KIND_POINTER ? TY_pointed(WN_ty(tree)) : TY_etype(WN_ty(tree));
07116         TY_IDX real_ty = TY_is_pshared(base_idx) ? pshared_ptr_idx : shared_ptr_idx;
07117         
07118         WN *kid0 = WN_kid0(tree);
07119         //check here for the case where NULL is assigned to a shared pointer.
07120         if(TY_kind(WN_ty(tree)) == KIND_POINTER && WN_operator(kid0) == OPR_TAS &&
07121            WN_operator(WN_kid0(kid0)) == OPR_INTCONST) {
07122           WN_kid0(tree) = kid0 = Strip_TAS(kid0);
07123           Is_True(WN_const_val(kid0) == 0, ("Setting a shared ptr to a constant different from NULL",""));
07124           return WN_SetNull_Sptr(tree);
07125         } else if(Type_Is_Shared_Ptr(WN_ty(kid0)) && Need_StoP_Cvt(WN_ty(kid0), WN_ty(tree), &iop)) {
07126           kids_lowered = TRUE;
07127           WN_kid0(tree)  = WN_Create_StoP_Cvt(lower_expr(block, kid0,actions), iop);
07128         } 
07129 
07130         WN_set_ty(tree, real_ty);
07131         WN_set_desc (tree, TY_mtype(real_ty));
07132         
07133       } else if (WN_Type_Is_Shared_Ptr(WN_kid0(tree)) || WN_operator(WN_kid0(tree)) == OPR_TAS)
07134         {
07135           TY_IDX src_idx = 0;
07136           WN *kid0 = WN_kid0(tree);
07137           if(WN_operator(kid0) == OPR_TAS || OPERATOR_is_load(WN_operator(kid0))) {
07138             src_idx = WN_ty(kid0);
07139             if(OPERATOR_is_load(WN_operator(kid0)) && WN_field_id(kid0)) {
07140               src_idx = Get_Field_Type(src_idx, WN_field_id(kid0));
07141             } 
07142           }
07143           kid0 = lower_expr(block,
07144                             WN_operator(WN_kid0(tree)) == OPR_TAS ? WN_kid0(WN_kid0(tree)) :
07145                             WN_kid0(tree),
07146                             actions);
07147           if (TY_kind(WN_object_ty(WN_kid0(tree))) == KIND_SCALAR)
07148             WN_kid0(tree) = kid0;
07149           else {
07150             if(OPERATOR_is_load(WN_operator(WN_kid0(tree))) && WN_field_id(WN_kid0(tree)))
07151               WN_kid0(tree) = kid0;
07152             else {
07153              //  fdump_tree(stderr, tree);
07154               TY_IDX  idx = WN_field_id(tree) ?  
07155                 get_field_type(WN_ty(tree), WN_field_id(tree)) :
07156                 WN_ty(tree) ;
07157               if(!Type_Is_Shared_Ptr(idx)) {
07158                 if(src_idx && !TY_is_shared(src_idx))
07159                   WN_kid0(tree) = WN_Convert_Shared_To_Local(kid0, WN_ty(tree), 0);
07160                 else
07161                   WN_kid0(tree) = kid0;
07162               }
07163               else  if(WN_field_id(tree) && !Type_Is_Shared_Ptr(WN_ty(tree)) &&  
07164                        Type_Is_Shared_Ptr(idx, TRUE)){
07165                 //this is the case where we store into a field of a local struct, the type of
07166                 //of the field being a sptr
07167                 //      Ty_Table[WN_ty(tree)].Print(stderr);
07168                 //      Ty_Table[WN_load_addr_ty(tree)].Print(stderr);
07169                 TY_IDX dst_idx = TY_To_Sptr_Idx(idx);
07170                 if(TY_mtype(dst_idx) == MTYPE_M) {
07171                   WN_set_rtype(tree, MTYPE_V);
07172                   WN_set_desc(tree, MTYPE_M);
07173                   WN_store_offset(tree) = Adjust_Field_Offset(WN_ty(tree),
07174                                                                WN_field_id(tree));
07175                  //  WN_set_ty(tree, dst_idx);
07176                   WN_kid0(tree) = kid0;
07177                 }            
07178               }
07179             }
07180 
07181               // WN_kid0(tree) = WN_Convert_Shared_To_Local(kid0, WN_ty(tree), 0);
07182           }
07183           return tree;
07184         } else if(WN_field_id(tree) > 1) {
07185           WN_store_offset(tree) = Adjust_Field_Offset(WN_ty(tree), WN_field_id(tree));
07186         } else if (WN_operator(WN_kid0(tree)) == OPR_ADD) {
07187           //WEI: We may need to fix up the offset 
07188           WN* offset = WN_kid1(WN_kid0(tree));
07189           if (WN_operator(offset) == OPR_INTCONST) {
07190             TY_IDX obj_ty = struct_addr_ty(WN_kid0(WN_kid0(tree)));
07191             if (obj_ty != 0) {
07192               int field_id = find_field_from_offset(obj_ty, WN_const_val(offset));
07193               int real_ofst =  Adjust_Field_Offset(obj_ty, field_id);
07194               WN_kid1(WN_kid0(tree)) = WN_CreateIntconst(OPR_INTCONST, Pointer_Mtype, MTYPE_V, real_ofst); 
07195               //cout << "STID OFFSET: " << real_ofst << endl;
07196             }
07197           }
07198         }
07199     }
07200     
07201     break; // OPR_STID
07202 
07203   case OPR_ISTBITS:
07204   case OPR_STBITS:
07205     if (Action(LOWER_BITS_OP))
07206       return lower_store_bits (block, tree, actions);
07207     break;
07208 
07209   case OPR_MSTORE:
07210     {
07211       WN *rhs = WN_kid0(tree);
07212       Is_True(!(WN_opcode(rhs) == OPC_MMLDID && WN_st(rhs) == Return_Val_Preg),
07213               ("MMLDID of Return_Val_Preg cannot be rhs of MSTORE"));
07214     }
07215     
07216     if (Action(LOWER_UPC_TO_INTR)) {
07217       if((WN_ty(WN_kid1(tree)) && TY_is_shared(TY_pointed(WN_ty(WN_kid1(tree))))) ||  
07218          (WN_ty(WN_kid0(tree)) && TY_is_shared(TY_pointed(WN_ty(WN_kid0(tree))))) ) {
07219         // fprintf(stderr, "MSTORE KID0 ");
07220 //      fdump_tree(stderr, WN_kid0(tree));
07221 //      fprintf(stderr, "MSTORE KID1 ");
07222 //      fdump_tree(stderr, WN_kid1(tree));
07223 //      fprintf(stderr, "MSTORE KID2 ");
07224 //      fdump_tree(stderr, WN_kid2(tree));
07225 //      fprintf(stderr, "=================\n");
07226         
07227         
07228         BOOL src_shared = FALSE;
07229         if (TY_kind(WN_ty(WN_kid0(tree))) == KIND_POINTER && 
07230             TY_is_shared(TY_pointed(WN_ty(WN_kid0(tree)))))
07231           src_shared = TRUE;
07232         WN_OFFSET ld_xtra_oft = 0;
07233         WN_OFFSET st_xtra_oft = 0;
07234         TY_IDX dest_ty = 0;
07235         TY_IDX orig_ty = WN_ty(WN_kid1(tree));
07236         //short circuit structure copies
07237         // s1 = s2;
07238         if (WN_operator(WN_kid0(tree)) == OPR_MLOAD ) {
07239           WN *kid0 = WN_kid0(tree);
07240           if(OPCODE_is_load(WN_opcode(WN_kid0(kid0))) || 
07241              OPCODE_is_store(WN_opcode(WN_kid0(kid0))))
07242             ld_xtra_oft = WN_offset(WN_kid0(kid0));
07243           // extract the type of the field, if any
07244           if (WN_field_id(kid0)) {
07245             UINT tmp_field_id = 0;
07246             dest_ty = FLD_type(FLD_get_to_field(TY_pointed(WN_object_ty(kid0)), 
07247                                                 WN_field_id(kid0), tmp_field_id));
07248           } else
07249             dest_ty = TY_pointed(WN_ty(kid0));
07250           WN_kid0(tree) = lower_expr(block, WN_kid0(WN_kid0(tree)), actions);
07251         } else
07252           WN_kid0(tree) = lower_expr(block, WN_kid0(tree), actions);
07253         
07254         st_xtra_oft = WN_offset(WN_kid1(tree));
07255         WN_kid1(tree) = lower_expr(block, WN_kid1(tree), actions);
07256         WN_kid2(tree) = lower_expr(block, WN_kid2(tree), actions);
07257         if (src_shared && !Type_Is_Shared_Ptr(orig_ty)) {
07258           //non-shared = shared;
07259           return WN_Create_Shared_Load(WN_kid0(tree), WN_kid1(tree), 
07260                                        TRUE, ld_xtra_oft);
07261         } else  if (!src_shared) {
07262           return WN_Create_Shared_Store(tree, src_shared, st_xtra_oft);
07263         } else {
07264           // shared struct = shared struct
07265           // fdump_tree(stderr,WN_kid0(tree));
07266           ST *spill_st = Gen_Temp_Symbol(dest_ty, (char*) ".Mspill");
07267           WN *dest = WN_Lda(Pointer_Mtype, 0, spill_st, 0);
07268           dest  = WN_Create_Shared_Load(WN_kid0(tree), dest, TRUE, 0, dest_ty);
07269           WN *wn0 = WN_CreateBlock();
07270           WN_INSERT_BlockLast(wn0, dest);
07271           wn0 = WN_CreateComma(OPR_COMMA, MTYPE_M, MTYPE_V, wn0, 
07272                                WN_Ldid(MTYPE_M, 0, spill_st, ST_type(spill_st)));
07273           WN_kid0(tree) = wn0;
07274           return WN_Create_Shared_Store(tree, FALSE, st_xtra_oft);
07275                                           
07276         }
07277       }
07278     } else if(Action(LOWER_UPC_MFIELD)) {
07279       TY_IDX idx = TY_pointed(WN_ty(tree));
07280       WN *kid = WN_kid2(tree);
07281       if(WN_operator(kid) == OPR_INTCONST)
07282         WN_const_val(kid) = 
07283           Adjusted_Type_Size(WN_field_id(tree) == 0 ? idx : Get_Field_Type(idx, WN_field_id(tree)));
07284       if(WN_field_id(tree) && WN_offset(tree))
07285         WN_offset(tree) = Adjust_Field_Offset(idx, WN_field_id(tree));
07286     }
07287 
07288     if (Align_Object)
07289     {
07290       INT16 i;
07291       for (i = 0; i < WN_kid_count(tree); i++)
07292         WN_kid(tree,i) = lower_expr(block, WN_kid(tree,i), actions);
07293 
07294       tree = improve_Malignment(tree, WN_kid1(tree), WN_kid2(tree),
07295                                 WN_store_offset(tree));
07296     }
07297 
07298     if (Action(LOWER_MSTORE))
07299     {
07300       if (WN_StoreIsUnused(WN_kid1(tree)))
07301       {
07302         WN      *eval;
07303 
07304         eval = lower_eval(block, WN_CreateEval(WN_kid0(tree)), actions);
07305 
07306         WN_Delete(tree);
07307 
07308         return eval;
07309       }
07310      /*
07311       *  rewrite
07312       *         MSTORE (MCSELECT (expr, MLOAD, MLOAD)
07313       *  into
07314       *         MSTORE (MLOAD (CSELECT expr, MLOAD, MLOAD), size)
07315       */
07316       if (WN_opcode(WN_kid0(tree)) == OPC_MCSELECT)
07317       {
07318         WN      *select, *expr, *mload0, *mload1, *cselect;
07319 
07320         select = WN_kid0(tree);
07321         expr = WN_kid0(select);
07322         mload0 = WN_kid1(select);
07323         mload1 = WN_kid2(select);
07324 
07325         Is_True(WN_operator_is(mload0, OPR_MLOAD),
07326                 ("unexpected MSTORE (MCSELECT) pattern"));
07327         Is_True(WN_operator_is(mload1, OPR_MLOAD),
07328                 ("unexpected MSTORE (MCSELECT) pattern"));
07329 
07330         cselect = WN_Cselect(Pointer_type, expr, WN_kid0(mload0),
07331                              WN_kid0(mload1));
07332         WN_kid0(mload0) = cselect;
07333         WN_kid0(tree) = mload0;
07334       }
07335       tree = lower_mstore(block, tree, actions);
07336       kids_lowered = TRUE;
07337     }
07338     
07339     
07340     
07341     break; /* MSTORE */
07342 
07343   }
07344   
07345   /* Lower kids if not done already. */
07346   if (! kids_lowered)
07347   {
07348     INT16 i;
07349     for (i = 0; i < WN_kid_count(tree); i++)
07350       WN_kid(tree,i) = lower_expr(block, WN_kid(tree,i), actions);
07351   }
07352 
07353   return tree;
07354 }
07355 
07356 
07357 
07358 
07359 /* ====================================================================
07360  *
07361  * WN *lower_eval(WN *block, WN *tree, LOWER_ACTIONS actions)
07362  *
07363  * Perform lowering (see WN_Lower description) on eval statement <tree>,
07364  * returning lowered tree.
07365  *
07366  * ==================================================================== */
07367 
07368 static WN *lower_eval(WN *block, WN *tree, LOWER_ACTIONS actions)
07369 {
07370   WN    *child = WN_kid0(tree);
07371 
07372   Is_True(WN_opcode(tree) == OPC_EVAL,
07373           ("expected EVAL node, not %s", OPCODE_name(WN_opcode(tree))));
07374 
07375   if (Action(LOWER_COMPLEX) && MTYPE_is_complex(WN_rtype(child)))
07376   {
07377     WN  *realexp, *imagexp, *eval;
07378 
07379     lower_complex_expr(block, child, actions, &realexp, &imagexp);
07380 
07381     realexp = lower_expr(block, realexp, actions);
07382     eval = WN_CreateEval(realexp);
07383     WN_INSERT_BlockLast(block, eval);
07384 
07385     child = imagexp;
07386   }
07387   else if (Action(LOWER_QUAD) && MTYPE_is_quad(WN_rtype(child)))
07388   {
07389     WN  *hi, *lo, *eval;
07390 
07391     lower_quad_expr(block, child, actions, &hi, &lo);
07392 
07393     hi = lower_expr(block, hi, actions);
07394     eval = WN_CreateEval(hi);
07395     WN_INSERT_BlockLast(block, eval);
07396 
07397     child = lo;
07398   }
07399   else if (Action(LOWER_MSTORE) && WN_operator_is(child, OPR_MLOAD))
07400   {
07401     TY_IDX mloadTY = TY_pointed(Ty_Table[WN_ty(child)]);
07402 
07403     if (TY_is_volatile(mloadTY))
07404     {
07405       DevWarn("eval of volatile (mload) seen. I hoped to never see this");
07406     }
07407     else if (Action(LOWER_TO_CG) && traceWoptFinishedOpt)
07408     {
07409       DevWarn("eval of (mload) processed (wopt should have removed this)");
07410     }
07411     block = lower_mload(block, child, actions);
07412     return block;
07413   }
07414 
07415   {
07416     WN  *eval;
07417 
07418     child = lower_expr(block, child, actions);
07419     eval = WN_CreateEval(child);
07420     WN_Delete(tree);
07421 
07422     return eval;
07423   }
07424   
07425 }
07426 
07427 
07428 
07429 static INT32
07430 calculateLoadStore(INT64 size, INT64 offset, TYPE_ID quantum, WN *src)
07431 {
07432   INT32 n = (size-offset) / MTYPE_RegisterSize(quantum);
07433 
07434   return WN_operator_is(src, OPR_INTCONST) ? n : 2*n;
07435 }
07436 
07437 /* ====================================================================
07438  *
07439  * static MSTORE_ACTIONS GenerateMstoreAction(WN *size, INT32 offset, 
07440  * TYPE_ID quantum, WN *expr)
07441  * 
07442  * Generate loop/inline or memory intrinsic code base on size and expr
07443  * The number of moves is relative to the quantum.
07444  * Acount for ld/st based on whether expr is constant
07445  *
07446  * for size nonconstant
07447  *      generate loop 
07448  *      we could generate a call BTW, but based on what criteria ? 
07449  *
07450  * for size constant
07451  *      nMoves >= MinStructCopyMemIntrSize
07452  *              generate intrinsic based on expr
07453  *              special case for memset as the expr must be a char.
07454  *              this means the expr must be same in all n bytes
07455  *      nMoves >= MinStructCopyLoopSize
07456  *              generate loop code
07457  *      else generate aggregate moves
07458  * 
07459 
07460  * ==================================================================== */
07461 static MSTORE_ACTIONS
07462 GenerateMstoreAction(WN *size, INT32 offset, TYPE_ID quantum, WN *expr)
07463 {
07464   MSTORE_ACTIONS action;
07465 
07466   INT32 nMoves;
07467   BOOL sizeIsConstant =  WN_operator_is(size, OPR_INTCONST);
07468 
07469   if (sizeIsConstant)
07470   {
07471     nMoves = calculateLoadStore(WN_const_val(size), offset, quantum, expr);
07472   }
07473 
07474   if (MinStructCopyMemIntrSize  &&
07475      ((sizeIsConstant==FALSE)           ||
07476       (sizeIsConstant==TRUE && MinStructCopyMemIntrSize <= nMoves)))
07477   {
07478     if (WN_operator_is(expr, OPR_INTCONST))
07479     {
07480       INT64     val=    WN_const_val(expr);
07481 
07482       if (val == 0)
07483         action = MSTORE_intrinsic_bzero;
07484       else
07485       {
07486         WN *i1con= WN_I1const(WN_rtype(expr), val);
07487 
07488         action = (val == WN_const_val(i1con)) ? MSTORE_intrinsic_memset
07489           : MSTORE_loop;
07490         WN_Delete(i1con);
07491       }
07492     }
07493     else if (WN_operator_is(expr, OPR_MLOAD))
07494     {
07495       action = MSTORE_intrinsic_bcopy;
07496     }
07497     else
07498     {
07499       action = MSTORE_loop;
07500     }
07501   }
07502   else if (sizeIsConstant==TRUE         &&
07503            MinStructCopyLoopSize        &&
07504            MinStructCopyLoopSize <= nMoves)
07505   {
07506       action = MSTORE_loop;
07507   }
07508   else
07509   {
07510     action = (sizeIsConstant) ? MSTORE_aggregate : MSTORE_loop;
07511   }
07512 
07513   if (traceMload)
07514   {
07515     if (sizeIsConstant) {
07516       DevWarn("GenerateMstoreAction: %s : line %d: quantum %d, "
07517               "size %lld, nMoves %d",
07518               MSTORE_ACTIONS_name(action),
07519               Srcpos_To_Line(current_srcpos),
07520               MTYPE_alignment(quantum),
07521               WN_const_val(size),
07522               nMoves);
07523     } else {
07524       DevWarn("GenerateMstoreAction: %s : line %d: quantum %d, "
07525               "size unknown",
07526               MSTORE_ACTIONS_name(action),
07527               Srcpos_To_Line(current_srcpos),
07528               MTYPE_alignment(quantum));
07529     }
07530   }
07531 
07532   return action;
07533 }
07534 
07535 // If the size of the mtype (used in load/store) is the same as the size of 
07536 // the struct, return the struct's type, otherwise, return a predefined
07537 // type corresponding to mtype.
07538 static inline TY_IDX
07539 struct_memop_type (TYPE_ID mtype, TY_IDX struct_type)
07540 {
07541     if (TY_size (struct_type) != MTYPE_byte_size (mtype))
07542         Set_TY_IDX_index (struct_type, TY_IDX_index(MTYPE_To_TY (mtype)));
07543     return struct_type;
07544 }
07545 
07546 
07547 /* ====================================================================
07548  *
07549  * Auxillary routine to copy aggregrate
07550  * 
07551  *  Copy size bytes, starting at offset
07552  * 
07553  *   There are so many formals that you probably deserve an explanation
07554  *      WN *block
07555  *
07556  *      TY_IDX srcAlign
07557  *      TY_IDX dstAlign
07558  *              alignment restrictions of the generated load/stores as cg
07559  *              needs to know whether to generate unaligned 
07560  *      INT32 offset
07561  *              start copying at (byte) offset
07562  *      INT32 size (or WN *)
07563  *              struct (byte) size 
07564  *              for loop code , this is a size expression
07565  *      TYPE_ID quantum
07566  *              unit to load/store
07567  *      ST *preg
07568  *      PREG_NUM srcPreg
07569  *      PREG_NUM dstPreg
07570  *              if srcAlign is NULL
07571  *                  srcPreg contains an expression (probably zero)
07572  *              else
07573  *                  srcPreg contains the address of the src to copy
07574  *              dstPreg contains the address of the dst to copy
07575  *              preg should be Int_Preg.
07576  *      WN *origLoad
07577  *      WN *origStore
07578  *              original load/store nodes (or NULL) needed to preserve alias
07579  *              maps.
07580  *
07581  * ==================================================================== */
07582 
07583 static void
07584 copy_aggregate(WN *block, TY_IDX srcAlign, TY_IDX dstAlign, INT32 offset,
07585                INT32 size, TYPE_ID quantum, ST *preg, PREG_NUM srcPreg,
07586                PREG_NUM dstPreg, WN *origLoad, WN *origStore,
07587                INT32 copy_alignment, LOWER_ACTIONS actions)
07588 {
07589   INT32 stride = MTYPE_RegisterSize(quantum);
07590   INT32 nMoves = size / stride;
07591 
07592   if (size <= 0)
07593     return;
07594 
07595   if (nMoves>0)
07596   {
07597    /*
07598     *  generate  unrolled load/store
07599     */
07600     while(nMoves--)
07601     {
07602      /*
07603       *  semantics are similar to the following:
07604       *      (quantum) *(dst + offset) =   (quantum) *(src + offset);
07605       *         or
07606       *      (quantum) *(dst + offset) =   srcPreg;
07607       */
07608       WN        *value, *addr, *store;
07609 
07610       if (srcAlign)
07611       {
07612         value = WN_IloadLdid(quantum, offset,
07613                              struct_memop_type (quantum, srcAlign),
07614                              preg, srcPreg);  
07615 
07616         lower_copy_maps(origLoad, value, actions);
07617       }
07618       else
07619       {
07620         value = WN_LdidPreg(quantum, srcPreg);
07621       }
07622 
07623       addr = WN_LdidPreg(Pointer_type, dstPreg);
07624 
07625       store = WN_Istore(quantum,
07626                         offset,
07627                         Make_Pointer_Type (struct_memop_type (quantum,
07628                                                               dstAlign)),
07629                         addr,
07630                         value);
07631       lower_copy_maps(origStore, store, actions);
07632 
07633       WN_INSERT_BlockLast(block, store);
07634 
07635       offset  += stride;
07636       size -= stride;
07637     }
07638   }
07639   if (size > 0)
07640   {
07641    /*
07642     *  If there is a residue we must recompute a new quantum
07643     *  and generate a copy for that.
07644     */
07645     quantum = compute_next_copy_quantum(quantum, copy_alignment);
07646 
07647     copy_aggregate(block,
07648                    srcAlign, dstAlign,
07649                    offset,
07650                    size,
07651                    quantum,
07652                    preg,
07653                    srcPreg, dstPreg,
07654                    origLoad, origStore,
07655                    copy_alignment,
07656                    actions);
07657   }
07658 }
07659 
07660 
07661 
07662 
07663 static void
07664 copy_element_and_increment(WN *block, TY_IDX srcAlign, TY_IDX dstAlign,
07665                            PREG_NUM offsetN, TYPE_ID quantum, PREG_NUM srcPreg,
07666                            PREG_NUM dstPreg, WN *origLoad, WN *origStore,
07667                            LOWER_ACTIONS actions)
07668 {
07669  /*
07670   *   (quantum) *(dst + offset) =   (quantum) *(src + offset);
07671   *             or
07672   *   (quantum) *(dst + offset) =   srcPreg;
07673   *             
07674   *  and increment offset
07675   *
07676   *             offset          +=  stride;
07677   */
07678   INT32  stride = MTYPE_RegisterSize(quantum);
07679   WN    *value, *addr, *store, *add, *inc;
07680   ST    *intPreg = MTYPE_To_PREG(Integer_type);
07681 
07682   if (srcAlign)
07683   {
07684     addr = WN_Add(Pointer_type,
07685                   WN_LdidPreg(Pointer_type, srcPreg),
07686                   WN_LdidPreg(Integer_type, offsetN));
07687     value = WN_CreateIload (OPR_ILOAD, Mtype_comparison(quantum), quantum,
07688                             0, struct_memop_type (quantum, srcAlign),
07689                             Make_Pointer_Type (srcAlign), addr);
07690 
07691     lower_copy_maps(origLoad, value, actions);
07692   }
07693   else
07694   {
07695     value = WN_LdidPreg(quantum, srcPreg);
07696   }
07697 
07698   addr = WN_Add(Pointer_type,
07699                 WN_LdidPreg(Pointer_type, dstPreg),
07700                 WN_LdidPreg(Integer_type, offsetN));
07701   store = WN_Istore(quantum,
07702                     0,
07703                     Make_Pointer_Type(struct_memop_type (quantum, dstAlign)),
07704                     addr,
07705                     value);
07706 
07707   lower_copy_maps(origStore, store, actions);
07708 
07709   WN_INSERT_BlockLast(block, store);
07710 
07711   /*
07712    *  offset += stride
07713    */
07714 
07715   add  = WN_Add(Integer_type,
07716                 WN_LdidPreg(Integer_type, offsetN),
07717                 WN_Intconst(Integer_type, stride));
07718   inc = WN_StidIntoPreg(Integer_type, offsetN, intPreg, add);
07719   WN_INSERT_BlockLast(block, inc);
07720 }
07721 
07722 
07723 
07724 
07725 /* ====================================================================
07726  *
07727  * Auxillary routine to copy aggregrate loop 
07728  *
07729  *      The size must be an integer constant
07730  *
07731  * ==================================================================== */
07732 static void
07733 copy_aggregate_loop_const(WN *block, TY_IDX srcAlign, TY_IDX dstAlign,
07734                           INT32 offset, INT32 size, TYPE_ID quantum,
07735                           PREG_NUM srcPreg, PREG_NUM dstPreg, WN *origLoad,
07736                           WN *origStore, INT32 copy_alignment,
07737                           LOWER_ACTIONS actions)
07738 {
07739  /*
07740   *  generate the following
07741   *    n = nMoves;
07742   *    index = 0;
07743   *    do
07744   *    {
07745   *     (quantum) *(dst + offset) =   (quantum) *(src + offset);
07746   *            n--;
07747   *    } while(n>0);
07748   *
07749   * Try generating a DO loop instead of a WHILE loop
07750   *
07751   *     (TBD)   we should really build an array expression 
07752   *             dst[offset] = src[offset]
07753   */
07754   PREG_NUM              offsetN;
07755   ST            *intPreg = MTYPE_To_PREG(Integer_type);
07756   INT32         stride   = MTYPE_RegisterSize(quantum);
07757   INT64         nMoves   = size  / stride;
07758   INT64         residue  = size - ( nMoves * stride );
07759 
07760   /*
07761    *  Bail out if there is nothing to move and no residue
07762    */
07763   if ((nMoves <= 0) && residue == 0)
07764     return;
07765 
07766   offsetN = AssignExpr(block, WN_Intconst(Integer_type, offset), Integer_type);
07767 
07768  /*
07769   *     create loop count variable, traditionally called n
07770   *     offset is most likely zero
07771   */
07772   if (nMoves > 0)
07773   {
07774     PREG_NUM    n;
07775     WN          *body;
07776     WN          *incr;
07777     WN          *start;
07778     WN          *test;
07779     WN          *doLoop;
07780 
07781     n = Create_Preg(Integer_type,"mstore_loopcount");
07782     body= WN_CreateBlock();
07783     start = WN_StidIntoPreg( Integer_type, n, intPreg,
07784                              WN_Intconst(Integer_type, nMoves));
07785     incr  = WN_StidIntoPreg( Integer_type, n, intPreg,
07786                              WN_Sub(Integer_type,
07787                                     WN_LdidPreg(Integer_type, n),
07788                                     WN_Intconst(Integer_type, 1)));
07789     test = WN_GT(Integer_type,
07790                  WN_LdidPreg(Integer_type, n),
07791                  WN_Zerocon(Integer_type));
07792     
07793    /*
07794     *   (quantum) *(dst + offset) =   (quantum) *(src + offset);
07795     *           or
07796     *   (quantum) *(dst + offset) =   srcPreg;
07797     *   and increment offset
07798     *                   offset    +=  stride;
07799     */
07800     copy_element_and_increment(body,
07801                                srcAlign, dstAlign,
07802                                offsetN,
07803                                quantum,
07804                                srcPreg, dstPreg,
07805                                origLoad, origStore,
07806                                actions);
07807     doLoop = WN_CreateDO(WN_CreateIdname(n, intPreg),
07808                          start, test, incr, body, NULL);
07809     WN_INSERT_BlockLast(block, doLoop);
07810     if ( Cur_PU_Feedback )
07811       Cur_PU_Feedback->FB_lower_mstore_to_loop( origStore, doLoop, nMoves );
07812   }
07813 
07814  /*
07815   *  If there is a residue we must recompute a new quantum
07816   *  and generate a copy for that.
07817   *
07818   *     if (residue > 0)
07819   *     {
07820   *         if (residue >= 4)
07821   *         {
07822   *             (int) *(dst + offset) =   (int) *(src + offset);
07823   *             offset  += 4;
07824   *             residue -= 4;
07825   *         }
07826   *         if (residue >= 2)
07827   *         {
07828   *              (short) *(dst + offset) =   (short) *(src + offset);
07829   *             offset  += 2;
07830   *             residue -= 2;
07831   *         }
07832   *         etc.
07833   *     }
07834   */
07835   if (residue)
07836   {
07837     WN    *residue_block=  WN_CreateBlock();
07838 
07839     while(residue>0)
07840     {
07841       quantum = compute_next_copy_quantum(quantum, copy_alignment);
07842 
07843       while (residue >= MTYPE_alignment(quantum))
07844       {
07845         copy_element_and_increment(residue_block, srcAlign, dstAlign,
07846                                    offsetN, quantum, srcPreg, dstPreg,
07847                                    origLoad, origStore, actions);
07848         residue -= MTYPE_alignment(quantum);
07849       }
07850     }
07851     WN_INSERT_BlockLast(block, residue_block);
07852   }
07853 }
07854 
07855 
07856 
07857 
07858 /* ====================================================================
07859  *
07860  * Auxillary routine to copy aggregrate loop 
07861  *
07862  *      The size must be an expression
07863  *
07864  * ==================================================================== */
07865 
07866 static void
07867 copy_aggregate_loop_n(WN *block, TY_IDX srcAlign, TY_IDX dstAlign,
07868                       INT32 offset, WN *size, TYPE_ID quantum,
07869                       PREG_NUM srcPreg, PREG_NUM dstPreg, WN *origLoad,
07870                       WN *origStore, INT32 copy_alignment,
07871                       LOWER_ACTIONS actions)
07872 {
07873  /*
07874   *  generate the following
07875   *    n = nMoves;
07876   *    index = 0;
07877   *    while(n>0)
07878   *    {
07879   *     (quantum) *(dst + offset) =   (quantum) *(src + offset);
07880   *            n--;
07881   *    }
07882   *
07883   *     (TBD)   we should really build an array expression 
07884   *             dst[offset] = src[offset]
07885   */
07886   PREG_NUM      offsetN, nMovesN, residueN;
07887   ST            *intPreg = MTYPE_To_PREG(Integer_type);
07888   INT32         stride   = MTYPE_RegisterSize(quantum);
07889 
07890   Is_True((WN_operator(size)!=OPR_INTCONST),("unexpected const"));
07891 
07892  /*
07893   *  Create the following expressions
07894   *
07895   *     nMovesn = ( size ) / stride
07896   *
07897   *     residue =   size - ( nMoves * stride )
07898   */
07899   {
07900     WN  *nMoves, *residue;
07901 
07902     nMoves   = WN_Div(Integer_type, WN_COPY_Tree(size),
07903                       WN_Intconst(Integer_type, stride));
07904 
07905     nMovesN  = AssignExpr(block, nMoves, Integer_type);
07906 
07907     residue  = WN_Sub(Integer_type,
07908                       WN_COPY_Tree(size),
07909                       WN_Mpy(Integer_type,
07910                              WN_LdidPreg(Integer_type, nMovesN),
07911                              WN_Intconst(Integer_type, stride)));
07912 
07913     residueN = AssignExpr(block, residue, Integer_type);
07914   }
07915 
07916  /*
07917   *     create loop count variable, traditionally called n
07918   *     offset is most likely zero
07919   */
07920 #if 0
07921   n = AssignExpr(block, WN_LdidPreg(Integer_type, nMovesN), Integer_type);
07922 
07923   offsetN = AssignExpr(block, WN_Intconst(Integer_type, offset), Integer_type);
07924 
07925   {
07926     WN  *body, *sub, *dec, *test, *whileDo;
07927 
07928     body = WN_CreateBlock();
07929    /*
07930     *   while(n>0)
07931     *   {
07932     *
07933     *     (quantum) *(dst + offset) =   (quantum) *(src + offset);
07934     *           or
07935     *     (quantum) *(dst + offset) =   srcPreg;
07936     *
07937     *                   offset    +=  stride;
07938     *
07939     *                   n --;
07940     *   }
07941     */
07942     copy_element_and_increment(body,
07943                                srcAlign, dstAlign,
07944                                offsetN, quantum,
07945                                srcPreg, dstPreg,
07946                                origLoad, origStore,
07947                                actions);
07948 
07949     sub  = WN_Sub(Integer_type,
07950                   WN_LdidPreg(Integer_type, n),
07951                   WN_Intconst(Integer_type, 1));
07952     dec  = WN_StidIntoPreg(Integer_type, n, intPreg, sub);
07953     WN_INSERT_BlockLast(body, dec);
07954 
07955 
07956     test = WN_GT(Integer_type,
07957                  WN_LdidPreg(Integer_type, n),
07958                  WN_Zerocon(Integer_type));
07959         
07960     whileDo = WN_CreateWhileDo(test, body);
07961     // ADD FEEDBACK INFO !!!
07962     WN_INSERT_BlockLast(block, whileDo);
07963   }
07964 #else
07965   {
07966     PREG_NUM    n;
07967     WN          *body;
07968     WN          *incr;
07969     WN          *start;
07970     WN          *test;
07971     WN          *doLoop;
07972 
07973     n = Create_Preg(Integer_type,"mstore_loopcount");
07974     offsetN = AssignExpr(block, WN_Intconst(Integer_type, offset),
07975                          Integer_type);
07976 
07977     body= WN_CreateBlock();
07978     start = WN_StidIntoPreg(Integer_type, n, intPreg,
07979                             WN_LdidPreg(Integer_type, nMovesN));
07980     incr  = WN_StidIntoPreg(Integer_type, n, intPreg,
07981                             WN_Sub(Integer_type,
07982                                    WN_LdidPreg(Integer_type, n),
07983                                    WN_Intconst(Integer_type, 1)));
07984     test = WN_GT(Integer_type,
07985                  WN_LdidPreg(Integer_type, n),
07986                  WN_Zerocon(Integer_type));
07987     
07988    /*
07989     *   (quantum) *(dst + offset) =   (quantum) *(src + offset);
07990     *           or
07991     *   (quantum) *(dst + offset) =   srcPreg;
07992     *   and increment offset
07993     *                   offset    +=  stride;
07994     */
07995     copy_element_and_increment(body,
07996                                srcAlign, dstAlign,
07997                                offsetN,
07998                                quantum,
07999                                srcPreg, dstPreg,
08000                                origLoad, origStore,
08001                                actions);
08002     doLoop = WN_CreateDO(WN_CreateIdname(n,intPreg),start,test,incr,body,NULL);
08003     WN_INSERT_BlockLast(block, doLoop);
08004   }
08005   
08006 #endif
08007 
08008 
08009 
08010 
08011 
08012  /*
08013   *  If there is a residue we must recompute a new quantum
08014   *  and generate a copy for that.
08015   *
08016   *     if (residue > 0)
08017   *     {
08018   *         if (residue >= 4)
08019   *         {
08020   *             (int) *(dst + offset) =   (int) *(src + offset);
08021   *             offset  += 4;
08022   *             residue -= 4;
08023   *         }
08024   *         if (residue >= 2)
08025   *         {
08026   *              (short) *(dst + offset) =   (short) *(src + offset);
08027   *             offset  += 2;
08028   *             residue -= 2;
08029   *         }
08030   *         etc.
08031   *     }
08032   *   We supply an incorrect alignment to compute_next_copy_quantum()
08033   *   because we cant skip the unaligned halfword 
08034   */
08035   {
08036     WN  *if_then, *unused, *cond, *IF;
08037 
08038     if_then = WN_CreateBlock();
08039     unused = WN_CreateBlock();  /* will be empty */
08040 
08041     cond = WN_GT(Integer_type,
08042                  WN_LdidPreg(Integer_type, residueN),
08043                  WN_Zerocon(Integer_type));
08044 
08045     IF = WN_CreateIf(cond, if_then, unused);
08046     // ADD FEEDBACK INFO !!
08047 
08048     quantum = compute_next_copy_quantum(quantum,
08049                                         MTYPE_alignment(Max_Uint_Mtype));
08050         
08051     while(MTYPE_alignment(quantum) > 0)
08052     {
08053       WN        *if_residue_block, *unused, *test, *IF_residue;
08054 
08055 
08056       if_residue_block = WN_CreateBlock();
08057       unused = WN_CreateBlock();
08058 
08059       test = WN_GE(Integer_type,
08060                    WN_LdidPreg(Integer_type, residueN),
08061                    WN_Intconst(Integer_type, MTYPE_alignment(quantum)));
08062 
08063       IF_residue = WN_CreateIf(test, if_residue_block, unused);
08064       // ADD FEEDBACK INFO !!
08065       lower_copy_maps(origStore, IF_residue, actions);
08066         
08067       copy_element_and_increment(if_residue_block, srcAlign, dstAlign,
08068                                  offsetN, quantum, srcPreg, dstPreg,
08069                                  origLoad, origStore, actions);
08070 
08071      /*
08072       *  residue -= stride
08073       */
08074       {
08075         WN      *sub, *dec;
08076 
08077         sub  = WN_Sub(Integer_type,
08078                       WN_LdidPreg(Integer_type, residueN),
08079                       WN_Intconst(Integer_type, MTYPE_alignment(quantum)));
08080         dec = WN_StidIntoPreg(Integer_type, residueN, intPreg, sub);
08081         lower_copy_maps(origStore, dec, actions);
08082         WN_INSERT_BlockLast(if_residue_block, dec);
08083       }
08084 
08085       WN_INSERT_BlockLast(if_then, IF_residue);
08086 
08087       quantum = compute_next_copy_quantum(quantum,
08088                                           MTYPE_alignment(Max_Uint_Mtype));
08089     }
08090     WN_INSERT_BlockLast(block, IF);
08091   }
08092 }
08093 
08094 
08095 
08096 
08097 /* ====================================================================
08098  *
08099  * Auxillary routine to copy aggregrate (loop version)
08100  *
08101  *  The size can be an expression or integer constant of any value
08102  *  so it must be tested
08103  *
08104  *  loop_const: will generate a
08105  *              n= CONST;       do {} while(n<0);
08106  *
08107  *  loop_n:     will generate a
08108  *              n= size;        while(n<0) {};
08109  *
08110  * ==================================================================== */
08111 
08112 static void
08113 copy_aggregate_loop(WN *block, TY_IDX srcTY, TY_IDX dstTY, INT32 offset,
08114                     WN *size, TYPE_ID quantum, ST *preg, PREG_NUM srcPreg,
08115                     PREG_NUM dstPreg, WN *origLoad, WN *origStore,
08116                     INT32 copy_alignment, LOWER_ACTIONS actions)
08117 {
08118   if (WN_operator_is(size, OPR_INTCONST))
08119   {
08120     if (WN_const_val(size)>0)
08121     {
08122       copy_aggregate_loop_const(block,
08123                                 srcTY, dstTY,
08124                                 offset,
08125                                 WN_const_val(size),
08126                                 quantum,
08127                                 srcPreg, dstPreg,
08128                                 origLoad, origStore,
08129                                 copy_alignment,
08130                                 actions);
08131     }
08132   }
08133   else
08134   {
08135     copy_aggregate_loop_n(block,
08136                           srcTY, dstTY,
08137                           offset,
08138                           size,
08139                           quantum,
08140                           srcPreg,
08141                           dstPreg,
08142                           origLoad, origStore,
08143                           copy_alignment,
08144                           actions);
08145   }
08146 }
08147 
08148 /*
08149  *  mark LDA as addr taken passed for intrinsic memory routines.
08150  *  Do not recurse on ILOAD (it would mark the pointer as taken_passed
08151  *  and not the object)
08152  */
08153 static void markAddrTakenPassed(WN *expr)
08154 {
08155   switch(WN_operator(expr))
08156   {
08157   case OPR_LDA:
08158     {
08159       ST *sym = WN_st(expr);
08160       // if (ST_class(sym) == CLASS_VAR || ST_class(sym) == CLASS_FUNC) {
08161       //   Do nothing here. ADDR flags should only grow more
08162       //   optimistic; they should never become more conservative,
08163       //   because the program's semantics cannot grow worse as we
08164       //   compile it.
08165       // }
08166     }
08167     return;
08168   case OPR_ILOAD:
08169   case OPR_ILOADX:
08170     return;
08171   }
08172 
08173   {
08174     INT32       i;
08175     for (i = 0; i < WN_kid_count(expr); i++)
08176       markAddrTakenPassed(WN_actual(expr,i));
08177   }
08178 }
08179 
08180 
08181 /* ====================================================================
08182  * 
08183  * Generate a call to an intrinsic -- NOT an intrinsic!
08184  * (currently from lower_mstore)
08185  *
08186  * ==================================================================== */
08187 
08188 inline WN *WN_Generate_Intrinsic_Call(WN *block, INTRINSIC id, 
08189                                       INT32 nparm, WN *parm[])
08190 {
08191   WN *call = WN_Create_Intrinsic(OPC_VINTRINSIC_CALL, id, nparm, parm);
08192   return intrinsic_runtime(block, call);
08193 }
08194 
08195 
08196 static void copy_aggregate_bzero(WN *block, TY_IDX dstTY, WN *dst, WN *size)
08197 {
08198   WN  *call, *parms[2];
08199 
08200   markAddrTakenPassed(dst);
08201 
08202   parms[0]=  WN_CreateParm(Pointer_type,
08203                            dst,
08204                            dstTY,
08205                            WN_PARM_BY_VALUE);
08206 
08207   parms[1]=  WN_CreateParm(WN_rtype(size),
08208                            WN_COPY_Tree(size),
08209                            MTYPE_To_TY(WN_rtype(size)),
08210                            WN_PARM_BY_VALUE);
08211 
08212   call= WN_Generate_Intrinsic_Call(block, INTRN_BZERO, 2, parms);
08213 
08214   WN_INSERT_BlockLast(block, call);
08215 }
08216 
08217 static void copy_aggregate_memset(WN *block, TY_IDX dstTY, WN *src, WN *dst,
08218                                   WN *size)
08219 {
08220   WN  *call, *parms[3];
08221 
08222   markAddrTakenPassed(dst);
08223   parms[0]=  WN_CreateParm(Pointer_type,
08224                            dst,
08225                            dstTY,
08226                            WN_PARM_BY_VALUE);
08227 
08228   parms[1]=  WN_CreateParm(WN_rtype(src),
08229                            src,
08230                            MTYPE_To_TY(WN_rtype(src)),
08231                            WN_PARM_BY_VALUE);
08232 
08233   parms[2]=  WN_CreateParm(WN_rtype(size),
08234                            WN_COPY_Tree(size),
08235                            MTYPE_To_TY(WN_rtype(size)),
08236                            WN_PARM_BY_VALUE);
08237 
08238   call= WN_Generate_Intrinsic_Call(block, INTRN_MEMSET, 3, parms);
08239 
08240   WN_INSERT_BlockLast(block, call);
08241 }
08242 
08243 static void copy_aggregate_bcopy(WN *block, INT32 offset, TY_IDX srcTY,
08244                                  TY_IDX dstTY, WN *src, WN *dst, WN *size)
08245 {
08246   WN  *call, *parms[3];
08247 
08248   if (offset)
08249   {
08250     src = WN_Add(Pointer_type, src, WN_Intconst(Pointer_type, offset));
08251     dst = WN_Add(Pointer_type, dst, WN_Intconst(Pointer_type, offset));
08252   }
08253   markAddrTakenPassed(src);
08254   markAddrTakenPassed(dst);
08255 
08256   parms[0]=  WN_CreateParm(WN_rtype(src),
08257                            src,
08258                            srcTY ? srcTY : MTYPE_To_TY(WN_rtype(src)),
08259                            WN_PARM_BY_VALUE);
08260 
08261   parms[1]=  WN_CreateParm(Pointer_type,
08262                            dst,
08263                            dstTY ? dstTY : MTYPE_To_TY(WN_rtype(dst)),
08264                            WN_PARM_BY_VALUE);
08265 
08266 
08267   parms[2]=  WN_CreateParm(WN_rtype(size),
08268                            WN_COPY_Tree(size),
08269                            MTYPE_To_TY(WN_rtype(size)),
08270                            WN_PARM_BY_VALUE);
08271 
08272   call= WN_Generate_Intrinsic_Call(block, INTRN_BCOPY, 3, parms);
08273 
08274   WN_INSERT_BlockLast(block, call);
08275 }
08276 
08277 
08278 
08279 /* ====================================================================
08280  *
08281  * These routine compute alignment used by the MSTORE/MLOAD routines
08282  *
08283  *      aligned memory access
08284  *              return minimum required alignment
08285  *
08286  *      otherwise
08287  *              form a ratio based on align vrs unaligned reference.
08288  *              Each unaligned ld/st requires 2 instructions.
08289  *              In addition, some processors may support 2 memory operations
08290  *              per clock, but only one unaligned reference (r8k and alien)
08291  *
08292  * When we can use unaligned quantums, do not return halfword
08293  * quantums as there is no hardware support (pv544367)
08294  *
08295  * ==================================================================== */
08296 
08297 extern INT32 compute_copy_alignment(TY_IDX src, TY_IDX dst, INT32 offset)
08298 {
08299   INT32 srcAlign, dstAlign, align;
08300   INT32 max=    MTYPE_alignment(Max_Uint_Mtype);
08301 
08302   srcAlign= (src) ? TY_align(src) : max;
08303   dstAlign= (dst) ? TY_align(dst) : max;
08304 
08305   align= MIN(srcAlign, dstAlign);
08306   align= MIN(align, max);
08307 
08308   Is_True((compute_offset_alignment(offset, align) == align),
08309           ("compute_copy_alignment: alignment not consistent with offset"));
08310 
08311   return MIN(align, max);
08312 }
08313 
08314 
08315 extern TYPE_ID compute_copy_quantum(INT32 alignment)
08316 {
08317   if (UseAlignedCopyForStructs==FALSE)
08318   {
08319     INT32  maxAlign= MTYPE_alignment(Max_Uint_Mtype);
08320     INT32  ratio = Copy_Quantum_Ratio();
08321     
08322     if (alignment*ratio < maxAlign) 
08323       return Max_Uint_Mtype;
08324   }
08325 
08326   return Mtype_AlignmentClass(alignment, MTYPE_CLASS_UNSIGNED_INTEGER);
08327 }
08328 
08329 static TYPE_ID compute_next_copy_quantum(TYPE_ID quantum, INT32 alignment)
08330 {
08331   TYPE_ID next = Mtype_prev_alignment(quantum);
08332 
08333   if (UseAlignedCopyForStructs==FALSE)
08334   {
08335     if ((MTYPE_alignment(next) > alignment)     &&
08336         (next == MTYPE_U2 || next == MTYPE_I2))
08337       next = Mtype_prev_alignment(next);
08338   }
08339   return next;
08340 }
08341 
08342 
08343 
08344 
08345 /* ====================================================================
08346  *
08347  * TY_IDX computeNewAlignmentTY(addr, type, WN_const_val(size), offset);
08348  *
08349  * Compute a new quantum (alignment), subject to size restrictions.
08350  * For the new quantum to apply we must have an ST of the appropriate
08351  * type/offset to align/pad
08352  *
08353  * ==================================================================== */
08354 
08355 static TY_IDX computeNewAlignmentTY(WN *addr, TY_IDX type, INT32 size,
08356                                     INT64 offset)
08357 {
08358   TY_IDX newType;
08359   INT32 align = TY_align(type);
08360   INT32 maxAlign = MTYPE_alignment(Max_Uint_Mtype);
08361 
08362   if ((size <= align) || (align >= maxAlign))
08363     return TY_IDX_ZERO;
08364 
08365  /*
08366   *  create offset consistent with the offset of addr and offset
08367   */
08368   newType = compute_alignment_type(addr, type, offset);
08369  
08370   if (WN_operator_is(addr, OPR_LDA) && ST_class(WN_st(addr)) != CLASS_BLOCK)
08371   {
08372     ST     *sym     = WN_st(addr);
08373     TY_IDX  symType = compute_alignment_type(addr, ST_type(sym), offset);
08374    /*
08375     *  If the objected is defined in the current module but not allocated yet
08376     *  we are free to redefine the alignment so compute largest possible
08377     *  consistent alignment. The alignment should be consistent with the
08378     *  offset of course
08379     */
08380     if (ST_pu_defined(sym) && !Is_Allocated(sym))
08381     {
08382       INT32  stAlign;
08383 
08384       stAlign = compute_offset_alignment(WN_lda_offset(addr), maxAlign);
08385       stAlign = compute_offset_alignment(offset, stAlign);
08386 
08387       if (TY_align(symType) < stAlign)
08388       {
08389         if (traceAlignment)
08390         {
08391           DevWarn("realign ST %s (from %d to %d) line %d", ST_name(sym),
08392                   TY_align(symType), stAlign, Srcpos_To_Line(current_srcpos));
08393         }
08394         // Convert Make_Align_Type once real iterators are implemented
08395         // to iterate over the TY table.
08396         symType = Make_Align_Type(symType, stAlign);
08397 
08398         if ((ST_class(sym) == CLASS_CONST)              &&
08399             (TCON_ty(STC_val(sym)) == MTYPE_STR)        &&
08400              TY_is_pointer(Ty_Table[ST_type(sym)]))
08401         {
08402           symType = Make_Pointer_Type(newType);
08403         }
08404         Set_ST_type(sym, symType);
08405 
08406         if (stAlign > align)
08407         {
08408           return Make_Align_Type(newType, stAlign);
08409         }
08410         return TY_IDX_ZERO;
08411       }
08412     }
08413   }
08414 
08415   if (TY_align(newType) > align)
08416     return newType;
08417 
08418   return TY_IDX_ZERO;
08419 }
08420 
08421 
08422 
08423 
08424 static WN *compute_new_size(WN *tree, WN *size, INT32 align)
08425 {
08426   if (Align_Padding)
08427   {
08428     INT64  sizeN   = WN_const_val(size);
08429     INT64  residue = sizeN % align;
08430     INT32  popcnt  = TARG_INT_Pop_Count(residue);
08431 
08432     if (popcnt > 1)
08433     {
08434       INT64  newsize = sizeN + (align-residue);
08435 
08436       return WN_Intconst(WN_rtype(size), newsize);
08437     }
08438   }
08439   return size;
08440 }
08441 
08442 
08443 
08444 
08445 /* ====================================================================
08446  *
08447  * WN *improve_Malignment(WN *tree, WN *addr, WN *size, INT64 offset)
08448  *
08449  * Given an mstore or mload try to improve the alignment (if possible)
08450  *
08451  *
08452  * ==================================================================== */
08453 static WN *improve_Malignment(WN *tree, WN *addr, WN *size, INT64 offset)
08454 {
08455   TY_IDX type, newType;
08456 
08457   if (Align_Object == FALSE)
08458     return tree;
08459 
08460   if (!WN_operator_is(size, OPR_INTCONST))
08461   {
08462     return tree;
08463   }
08464 
08465   TY &tree_ty = Ty_Table[WN_ty(tree)];
08466 
08467   if (TY_is_f90_pointer(tree_ty)) {
08468      /* It's not safe to realign F90 pointers */
08469      return tree;
08470   }
08471 
08472   type = TY_pointed(tree_ty);
08473 
08474   newType = computeNewAlignmentTY(addr, type, WN_const_val(size), offset);
08475 
08476   if (newType)
08477   {
08478     if (traceAlignment)
08479     {
08480       DevWarn("realign OPCODE %s (from %d to %d) line %d",
08481               OPCODE_name(WN_opcode(tree)), TY_align(type), TY_align(newType),
08482               Srcpos_To_Line(current_srcpos));
08483     }
08484 
08485     WN_set_ty(tree, Make_Pointer_Type(newType));
08486 
08487     switch(WN_operator(tree))
08488     {
08489     case OPR_MSTORE:
08490       WN_kid2(tree)= compute_new_size(tree, size, TY_align(newType));
08491       break;
08492 
08493     case OPR_MLOAD:
08494       WN_kid1(tree)= compute_new_size(tree, size, TY_align(newType));
08495       break;
08496     }
08497   }
08498 
08499   return tree;
08500 }
08501 
08502 
08503 
08504 
08505 /* ====================================================================
08506  *
08507  * WN *lower_mstore(WN *block, WN *tree, LOWER_ACTIONS actions)
08508  *
08509  * Perform lowering (see WN_Lower description) on mstore statement <tree>,
08510  * returning lowered tree.
08511  *
08512  * The following control the expansion
08513  *    
08514  *    BOOL GenerateLoopCode(INT32 size, TYPE_ID quantum)
08515  *        See notes on this function for more information
08516  *
08517  *    BOOL UseAlignedCopyForStructs
08518  *        TRUE
08519  *              expand using minimum common alignment 
08520  *        FALSE 
08521  *              expand using maximum integer type
08522  *
08523  * ==================================================================== */
08524 
08525 static WN *lower_mstore(WN * /*block*/, WN *mstore, LOWER_ACTIONS actions)
08526 {
08527   WN            *newblock;
08528   WN            *load, *addr, *size;
08529   SRCPOS        srcpos = WN_Get_Linenum(mstore);
08530   CURRENT_STATE mstate = pushCurrentState(mstore, actions);
08531 
08532   load =        WN_kid0(mstore);
08533   addr =        WN_kid1(mstore);
08534   size =        WN_kid2(mstore);
08535 
08536   Is_True((WN_opcode(mstore) == OPC_MSTORE),
08537           ("expected MSTORE node, not %s", OPCODE_name(WN_opcode(mstore))));
08538 
08539 
08540   if (WN_field_id (mstore) != 0)
08541       lower_field_id (mstore);
08542 
08543   newblock = WN_CreateBlock();
08544   {
08545     TY_IDX  dstTY = TY_pointed(Ty_Table[WN_ty(mstore)]);
08546     TY_IDX  srcTY = TY_IDX_ZERO;
08547     WN     *expr = load;
08548 
08549    /*
08550     *  The "load" may be any expression (ex. constant 0)
08551     *  If so, there should be no alignment restrictions
08552     */
08553     if (WN_opcode(load) == OPC_MLOAD)
08554     {
08555       srcTY = TY_pointed(Ty_Table[WN_ty(load)]);
08556       expr =    WN_kid0(load);
08557      /*
08558       *  the mload may have an offset
08559       */
08560       if (WN_load_offset(load))
08561       {
08562         expr = WN_Add(Pointer_type,
08563                       expr,
08564                       WN_Intconst(Pointer_type, WN_load_offset(load)));
08565         WN_kid0(load)=  expr;
08566       }
08567     }
08568     else
08569     {
08570       load =            NULL;
08571     }
08572 
08573     {
08574       INT32     copy_alignment;
08575       PREG_NUM  dstPreg, srcPreg;
08576       TYPE_ID   quantum;
08577       ST        *preg=    MTYPE_To_PREG(Pointer_type);
08578 
08579       if (WN_store_offset(mstore))
08580       {
08581         addr = WN_Add(Pointer_type,
08582                       addr,
08583                       WN_Intconst(Pointer_type, WN_store_offset(mstore)));
08584       }
08585 
08586       copy_alignment = compute_copy_alignment(srcTY, dstTY,
08587                                               WN_store_offset(mstore));
08588       quantum = compute_copy_quantum(copy_alignment);
08589 
08590       switch(GenerateMstoreAction(size, 0, quantum, WN_kid0(mstore)))
08591       {
08592       case MSTORE_intrinsic_bzero:
08593         copy_aggregate_bzero(newblock, WN_ty(mstore), addr, size);
08594         break;
08595 
08596       case MSTORE_intrinsic_memset:
08597         copy_aggregate_memset(newblock, WN_ty(mstore), expr, addr, size);
08598         break;
08599 
08600       case MSTORE_intrinsic_bcopy:
08601         copy_aggregate_bcopy(newblock, 0, TY_pointer(srcTY), TY_pointer(dstTY),
08602                              expr, addr, size);
08603         break;
08604 
08605       case MSTORE_loop:
08606         srcPreg = AssignExpr(newblock, expr, WN_rtype(expr));
08607         dstPreg = AssignExpr(newblock, addr, Pointer_type);
08608         copy_aggregate_loop(newblock,
08609                             srcTY,
08610                             dstTY,
08611                             0,
08612                             size,
08613                             quantum,
08614                             preg,
08615                             srcPreg,
08616                             dstPreg,
08617                             load,
08618                             mstore,
08619                             copy_alignment,
08620                             actions);
08621         break;
08622 
08623       case MSTORE_aggregate:
08624         srcPreg = AssignExpr(newblock, expr, WN_rtype(expr));
08625         dstPreg = AssignExpr(newblock, addr, Pointer_type);
08626         copy_aggregate(newblock,
08627                        srcTY,
08628                        dstTY,
08629                        0,
08630                        WN_const_val(size),
08631                        quantum,
08632                        preg,
08633                        srcPreg,
08634                        dstPreg,
08635                        load,
08636                        mstore,
08637                        copy_alignment,
08638                        actions);
08639         break;
08640       }
08641     }
08642   }
08643 
08644   WN_Delete( WN_kid2(mstore));
08645   WN_Delete(mstore);
08646 
08647   newblock = lower_block(newblock, actions);
08648 
08649   popCurrentState(mstate);
08650   return newblock;
08651 }
08652 
08653 
08654 
08655 /* ====================================================================
08656  *
08657  * WN *lower_mload(WN *block, WN *tree, LOWER_ACTIONS actions)
08658  *
08659  * This expansion is generated only for eval (mload), where the TY is volatile
08660  * I hope this never happens in practice
08661  * With gccfe this can happen when TY is not volatile and we don't optimize.
08662  *
08663  * ==================================================================== */
08664 
08665 static WN *lower_mload(WN * /*block*/, WN *mload, LOWER_ACTIONS actions)
08666 {
08667   PREG_NUM  srcPreg;
08668   TYPE_ID   quantum;
08669   INT32     size, copy_alignment;
08670   WN        *newblock;
08671 
08672   Is_True((WN_opcode(mload) == OPC_MLOAD),
08673           ("expected MLOAD node, not %s", OPCODE_name(WN_opcode(mload))));
08674   Is_True((WN_operator_is(WN_kid1(mload), OPR_INTCONST)),
08675           ("expected MLOAD size constant  "));
08676 
08677   if (WN_field_id (mload) != 0)
08678       lower_field_id (mload);
08679 
08680   WN       *addr   = WN_kid0(mload);
08681   INT32     offset = WN_load_offset(mload);
08682   TY_IDX    srcTY  = TY_pointed(Ty_Table[WN_ty(mload)]);
08683 
08684   newblock = WN_CreateBlock();
08685 
08686   size = WN_const_val( WN_kid1(mload) );
08687   copy_alignment = compute_copy_alignment( srcTY, TY_IDX_ZERO, offset );
08688   quantum = compute_copy_quantum( copy_alignment );
08689 
08690   srcPreg = AssignExpr(newblock, addr, WN_rtype(addr));
08691 
08692   while (size > 0)
08693   {
08694     INT32 stride = MTYPE_RegisterSize(quantum);
08695     INT32 nMoves = size / stride;
08696 
08697    /*
08698     *  generate  unrolled eval (load)
08699     */
08700     while (nMoves > 0)
08701     {
08702       WN        *value, *eval;
08703 
08704       // use quantum TY rather than srcTY since want quantum-sized loads.
08705       value = WN_IloadLdid(quantum, offset, MTYPE_To_TY(quantum),
08706                            MTYPE_To_PREG(Pointer_type), srcPreg);
08707 
08708       lower_copy_maps(mload, value, actions);
08709 
08710       eval = WN_CreateEval(value);
08711 
08712       WN_INSERT_BlockLast(newblock, eval);
08713 
08714       offset += stride;
08715       size   -= stride;
08716       nMoves--;
08717     }
08718    /*
08719     *  If there is a residue we must recompute a new quantum
08720     *  and generate a copy for that.
08721     */
08722     if (size > 0)
08723     {
08724       quantum = compute_next_copy_quantum(quantum, copy_alignment);
08725     }
08726   }
08727 
08728   WN_Delete( WN_kid1(mload));
08729   WN_Delete(mload);
08730 
08731   newblock = lower_block(newblock, actions);
08732 
08733   return newblock;
08734 }
08735 
08736 
08737 
08738 
08739 /* ====================================================================
08740  *
08741  * void lower_complex_actual
08742  *
08743  * Perform lowering (see WN_Lower description) for complex actuals
08744  * This is used in fortran only , and only by value (%val)
08745  *
08746  *
08747  * ==================================================================== */
08748 
08749 static void lower_complex_actual (WN *block, WN *val, PLOC ploc,
08750                                   LOWER_ACTIONS actions)
08751 {
08752   WN     *size, *mload, *addr;
08753   TY_IDX  complexType = TY_Of_Expr(val);
08754 
08755   size = WN_Intconst(Integer_type, TY_size(Ty_Table[complexType]));
08756 
08757   addr = make_pointer_to_node(block, val);
08758 
08759   mload = WN_CreateMload(0, Make_Pointer_Type(complexType), addr, size);
08760 
08761   lower_mload_actual (block, mload, ploc, actions);
08762 }
08763 
08764 
08765 
08766 
08767 /* ====================================================================
08768  *
08769  * void lower_mload_actual
08770  *
08771  * Perform lowering (see WN_Lower description) for structure actuals
08772  * the structure will be copied to [ regs ] and [ stack ]
08773  *
08774  *
08775  * ==================================================================== */
08776 
08777 static void lower_mload_actual (WN *block, WN *mload, PLOC ploc,
08778                                 LOWER_ACTIONS actions)
08779 {
08780   ST       *preg;
08781   INT32     size, mloadOffset = 0; 
08782   PREG_NUM  addrN;
08783 
08784   if (WN_field_id(mload) != 0)
08785       lower_field_id (mload);
08786 
08787   TY_IDX    mloadTY = TY_pointed(Ty_Table[WN_ty(mload)]);
08788   WN       *mloadSize = WN_kid1(mload);
08789 
08790   if (WN_operator(mloadSize) != OPR_INTCONST) {
08791         DevWarn("mload_actual size is not INTCONST");
08792         if (WN_operator(mloadSize) == OPR_CVTL) {
08793                 mloadSize = WN_kid0(mloadSize);
08794         }
08795   }
08796   size = WN_const_val(mloadSize);
08797   if (size<=0 || WN_operator(mloadSize) != OPR_INTCONST)
08798   {
08799     DevWarn("size of mload actual should be > 0");
08800     size = TY_size(Ty_Table[mloadTY]);
08801     DevWarn("adjusting size of (%s) to TY_size= %d",
08802             TY_name(Ty_Table[mloadTY]), size);
08803     mloadSize = WN_Intconst(Integer_type, size);
08804   }
08805 
08806   Is_True((WN_opcode(mload) == OPC_MLOAD),
08807           ("expected MLOAD node, not %s", OPCODE_name(WN_opcode(mload))));
08808 
08809   Setup_Struct_Output_Parameter_Locations(mloadTY);
08810   ploc = Get_Struct_Output_Parameter_Location(ploc);
08811 
08812  /*
08813   *  create addrN assignment to hold the address of the mload
08814   *  Adjust the address if there is an offset in the mload
08815   */
08816   preg = MTYPE_To_PREG(Pointer_type);
08817   {
08818     WN  *addr = WN_COPY_Tree(WN_kid0(mload));
08819 
08820     if (WN_load_offset(mload))
08821     {
08822       addr = WN_Add(Pointer_type,
08823                     addr,
08824                     WN_Intconst(Pointer_type, WN_load_offset(mload)));
08825     }
08826     addrN = AssignExpr(block, addr, Pointer_type);
08827   }
08828 
08829   while (PLOC_is_nonempty(ploc))
08830   {
08831     if (PLOC_on_stack(ploc))
08832     {
08833       PREG_NUM  dstPreg;
08834      /*
08835       *  create WN to copy mload to sp+offset
08836       *
08837       *  dstPreg = SP + offset - mloadoffset
08838       *  copy_aggregate() will add mloadoffset later
08839       */
08840       {
08841         WN      *add;
08842         INT64   offset;
08843 
08844         offset = PLOC_offset(ploc) - Formal_Save_Area_Size
08845           + Stack_Offset_Adjustment - mloadOffset; 
08846 
08847         add = WN_Add(Pointer_type,
08848                      WN_LdidPreg(Pointer_type, Stack_Pointer_Preg_Offset),
08849                      WN_Intconst(Pointer_type, offset));
08850         dstPreg = AssignExpr(block, add, Pointer_type);
08851       }
08852       {
08853         TY_IDX srcTY =  mloadTY;
08854         TY_IDX dstTY =  MTYPE_To_TY(Max_Uint_Mtype);
08855         TYPE_ID         quantum;
08856         WN              *con;
08857         INT32           copy_alignment, nMoves;
08858         INT32           todo= size - mloadOffset;
08859 
08860        /*
08861         * the dest is guaranteed to be Max_Uint aligned
08862         */
08863         copy_alignment= compute_copy_alignment(srcTY, dstTY, 0);
08864         quantum =       compute_copy_quantum(copy_alignment);
08865 
08866         /*
08867          *  we cannot (now) generate an intrinsics as we are in the middle
08868          *  of setting call registers!!
08869          */
08870         nMoves= calculateLoadStore(todo, mloadOffset, quantum, WN_kid0(mload));
08871 
08872         if (MinStructCopyLoopSize && MinStructCopyLoopSize <= nMoves)
08873         {
08874           con = WN_Intconst(Integer_type, todo);
08875 
08876           copy_aggregate_loop(block,
08877                               srcTY,
08878                               dstTY,
08879                               mloadOffset,
08880                               con,
08881                               quantum,
08882                               preg,
08883                               addrN,
08884                               dstPreg,
08885                               mload,
08886                               NULL,
08887                               copy_alignment,
08888                               actions);
08889           WN_Delete(con);
08890         }
08891         else
08892         {
08893           copy_aggregate(block,
08894                          srcTY,
08895                          dstTY,
08896                          mloadOffset,
08897                          todo,
08898                          quantum,
08899                          preg,
08900                          addrN,
08901                          dstPreg,
08902                          mload,
08903                          NULL,
08904                          copy_alignment,
08905                          actions);
08906         }
08907       }
08908       return;
08909     }
08910     else
08911     {
08912      /*
08913       *  copy structure element to register
08914       */
08915       PREG_NUM regNo = PLOC_reg(ploc);
08916       ST        *reg = Preg_Offset_Is_Float(regNo) ? Float_Preg : Int_Preg;
08917       TYPE_ID   type = TY_mtype(Ty_Table[ST_type(reg)]);
08918 
08919       {
08920         WN      *load, *stid;
08921         INT32   todo = size - mloadOffset;
08922 
08923         if (PLOC_size(ploc) < MTYPE_size_reg(type)
08924                 && type == MTYPE_F8 && PLOC_size(ploc) == 4)
08925         {
08926                 // need to copy a smaller size than default reg-size
08927                 DevWarn("actual_mload: switch from mtype_f8 to mtype_f4");
08928                 type = MTYPE_F4;
08929                 reg = MTYPE_To_PREG(type);
08930         }
08931 
08932        /*
08933         *  special case "small" structs (or remainder of struct)
08934         *  we will try not to run off the end of the structure (as bad)
08935         */
08936         if (todo < MTYPE_alignment(type))
08937         {
08938           TYPE_ID       quantum;
08939           INT32         newAlign, shiftn;
08940 
08941           Is_True(Preg_Offset_Is_Int(regNo),
08942                   ("mload actual->reg(size/alignment problem"));
08943           newAlign = nearest_power_of_two(todo);
08944 
08945           quantum = Mtype_AlignmentClass(newAlign, MTYPE_type_class(type));
08946 
08947           load = WN_IloadLdid(quantum, mloadOffset,
08948                               struct_memop_type (quantum, mloadTY), preg,
08949                               addrN); 
08950 
08951           lower_copy_maps(mload, load, actions);
08952 
08953           if (Target_Byte_Sex == BIG_ENDIAN) {
08954             shiftn = MTYPE_size_reg(type) - MTYPE_size_reg(quantum);
08955   
08956             load = WN_Shl(type, load, WN_Intconst(type, shiftn));
08957           }
08958         }
08959         else
08960         {
08961           load = WN_IloadLdid(type, mloadOffset,
08962                               struct_memop_type (type, mloadTY), preg,
08963                               addrN); 
08964 
08965           lower_copy_maps(mload, load, actions);
08966         }
08967 
08968         stid= WN_Stid(type, regNo, reg, ST_type(reg), load);
08969 
08970         WN_INSERT_BlockLast(block, stid);
08971       }
08972     }
08973     mloadOffset += PLOC_size(ploc);
08974     ploc = Get_Struct_Output_Parameter_Location(ploc);
08975   }
08976 }
08977 
08978 
08979 /* ====================================================================
08980  *
08981  * static void lower_mload_formal
08982  *
08983  * Perform lowering (see WN_Lower description) for structure formals
08984  * registers will be copied to [ stack ]
08985  *
08986  * ==================================================================== */
08987 
08988 static void lower_mload_formal(WN *block, WN *mload, PLOC ploc,
08989                                LOWER_ACTIONS actions)
08990 {
08991   INT32   size, offset = 0; 
08992   ST     *sym = WN_st(mload);
08993   TY_IDX  symTY = ST_type(sym);
08994 
08995   Setup_Struct_Input_Parameter_Locations(symTY);
08996   ploc = Get_Struct_Input_Parameter_Location(ploc);
08997   size = TY_size(Ty_Table[symTY]);
08998 
08999   while (PLOC_is_nonempty(ploc))
09000   {
09001     if (PLOC_on_stack(ploc))
09002     {
09003      /*
09004       *  structure is already on the stack, nothing to do
09005       */
09006       return;
09007     }
09008     else
09009     {
09010      /*
09011       * copy register to stack
09012       */
09013       PREG_NUM  regNo = PLOC_reg(ploc);
09014       ST        *reg = Preg_Offset_Is_Float(regNo) ? Float_Preg : Int_Preg;
09015       TYPE_ID   type = TY_mtype(ST_type(reg));
09016       INT32     todo = size - offset;
09017       {
09018         WN        *ldid, *store;
09019 
09020         if (PLOC_size(ploc) < MTYPE_size_reg(type)
09021                 && type == MTYPE_F8 && PLOC_size(ploc) == 4)
09022         {
09023                 // need to copy a smaller size than default reg-size
09024                 DevWarn("formal_mload: switch from mtype_f8 to mtype_f4");
09025                 type = MTYPE_F4;
09026                 reg = MTYPE_To_PREG(type);
09027         }
09028 
09029         ldid = WN_LdidPreg(type, regNo);
09030        /*
09031         *  special case "small" structs (or remainder of struct)
09032         *  to use type closer to size of remaining todo
09033         */
09034         if (todo < MTYPE_alignment(type))
09035         {
09036           TYPE_ID       quantum;
09037           INT32         newAlign, shiftn;
09038 
09039           Is_True(Preg_Offset_Is_Int(regNo),
09040                   ("mload actual->reg(size/alignment problem"));
09041           newAlign = nearest_power_of_two(todo);
09042 
09043           quantum = Mtype_AlignmentClass(newAlign, MTYPE_type_class(type));
09044 
09045           shiftn = MTYPE_size_reg(type) - MTYPE_size_reg(quantum);
09046 
09047           if (Target_Byte_Sex == BIG_ENDIAN) {
09048            /*
09049             *  fix (kludge) for kernel bug pv 369702
09050             *  Since U4 and I4 are both sign extended we could use
09051             *  an arithmetic shift
09052             */
09053             if (MTYPE_alignment(quantum) == 4)
09054             {
09055               ldid= WN_Ashr(type, ldid, WN_Intconst(type, shiftn));
09056             }
09057             else
09058             {
09059               ldid= WN_Lshr(type, ldid, WN_Intconst(type, shiftn));
09060             }
09061           }
09062 
09063           store = WN_Stid (quantum, offset, sym,
09064                            struct_memop_type (quantum, symTY) , ldid);
09065         }
09066         else
09067         {
09068           store = WN_Stid (type, offset, sym, struct_memop_type (type, symTY),
09069                            ldid);   
09070         }
09071         lower_copy_maps(mload, store, actions);
09072 
09073         WN_INSERT_BlockLast(block, store);
09074       }
09075       offset += PLOC_size(ploc);
09076     }
09077     ploc = Get_Struct_Input_Parameter_Location(ploc);
09078   }
09079 }
09080 
09081 
09082 
09083 
09084 /* ====================================================================
09085  *
09086  *  void lower_complex_emulation(WN *block, WN *tree, LOWER_ACTIONS actions,
09087  *                              WN **realpart, WN **imagpart)
09088  *
09089  * Perform lowering (see WN_Lower description) on an expression
09090  * or intrinsic op, returning lowered tree.  
09091  *
09092  * ==================================================================== */
09093 static void lower_complex_emulation(WN *block, WN *tree, LOWER_ACTIONS actions,
09094                                    WN **realpart, WN **imagpart)
09095 {
09096   WN            *wn;
09097   BOOL          intrinsic_lowered;
09098 
09099   Is_True(MTYPE_is_complex(WN_rtype(tree)),
09100          ("expected complex type in lower_complex_emulation"));
09101 
09102  /*
09103   *  there is no way to turn off intrinsics consistently
09104   *  ie. the best we could do is 
09105   *             z = c4intrinsic(...)
09106   *  and then we would try to lower that !!
09107   */
09108 
09109   wn = lower_emulation(block, tree, actions, intrinsic_lowered);
09110 
09111   // Don't do this. It causes the optimizer to miss a lot of CSE's. 
09112   // R. Shapiro 10/5/98
09113   if (!intrinsic_lowered) {
09114        actions |= LOWER_INTRINSIC;
09115    }
09116   lower_complex_expr(block, wn, actions, realpart, imagpart);
09117 }
09118 
09119 
09120 /* ====================================================================
09121  *
09122  * WN *lower_emulation(WN *block, WN *tree, LOWER_ACTIONS actions,
09123  *                     BOOL & intrinsic_lowered)
09124  *
09125  * Perform lowering (see WN_Lower description) on an expression
09126  * or intrinsic op, returning lowered tree.  
09127  * 
09128  * intrinsic_lowered is set to TRUE if lowereing occurred on an intrinsic
09129  *
09130  * Should be called only if actions contains LOWER_INTRINSIC.
09131  *
09132  * ==================================================================== */
09133 static WN *lower_emulation(WN *block, WN *tree, LOWER_ACTIONS actions,
09134                            BOOL & intrinsic_lowered)
09135 {
09136   WN    *wn, *emBlock;
09137   OPCODE op = WN_opcode(tree);
09138 
09139   intrinsic_lowered = FALSE;
09140  /*
09141   *  try experiment with lowering children first
09142   *  (remember these are most likely complex expressions)
09143   */
09144   {
09145     INT32       i;
09146 
09147     for (i = 0; i < WN_kid_count(tree); i++)
09148       WN_actual(tree,i) = lower_expr(block, WN_actual(tree,i), actions);
09149   }
09150 
09151  /*
09152   *  Create a callblock and try to emulate call
09153   */
09154   wn = NULL;
09155   emBlock = WN_CreateBlock();
09156 
09157   if (OPCODE_is_intrinsic(WN_opcode(tree)))
09158   {
09159     Is_True((INTRN_is_nary(WN_intrinsic(tree))==FALSE),("nary slipped by"));
09160     if (Action(LOWER_INLINE_INTRINSIC) || Action(LOWER_INL_STACK_INTRINSIC))
09161     {
09162       wn = emulate(emBlock , tree);
09163     }
09164     if (wn == NULL && NotAction(LOWER_INTRINSIC))
09165     {
09166        return tree;
09167     }
09168     intrinsic_lowered = TRUE;
09169   }
09170  /*
09171   *  most likely quad emulation
09172   */
09173   else
09174   {
09175     wn = emulate(emBlock , tree);
09176   }
09177 
09178 
09179   if (wn)
09180   {
09181     emBlock = lower_block(emBlock, actions);
09182     WN_INSERT_BlockLast(block, emBlock);
09183 
09184     /*
09185      *  the emulation may contain nodes that may need to be lowered
09186      */
09187     if (OPCODE_is_stmt(WN_opcode(wn)))
09188     {
09189       wn = lower_stmt(block, wn, actions);
09190     }
09191     else if (OPCODE_is_expression(WN_opcode(wn)))
09192     {
09193       wn = lower_expr(block, wn, actions);
09194     }
09195   }
09196   else
09197   {
09198     WN_Delete(emBlock);
09199 
09200     if (OPCODE_is_call(op))
09201     {
09202       wn = lower_intrinsic(block, tree, actions);
09203     }
09204     else
09205     {
09206       //FIX:
09207       if (WN_intrinsic(tree) == INTRN_TLD_ADDR) {
09208         //prevent the lowering of TLD_ADDR from happening twice
09209         return tree;
09210       }
09211 
09212       wn = lower_intrinsic_op(block, tree, actions);
09213     }
09214   }
09215   return wn;
09216 }
09217 
09218 
09219 #ifdef linux
09220 /* ====================================================================
09221  *
09222  * WN *lower_cis_intrinsic(WN *block, WN *tree, LOWER_ACTIONS actions)
09223  *
09224  * Perform lowering on CIS intrinsics for linux. On linux we'ld like
09225  * so use the standard sincos() library routines rather than the irix
09226  * *cis() routines. The trouble is that sincos returns its results
09227  * through pointers passed as arguments. Therefore it must be an
09228  * INSTRINSIC_CALL and not an INTRINSIC_OP (we want the later in order for 
09229  * wopt to perform the CSEs of the combined function, which operaters on
09230  * expressions only). Therefore we generate the CIS INTRINSIC_OP and
09231  * lower it here to a call to sincos(). The lowering looks like this:
09232  *
09233  * Before:
09234  *      C*INTRINSIC_OP INTRN_*CIS (angle)
09235  *
09236  * After:
09237  *      create C* temp
09238  *      VINTRINSIC_CALL INTRN_SINCOS (angle, &temp+x, &temp+0)
09239  *      C*C*LDID temp
09240  *
09241  * Note that the INTRINSIC_CALL is lowered here as well.
09242  *
09243  * ==================================================================== */
09244 static WN *lower_cis_intrinsic(WN *block, WN *tree, LOWER_ACTIONS actions)
09245 {
09246   WN *callblock, *call, *parms[3];
09247   INTRINSIC sincos_id;
09248   TYPE_ID real_mtyp, complex_mtyp;
09249   TY_IDX real_ty, complex_ty;
09250   ST *return_sincos;
09251   WN *asinx, *acosx;
09252 
09253   complex_mtyp = WN_rtype(tree);
09254   real_mtyp = Mtype_complex_to_real(complex_mtyp);
09255   complex_ty = MTYPE_To_TY(complex_mtyp);
09256   real_ty = MTYPE_To_TY(real_mtyp);
09257 
09258   return_sincos = Gen_Temp_Symbol(complex_ty, ".sincos");
09259   acosx = WN_CreateLda(OPR_LDA, Pointer_Mtype, MTYPE_V, 
09260                        0,
09261                        Make_Pointer_Type(real_ty), return_sincos);
09262   asinx = WN_CreateLda(OPR_LDA, Pointer_Mtype, MTYPE_V, 
09263                        MTYPE_byte_size(real_mtyp),
09264                        Make_Pointer_Type(real_ty), return_sincos);
09265 
09266   switch (real_mtyp) {
09267   case MTYPE_F4:  sincos_id = INTRN_SINCOSF; break;
09268   case MTYPE_F8:  sincos_id = INTRN_SINCOS;  break;
09269   case MTYPE_F10: sincos_id = INTRN_SINCOSL; break;
09270   default:        sincos_id = INTRINSIC_INVALID; break;
09271   }
09272 
09273   parms[0] = WN_kid0(tree);
09274   parms[1] = WN_CreateParm(Pointer_type, asinx, MTYPE_To_TY(Pointer_type),
09275                            WN_PARM_BY_VALUE);
09276   parms[2] = WN_CreateParm(Pointer_type, acosx, MTYPE_To_TY(Pointer_type),
09277                            WN_PARM_BY_VALUE);
09278   call = WN_Create_Intrinsic(OPC_VINTRINSIC_CALL, sincos_id, 3, parms);
09279   WN_Delete(tree);
09280 
09281   callblock = WN_CreateBlock();
09282   callblock = lower_block(callblock, actions);
09283   WN_INSERT_BlockLast(block, callblock);
09284 
09285   call = lower_intrinsic_call(block, call, actions);
09286   WN_INSERT_BlockLast(block, call);
09287 
09288   WN *ldid = WN_Ldid(complex_mtyp, 0, return_sincos, complex_ty);
09289   return lower_expr(block, ldid, actions);
09290 }
09291 #endif
09292 
09293 
09294 /* ====================================================================
09295  *
09296  * WN *lower_intrinsic_op(WN *block, WN *tree, LOWER_ACTIONS actions)
09297  *
09298  * Perform lowering (see WN_Lower description) on intrinsic statement <tree>,
09299  * returning lowered tree.  Should be called only if actions contains
09300  * LOWER_INTRINSIC.
09301  *
09302  * Since we are calling a runtime routine from a non-statement level
09303  * we need to
09304  *    [1]       insert call (lower_intrinsic)
09305  *    [2]       assign return value to preg temp
09306  *    [3]       return preg temp
09307  *
09308  * The return preg value may require special processing after
09309  * (see below for examples)
09310  * ==================================================================== */
09311 static WN *lower_intrinsic_op(WN *block, WN *tree, LOWER_ACTIONS actions)
09312 {
09313   WN            *wn;
09314   OPCODE        op = WN_opcode(tree);
09315   INTRINSIC     id = WN_intrinsic(tree);
09316 
09317   Is_True(Action(LOWER_INTRINSIC),
09318           ("actions does not contain LOWER_INTRINSIC"));
09319   Is_True(OPCODE_is_intrinsic(op),
09320           ("expression is not intrinsic"));
09321 
09322 #ifdef linux
09323   switch (id) {
09324   case INTRN_F4CIS:
09325   case INTRN_F8CIS:
09326 //  case INTRN_F10CIS:
09327     return lower_cis_intrinsic(block, tree, actions);
09328   }
09329 #endif
09330 
09331  /*
09332   *  To evaluate the intrinsic call we need to save the return type 
09333   *  and create a temporary to hold the return value
09334   */
09335   wn = lower_intrinsic(block, tree, actions);
09336 
09337   Is_True(OPCODE_is_call(WN_opcode(wn)), 
09338           ("lowered instrinsic op is not a call"));
09339   WN_INSERT_BlockLast(block, wn);
09340 
09341   {
09342     TYPE_ID     ty1, ty2;
09343     PREG_NUM    reg1, reg2;
09344     TYPE_ID     type = WN_rtype(tree);
09345 
09346     rename_preg(INTR_intrinsic_name(tree), ".return");
09347 
09348     if (WHIRL_Return_Info_On) {
09349 
09350       RETURN_INFO return_info = Get_Return_Info (MTYPE_To_TY(type),
09351                                                  Complex_Not_Simulated);
09352 
09353       if (RETURN_INFO_count(return_info) <= 2) {
09354 
09355         ty1  = RETURN_INFO_mtype (return_info, 0);
09356         ty2  = RETURN_INFO_mtype (return_info, 1);
09357         reg1 = RETURN_INFO_preg (return_info, 0);
09358         reg2 = RETURN_INFO_preg (return_info, 1);
09359       }
09360 
09361       else
09362         Fail_FmtAssertion("lower_intrinsic_op: more than 2 return registers");
09363         /*NOTREACHED*/
09364     }
09365 
09366     else
09367       Get_Return_Mtypes(MTYPE_To_TY(type), Complex_Not_Simulated, &ty1, &ty2);
09368 
09369     switch(type)
09370     {
09371     case MTYPE_C4:
09372     case MTYPE_C8:
09373       {
09374         PREG_NUM        rzN, izN;
09375         TYPE_ID         real = Mtype_complex_to_real(type);
09376 
09377         if (!WHIRL_Return_Info_On) 
09378           Get_Return_Pregs ( ty1, ty2, &reg1, &reg2 );
09379         Is_True((reg1 && reg2),
09380                 ("expected complex return value from intrinsic_op"));
09381 
09382         rzN = AssignExpr(block, WN_LdidPreg(real, reg1), real);
09383         izN = AssignExpr(block, WN_LdidPreg(real, reg2), real);
09384 
09385         wn = WN_Complex(type,
09386                         WN_LdidPreg(real, rzN),
09387                         WN_LdidPreg(real, izN));
09388       }
09389       break;
09390 
09391     case MTYPE_CQ:
09392      /*
09393       *  call is RSTYLE_VIA_FIRST_ARG
09394       *
09395       *  hopefully our intrinsic lowerer has inserted the address of the
09396       *  temporary area.
09397       */
09398       {
09399         TYPE_ID   real = Mtype_complex_to_real(type);
09400         TY_IDX    realTY = MTYPE_To_TY(real);
09401         WN       *temp,*temp1, *actual = WN_kid0(wn);
09402 
09403         if (WN_operator_is(actual, OPR_PARM))
09404           actual = WN_kid0(actual);
09405 
09406         temp = lower_copy_tree( actual, actions);
09407         temp1 = lower_copy_tree( actual, actions);
09408 
09409         Is_True((OPCODE_is_call(WN_opcode(wn))), ("expected call opcode"));
09410 
09411         wn = WN_Complex(type,
09412                         WN_Iload(real, 0, realTY, temp),
09413                         WN_Iload(real, MTYPE_RegisterSize(real),
09414                                  realTY, temp1));
09415       }
09416       break;
09417 
09418     default:
09419       {
09420         PREG_NUM        retReg;
09421 
09422         if (!WHIRL_Return_Info_On) 
09423           Get_Return_Pregs ( ty1, ty2, &reg1, &reg2 );
09424 
09425         Is_True((reg1 != 0), ("expected return value from intrinsic_op"));
09426         Is_True((reg2 == 0), ("cannot evaluate 2 regs into an expression"));
09427 
09428         retReg = AssignExpr(block, 
09429                             WN_LdidPreg(ty1, reg1),
09430                             type);
09431 
09432         wn = WN_LdidPreg(type, retReg);
09433       }
09434       break;
09435     }
09436     rename_reset();
09437   }
09438 
09439   /*
09440    *  These require special processing as the function return
09441    *  value must be interpreted (i think)
09442    *
09443    *        s_cmp(a, b, len_a, len_b)
09444    *            a <  b          negative
09445    *            a == 0          0
09446    *            a >  0          positive
09447    */
09448   switch (id) {
09449   case INTRN_CEQEXPR:
09450     wn = WN_EQ(Boolean_type, wn, WN_Zerocon(Boolean_type));
09451     break;
09452   case INTRN_CNEEXPR:
09453     wn = WN_NE(Boolean_type, wn, WN_Zerocon(Boolean_type));
09454     break;
09455   case INTRN_CGEEXPR:
09456     wn = WN_GE(Boolean_type, wn, WN_Zerocon(Boolean_type));
09457     break;
09458   case INTRN_CGTEXPR:
09459     wn = WN_GT(Boolean_type, wn, WN_Zerocon(Boolean_type));
09460     break;
09461   case INTRN_CLEEXPR:
09462     wn = WN_LE(Boolean_type, wn, WN_Zerocon(Boolean_type));
09463     break;
09464   case INTRN_CLTEXPR:
09465     wn = WN_LT(Boolean_type, wn, WN_Zerocon(Boolean_type));
09466     break;
09467   }
09468 
09469  /*
09470   *  The preg may need map processing
09471   */
09472   return lower_expr(block, wn, actions);
09473 }
09474 
09475 
09476 
09477 
09478 /* ====================================================================
09479  *
09480  * WN *lower_intrinsic(WN *block, WN *tree, LOWER_ACTIONS actions)
09481  *
09482  * Perform lowering (see WN_Lower description) on an expression or,
09483  * intrinsic returning lowered tree.  
09484  *
09485  * Should be called only if actions contains LOWER_INTRINSIC.
09486  *
09487  * ==================================================================== */
09488 static WN *lower_intrinsic(WN *block, WN *tree, LOWER_ACTIONS actions)
09489 {
09490 
09491   Is_True(Action(LOWER_INTRINSIC),
09492           ("actions does not contain LOWER_INTRINSIC"));
09493   Is_True(OPCODE_is_intrinsic(WN_opcode(tree)),
09494           ("expression is not intrinsic"));
09495 
09496   {
09497     INTRINSIC   id = (INTRINSIC) WN_intrinsic(tree);
09498 
09499     if (INTRN_is_actual(id))
09500     {
09501      /*
09502       *  weird fortran anachronism, we need to create an ST entry
09503       *         and pass an LDA of the address
09504       */
09505       TYPE_ID   rtype = WN_rtype(tree);
09506       WN        *lda;
09507       {
09508         TY_IDX  ty = Make_Function_Type(MTYPE_To_TY(rtype));
09509         ST     *st = Gen_Intrinsic_Function(ty, INTRN_rt_name(id));
09510         lda = WN_Lda(Pointer_type, 0, st);
09511       }
09512 
09513       WN_Delete(tree);
09514       return lower_expr(block, lda, actions);
09515     }
09516   }
09517   {
09518    /*
09519     *  Create a callblock and generate call.
09520     *  The arguments may be expanded to match the runtime routine.
09521     */
09522     WN  *call, *callblock;
09523 
09524     callblock = WN_CreateBlock();
09525 
09526     call = intrinsic_runtime(callblock, tree);
09527 
09528     callblock = lower_block(callblock, actions);
09529     WN_INSERT_BlockLast(block, callblock);
09530 
09531     if (Action(LOWER_TO_CG))
09532         actions |= LOWER_CALL;
09533     call = lower_call(block, call, actions);
09534 
09535     return call;
09536   }
09537 }
09538 
09539 
09540 /* ====================================================================
09541  *
09542  * WN *lower_actual(WN *block, WN *actual, TYPE_ID parmType, INT32 reg)
09543  *
09544  * Auxilary function to lower_call to put and actual in a register
09545  * This was motivated by -DEBUG:Varargs_Prototypes=off, where for
09546  * unprototyped calls, all floating point registers need to go in the
09547  * integer registers as well
09548  *
09549  * ==================================================================== */
09550 static WN *lower_actual(WN *block, WN *actual, TYPE_ID parmType, INT32 reg)
09551 {
09552  /*
09553   * float parm goes in int register, so convert
09554   */
09555   if (MTYPE_float(parmType) && Preg_Offset_Is_Int(reg))
09556   {
09557     TYPE_ID type = TY_mtype(ST_type(Int_Preg));
09558 
09559     actual = WN_Tas(type, ST_type(Int_Preg), actual);
09560   }
09561   
09562   {
09563     WN  *stid;
09564     ST  *regST;
09565 
09566     if (Preg_Offset_Is_Int(reg)) 
09567         regST = Int_Preg;
09568     else
09569         // keep float size in preg
09570         regST=  MTYPE_To_PREG(parmType);
09571 
09572     TYPE_ID type = TY_mtype(ST_type(regST));
09573 
09574     stid = WN_StidIntoPreg (type, reg, regST, actual);
09575     WN_Set_Linenum(stid, current_srcpos);
09576     WN_INSERT_BlockLast(block, stid);
09577   }
09578 
09579   return actual;
09580 }
09581 
09582 /* ====================================================================
09583  *  For each function generate a call to a profiler function
09584  *      __prof( &func, &call, funcname, callname, state);
09585  *  where
09586  *      state==0        before call
09587  *     state==1 after call
09588  *
09589  * ==================================================================== */
09590 
09591 static WN *lower_profile_call(WN *block, WN *tree, INT32 state,
09592                               LOWER_ACTIONS actions)
09593 {
09594   if (Gen_Profile && WN_has_sym(current_function))
09595   {
09596     WN          *profcall;
09597     char        *name;
09598 
09599     {
09600       TY_IDX  ty = Make_Function_Type(MTYPE_To_TY(MTYPE_V));
09601       ST     *st = Gen_Intrinsic_Function(ty, Gen_Profile_Name);
09602 
09603       Set_PU_no_side_effects(Pu_Table[ST_pu(st)]);
09604       Set_PU_is_pure(Pu_Table[ST_pu(st)]);
09605 
09606       profcall = WN_Call(MTYPE_V, MTYPE_V, 5, st);
09607     }
09608 
09609     ST *current_fcn_st = WN_st(current_function);
09610 
09611     WN_actual(profcall, 0) = WN_Lda(Pointer_type, 0, current_fcn_st);
09612     name = ST_name(current_fcn_st);
09613     WN_actual(profcall, 2) = WN_LdaString(name, 0, strlen(name)+1);
09614     WN_actual(profcall, 4) = WN_Intconst(MTYPE_I4, state);
09615 
09616     if (WN_has_sym(tree))
09617     {
09618       ST *st = WN_st(tree);
09619 
09620       WN_actual(profcall, 1) = WN_Lda(Pointer_type, 0, st);
09621       name = ST_name(st);
09622       WN_actual(profcall, 3) = WN_LdaString(name, 0, strlen(name)+1);
09623     }
09624     else
09625     {
09626       Is_True((WN_operator_is(tree, OPR_ICALL)),
09627               ("expected icall node, not %s", OPCODE_name(WN_opcode(tree))));
09628 
09629       WN_actual(profcall, 1)
09630         = lower_copy_tree(WN_actual(tree, WN_num_actuals(tree)), actions);
09631       WN_actual(profcall, 3) = WN_Zerocon(Pointer_type);
09632     }
09633 
09634     Gen_Profile = FALSE;
09635     profcall = lower_call(block, profcall, actions);
09636     Gen_Profile = TRUE;
09637 
09638     return profcall;
09639   }
09640   return NULL;
09641 }
09642 
09643 /* ====================================================================
09644  *
09645  * WN *lower_call(WN *block, WN *tree, LOWER_ACTIONS actions)
09646  *
09647  * Perform lowering (see WN_Lower description) on call statement <tree>,
09648  * returning lowered tree.  Should be called only if actions contains
09649  * LOWER_CALL.
09650  *
09651  * ==================================================================== */
09652 
09653 static WN *lower_call(WN *block, WN *tree, LOWER_ACTIONS actions)
09654 {
09655   INT16        i;
09656   PLOC         ploc;
09657   TY_IDX       call_ty;
09658   WN          *callblock;
09659   SRCPOS       srcpos = WN_Get_Linenum(tree);
09660   INT          num_actuals = WN_num_actuals(tree);
09661   ST          *callee_st = NULL;
09662 
09663   Is_True(OPERATOR_is_call(WN_operator(tree)),
09664           ("expected call node, not %s", OPERATOR_name(WN_operator(tree))));
09665 
09666   for (i = 0; i < WN_kid_count(tree); i++)
09667     WN_actual(tree, i) = lower_expr(block, WN_actual(tree, i), actions);
09668 
09669   /* Get the ST of the callee if available */
09670   if (WN_has_sym(tree)) {
09671     callee_st = WN_st(tree);
09672   }
09673 
09674   if (WHIRL_Return_Val_On && Action(LOWER_RETURN_VAL) && 
09675       WN_rtype(tree) == MTYPE_V &&
09676       (WN_operator(tree) == OPR_CALL || WN_operator(tree) == OPR_ICALL ||
09677        WN_operator(tree) == OPR_PICCALL)) {
09678     // if it is a call returning struct coerced to void, may need to introduce
09679     // a fake first parameter
09680     TY_IDX prototype;
09681     if (WN_operator(tree) == OPR_ICALL) 
09682       prototype = WN_ty(tree);
09683     else {
09684       ST_IDX func_stidx = WN_st_idx(tree);
09685       PU_IDX puidx = ST_pu(St_Table[func_stidx]);
09686       prototype = PU_prototype(Pu_Table[puidx]);
09687     }
09688     RETURN_INFO return_info = Get_Return_Info(TY_ret_type(prototype),
09689                                               Complex_Not_Simulated);
09690     if (RETURN_INFO_return_via_first_arg(return_info)) {
09691       ST *return_st = Gen_Temp_Symbol(TY_ret_type(prototype), ".vcall");
09692       WN *awn = WN_CreateLda(OPR_LDA, Pointer_Mtype, MTYPE_V, 0,
09693                              Make_Pointer_Type(TY_ret_type(prototype)), 
09694                              return_st);
09695       awn = lower_expr(block, awn, actions);
09696       WN *n_call = add_fake_parm(tree, awn, WN_ty(awn));
09697       WN_Delete(tree);
09698       tree = n_call;
09699     }
09700   }
09701 
09702   if (Action(LOWER_PICCALL))
09703   {
09704    /* convert a CALL to PICCALL for the following cases:
09705     *
09706     *  1. we are generating PIC code.
09707     *  2. -TARG:force_jalr
09708     *  3. We need to setup $t9.
09709     *  4. We are generating CPIC code and the callee is visible outside the
09710     *     dso.
09711     */
09712     if (WN_operator_is(tree, OPR_CALL)  &&
09713         (Force_Jalr                     ||
09714          PU_needs_t9(Pu_Table[ST_pu(callee_st)]) ||
09715          (Gen_PIC_Calls &&
09716           (Gen_PIC_Shared                       ||
09717           (Gen_PIC_Call_Shared &&
09718            ST_visible_outside_dso(*callee_st)) )))) 
09719     {
09720       INT16       n = WN_kid_count(tree);
09721       WN          *itree;
09722       /*
09723        *  convert (CALL sym args ...) into (PICCALL args ... (LDA sym)). 
09724        *  The LDA does not have an OP_PARM
09725        */
09726       itree = WN_Piccall( WN_rtype(tree), WN_desc(tree), n+1, callee_st);
09727   
09728       Is_True(callee_st == WN_st(tree),
09729               ("lower_call: something changed that Robert didn't expect!"));
09730       WN_actual(itree, n) = WN_Lda(Pointer_type, 0, callee_st);
09731       WN_Set_Linenum(itree, srcpos);
09732       WN_Set_Flags(tree, itree);
09733   
09734       while (--n >= 0)
09735         WN_actual(itree, n) = WN_actual(tree, n);
09736 
09737       if (Cur_PU_Feedback) {
09738         Cur_PU_Feedback->FB_lower_call( tree, itree );
09739       }
09740       WN_Delete(tree);
09741       tree = itree;
09742     }
09743   }
09744   
09745   if (NotAction(LOWER_CALL))
09746     return tree;
09747 
09748  /*
09749   *  For each function generate a call to a profiler function
09750   *     __prof( &func, &call, funcname, callname);
09751   */
09752   if (Gen_Profile)
09753   {
09754     WN  *profcall = lower_profile_call(block, tree, 0, actions);
09755     WN_INSERT_BlockLast (block, profcall);
09756   }
09757 
09758   callblock = WN_CreateBlock();
09759 
09760   /*
09761    * TODO:
09762    * (a) Just before each call passing a struct by value, if (part of) the
09763    *     struct can be passed in register(s), convert MLOAD into multiple
09764    *     ILOADs.  MEDIUM PRIORITY (at least detect condition)
09765    * (b) Just before each call, pass static link to nested calls.
09766    * (d) For -o32 -shared, just after returning from a call, restore $gp
09767    *     (but see bug 159929).
09768    */
09769 
09770   /*
09771    * Create block containing stores of actual loads into pregs.
09772    * The call can continue to have the original actuals, because 
09773    * we don't use that except to see the number of parameters. 
09774    *
09775    * New:  Go through the list twice to give localize an easier job
09776    *       First handle structures (there may be loop code to move the
09777    *       structure)
09778    */
09779   call_ty = (WN_operator_is(tree,OPR_ICALL) ? WN_ty(tree) :
09780              ST_pu_type(callee_st));
09781   Is_True(WN_operator_is(tree, OPR_ICALL) ||
09782           callee_st == WN_st(tree),
09783           ("lower_call: something changed that Robert didn't expect!"));
09784   ploc = Setup_Output_Parameter_Locations(call_ty);
09785 
09786   for (i = 0; i < num_actuals; i++)
09787   {
09788     WN          *parm = WN_actual(tree, i);
09789     TYPE_ID     parmType = WN_rtype(parm);
09790     WN          *actual = WN_operator_is(parm, OPR_PARM) ? WN_kid0(parm)
09791                                                          : parm;
09792 
09793     if (MTYPE_is_m(parmType))
09794     {
09795      /*
09796       * structure parameter
09797       */
09798       ploc = Get_Output_Parameter_Location( TY_Of_Parameter(parm));
09799       lower_mload_actual (callblock, actual, ploc, actions);
09800     }
09801     else if (MTYPE_is_complex(parmType) && PU_ftn_lang(Get_Current_PU()))
09802     {
09803      /*
09804       * Fortran by value can generate this construct
09805       * we must make it look like a structure parameter
09806       * Note that GCC has complex type, which should go to
09807       * normal processing (like quads).
09808       */
09809       ploc = Get_Output_Parameter_Location( TY_Of_Parameter(parm));
09810       lower_complex_actual (callblock, actual, ploc, actions);
09811     }
09812     else
09813     {
09814       ploc = Get_Output_Parameter_Location( MTYPE_To_TY(parmType));
09815     }
09816   }
09817 
09818   ploc = Setup_Output_Parameter_Locations(call_ty);
09819   for (i = 0; i < num_actuals; i++)
09820   {
09821    /*
09822     * We need to get the TY of the parameter: 
09823     * if no prototype, then we don't have a list of formals;
09824     * the actual may need to be converted if there is a prototype;
09825     * the rtype of the opcode is the converted type, so use it. 
09826     */
09827     WN         *parm = WN_actual(tree, i);
09828     TYPE_ID     parmType = WN_rtype(parm);
09829     WN         *actual = WN_operator_is(parm, OPR_PARM) ? WN_kid0(parm) : parm;
09830     TY_IDX      ty;
09831 
09832     if (MTYPE_is_m(parmType) 
09833         || (MTYPE_is_complex(parmType) && PU_ftn_lang(Get_Current_PU())) )
09834     {
09835      /*
09836       * already processed
09837       */
09838       ploc = Get_Output_Parameter_Location( TY_Of_Parameter(parm));
09839       continue;
09840     }
09841 
09842     ty =  TY_Of_Parameter(parm);
09843     ploc = Get_Output_Parameter_Location( MTYPE_To_TY(parmType));
09844     {
09845      /*
09846       *  canonicalize [I,U][1,2] types (to [I,U]4
09847       */
09848       TYPE_ID  type = Mtype_comparison( Fix_TY_mtype(ty));
09849 
09850       if (parmType != type)
09851       {
09852         DevWarn("lower_call(): line %d, parm #%d type mismatch (WN_rtype(parm)"
09853                 " = %s) (cannonical TY_mtype(parm))) %s)",
09854                 Srcpos_To_Line(WN_Get_Linenum(tree)), i,
09855                 Mtype_Name(parmType), Mtype_Name(type));
09856       }
09857     }
09858 
09859     if (PLOC_on_stack(ploc))
09860     {
09861      /*
09862       * stack offset 
09863       * We can use the preg for $sp here, but a simpler way
09864       * is to use the SP symbol. 
09865       */
09866       WN *wn;
09867 
09868       wn = WN_Stid(parmType, PLOC_offset(ploc) - Formal_Save_Area_Size
09869                              + Stack_Offset_Adjustment,
09870                    SP_Sym, ty, actual);
09871       WN_Set_Linenum(wn, srcpos);
09872       WN_INSERT_BlockLast(callblock, wn);
09873     }
09874    /*
09875     * special case (as quad -> integer doesn't make much sense).
09876     * Store argument into temp preg float parm goes in int register, so convert
09877     */
09878     else if (MTYPE_is_quad(parmType) && Preg_Offset_Is_Int(PLOC_reg(ploc)))
09879     {
09880       PREG_NUM qN;
09881 
09882       qN = AssignExpr(callblock, actual, parmType);
09883 
09884       lower_actual(callblock, WN_LdidPreg(MTYPE_F8, qN),   MTYPE_F8,
09885                    PLOC_reg(ploc));
09886 
09887       lower_actual(callblock, WN_LdidPreg(MTYPE_F8, qN+1), MTYPE_F8,
09888                    PLOC_reg(ploc)+1);
09889     }
09890     else
09891     {
09892       actual = lower_actual(callblock, actual, parmType, PLOC_reg(ploc));
09893 
09894       if (WN_operator_is(parm, OPR_PARM))
09895         WN_kid0(parm) = actual;
09896       else
09897         WN_actual(tree, i) = actual;
09898 
09899       if (! TY_has_prototype(call_ty)        &&
09900           DEBUG_Varargs_Prototypes == FALSE  &&
09901           Preg_Offset_Is_Float(PLOC_reg(ploc)))
09902       {
09903         actual = lower_copy_tree(actual, actions);
09904 
09905         if (MTYPE_is_quad(parmType))
09906         {
09907           PREG_NUM  qN;
09908 
09909           qN = AssignExpr(callblock, actual, parmType);
09910 
09911           lower_actual(callblock, WN_LdidPreg(MTYPE_F8, qN),   MTYPE_F8,
09912                        PLOC_vararg_reg(ploc));
09913           lower_actual(callblock, WN_LdidPreg(MTYPE_F8, qN+1), MTYPE_F8,
09914                        PLOC_vararg_reg(ploc)+1);
09915         }
09916         else
09917         {
09918           lower_actual(callblock, actual, parmType, PLOC_vararg_reg(ploc));
09919         }
09920       }
09921     }
09922   }
09923 
09924  /*
09925   * store param size in tree for later re-use 
09926   * unless has no prototype (then could have varying # args). 
09927   */
09928   if (num_actuals > 0 &&
09929       TY_has_prototype(call_ty) &&
09930       Get_PU_arg_area_size(call_ty) == 0 &&
09931       ! TY_is_varargs(call_ty))
09932   {
09933       Set_PU_arg_area_size(call_ty, PLOC_total_size(ploc));
09934   }
09935 
09936 
09937  /*
09938   *  copy the arguments to avoid building a dag
09939   *  (region code might delete these nodes)
09940   *  CG will use these arguments to build register usage information
09941   */
09942   {
09943     INT16       n= num_actuals;
09944 
09945     while (--n >= 0)
09946       WN_actual(tree, n) = lower_copy_tree( WN_actual(tree, n), actions);
09947   }
09948 
09949   if (MTYPE_is_complex(WN_rtype(tree)))
09950   {
09951     INT16       n = WN_kid_count(tree);
09952     WN          *itree;
09953     TYPE_ID     rtype, desc;
09954     
09955     rtype = Mtype_complex_to_real(WN_rtype(tree));
09956     desc = Mtype_complex_to_real(WN_desc(tree));
09957 
09958    /*
09959     *  For complex the call type will be changed by WN_Call()
09960     *  into (PICCALL args ... (LDA sym)).
09961     */
09962     if (WN_operator_is(tree, OPR_CALL))
09963     {
09964       itree = WN_Call( rtype, desc, n, WN_st(tree));
09965     }
09966     else if (WN_operator_is(tree, OPR_ICALL))
09967     {
09968       itree = WN_Icall( rtype, desc, n, WN_ty(tree));
09969     }
09970     WN_Set_Linenum(itree, srcpos);
09971     WN_Set_Flags(tree, itree);
09972 
09973     while (--n >= 0)
09974       WN_actual(itree, n) = WN_actual(tree, n);
09975 
09976     if (Cur_PU_Feedback) {
09977       Cur_PU_Feedback->FB_lower_call( tree, itree );
09978     }
09979     WN_Delete(tree);
09980     tree = itree;
09981   }
09982 
09983   /*
09984    *  F90 needs this 
09985    *  The callee will require the current FP or Slink in $2
09986    */
09987   if (Action(LOWER_UPLEVEL))
09988   {
09989     if (callee_st && PU_is_nested_func(Pu_Table[ST_pu(callee_st)]))
09990     {
09991       WN  *wn, *link;
09992      
09993      /*
09994       *  These are "downlevel" calls for F90 (ex mp procedures),
09995       *  or uplevel (child calls parent)
09996       *  This should only happen for F90.
09997       */
09998       if (PU_lexical_level(&St_Table[WN_st_idx(current_function)]) <
09999           PU_lexical_level(callee_st))
10000       {
10001         link = WN_LdidPreg(Pointer_type, Frame_Pointer_Preg_Offset);
10002       }
10003 
10004      /*
10005       *  Need to set up the register for "sideways" (internal calling internal)
10006       *  and uplevel calls. This should only happen for F90.
10007       */
10008       else 
10009       {
10010         ST  *slink = Find_Slink_For_Scope(WN_st(current_function),
10011                                           callee_st);
10012 
10013         link = WN_Ldid (Pointer_type, 0, slink, ST_type(slink));
10014       }
10015 
10016       wn = WN_StidIntoPreg(Pointer_type,
10017                            Static_Link_Preg_Offset,
10018                            MTYPE_To_PREG(Pointer_type), link);
10019           
10020       WN_Set_Linenum(wn, srcpos);
10021       WN_INSERT_BlockLast(callblock, wn);
10022      }
10023   }
10024 
10025   /* 
10026    * Check that stack space needed for actuals doesn't overflow 
10027    * what we initially reserved. 
10028    */
10029   Check_Actual_Stack_Size (tree);
10030 
10031   callblock = lower_block(callblock, actions);
10032   WN_INSERT_BlockLast (block, callblock);
10033 
10034   /******************************************************
10035         STUPID: cannot generate call here as it will affect the return value
10036         for this function
10037   if (Gen_Profile)
10038   {
10039     WN_INSERT_BlockLast (block, tree);
10040 
10041     return lower_profile_call(block, tree, 1, actions);
10042   }
10043   ******************************************************/
10044 
10045   return tree;
10046 }
10047 
10048 
10049 
10050 
10051 /* ====================================================================
10052  *
10053  * WN *lower_compgoto(WN *block, WN *tree, LOWER_ACTIONS actions)
10054  *
10055  * Perform lowering (see WN_Lower description) on switch val in COMPGOTO
10056  * node <tree>, returning XGOTO.
10057  *
10058  * If there is a default label, code is generated to test the range
10059  * of switch values
10060  * ==================================================================== */
10061 
10062 static WN *lower_compgoto(WN *block, WN *tree, LOWER_ACTIONS actions)
10063 {
10064   INT32         pointerSize = MTYPE_RegisterSize(Pointer_type);
10065   INT32         num_entries = WN_num_entries(tree);
10066   WN            *index, *add;
10067   ST            *table_st;
10068   LEAF          indexN, addN;
10069 
10070   Is_True(WN_opcode(tree) == OPC_COMPGOTO,
10071           ("expected COMPGOTO node, not %s", OPCODE_name(WN_opcode(tree))));
10072   Is_True(WN_num_entries(tree) > 0,
10073           ("expected COMPGOTO nu,_entries > 0 not %d", WN_num_entries(tree)));
10074 
10075   WN_kid0(tree) = lower_expr(block,
10076                              WN_Coerce(Pointer_type, WN_kid0(tree)),
10077                              actions);
10078 
10079   if (NotAction(LOWER_COMPGOTO))
10080     return tree;
10081 
10082   index = WN_kid0(tree);
10083 
10084   indexN = Make_Leaf(block, WN_Coerce(Pointer_type, index), Pointer_type);
10085 
10086  /*
10087   * create fake, incomplete array type so table_st has correct size
10088   *
10089   *  generate jump for computed goto
10090   *    agoto ( & table + (i * sizeof(Pointer_type)));
10091   *
10092   *  create
10093   *    addN = table + (i * sizeof(Pointer_type));
10094   */
10095   {
10096     TY_IDX table;
10097     WN  *mpy;
10098 
10099     table = Make_Array_Type(Pointer_type, 1, num_entries);
10100 
10101     table_st = Gen_Read_Only_Symbol (table, "jump_table");
10102     Set_ST_is_initialized(table_st);    /* so goes in rdata section */
10103     
10104     mpy = WN_Mpy(Pointer_type, 
10105                  Load_Leaf(indexN),
10106                  WN_Intconst(Pointer_type, pointerSize));
10107 
10108     add = WN_Add(Pointer_type,
10109                  WN_Lda (Pointer_type, 0, table_st),
10110                  mpy);
10111     addN = Make_Leaf(block, add, Pointer_type);
10112   }
10113   
10114  /*
10115   *  for default cases we must verify the index fall in range
10116   */
10117   WN *wn_truebr = NULL;
10118   if (WN_kid_count(tree) == 3)
10119   {
10120    /*
10121     *  branch to default if (index >= n)
10122     *  because the indexN is unsigned, we do not have to compare 
10123     *  greater then zero
10124     */
10125     WN  *ge, *truebr;
10126     WN  *def  = WN_kid2(tree);
10127 
10128     ge =  WN_GE(Pointer_type,
10129                 Load_Leaf(indexN),
10130                 WN_Intconst(Pointer_type, num_entries));
10131 
10132     truebr = lower_truebr(WN_label_number(def), ge, &wn_truebr, actions);
10133     WN_INSERT_BlockLast(block, truebr);
10134   }
10135 
10136  /*
10137   * create fake, incomplete array type so table_st has correct size
10138   *
10139   *  generate jump for computed goto
10140   *    agoto ( & table + (i * sizeof(Pointer_type)));
10141   */
10142   {
10143     WN  *xgoto;
10144     WN  *gotoTable = WN_kid1(tree);
10145 
10146     index = WN_Iload(Pointer_type,
10147                      0,
10148                      MTYPE_To_TY(Pointer_type),
10149                      Load_Leaf(addN));
10150 
10151     index = lower_expr(block, index, actions);
10152 
10153     xgoto = WN_CreateXgoto(num_entries, index, gotoTable, table_st);
10154     WN_Set_Linenum (xgoto, WN_Get_Linenum(tree));
10155 
10156     // Lower feedback info
10157     if ( Cur_PU_Feedback )
10158       Cur_PU_Feedback->FB_lower_compgoto( tree, xgoto, wn_truebr );
10159 
10160     return xgoto;
10161   }
10162 }
10163 
10164 
10165 
10166 
10167 /* ====================================================================
10168  *
10169  * WN *lower_assert(WN *block, WN *tree, LOWER_ACTIONS actions)
10170  *
10171  * Perform lowering (see WN_Lower description) on OPC_ASSERT
10172  * node <tree>, returning structured if
10173  *
10174  * ==================================================================== */
10175 
10176 static WN *lower_assert(WN *block, WN *tree, LOWER_ACTIONS actions)
10177 {
10178   WN  *if_else, *if_then, *IF, *trap, *cond;
10179 
10180   Is_True(WN_opcode(tree) == OPC_ASSERT,
10181           ("expected ASSERT node, not %s", OPCODE_name(WN_opcode(tree))));
10182 
10183   WN_kid0(tree) = lower_expr(block, WN_kid0(tree), actions);
10184 
10185   if (NotAction(LOWER_ASSERT))
10186     return tree;
10187 
10188   if_then = WN_CreateBlock();
10189   if_else = WN_CreateBlock();
10190   cond = lower_expr(block, WN_kid0(tree), actions);
10191 
10192  /*
10193   * generate intrinsic call 
10194   */
10195   switch ( WN_offset(tree) ) {
10196     case WN_TRAP_F77_BOUNDS_ERROR:
10197       {
10198         char *name;
10199         WN **kids = (WN **) alloca(4 * sizeof(WN *));
10200 
10201         /* add blank at end of string cause s_rnge wants one */
10202         kids[0] = WN_LdaString ( "? ", 0, 2 );
10203         kids[1] = WN_Intconst ( MTYPE_I4, -1 ); /* cause of s_rnge weirdness */
10204 
10205         /* s_rnge expects name with _ at end */
10206         name = ST_name(&St_Table[PU_Info_proc_sym(Current_PU_Info)]);
10207         kids[2] = WN_LdaString ( name, 0, strlen(name)+1 );
10208 
10209         kids[3] = WN_Intconst(MTYPE_I4, Srcpos_To_Line(WN_Get_Linenum(tree)));
10210         trap = WN_Create_Intrinsic ( OPC_VINTRINSIC_CALL,
10211                                      INTRN_F77_BOUNDS_ERR, 4, kids );
10212       } 
10213       break;
10214 
10215     case WN_TRAP_C_BOUNDS_ERROR:
10216       /* Check DEBUG_Verbose_Runtime.  If set, call __C_runtime_error;
10217        * otherwise emit a BRK_RANGE trap.
10218        */
10219       /* TODO PV 443095:  This doesn't have descriptive parameters due
10220        * to limitations on the ASSERT node.  Fix that eventually.
10221        */
10222       if ( DEBUG_Verbose_Runtime ) {
10223         char *name;
10224         WN **kids = (WN **) alloca(4 * sizeof(WN *));
10225 
10226         /* __C_runtime_error ( BRK_RANGE, PU_name, line_no, fmt, ...);
10227          */
10228 
10229         // 'BRK_RANGE' is SGI specific meaning 'range error check'
10230 #if defined(__sgi)
10231         kids[0] = WN_Intconst ( MTYPE_I4, BRK_RANGE );
10232 #else
10233         fprintf(stderr, "Don't know how to do BRK_RANGE\n");
10234         exit(-1);
10235 #endif
10236 
10237         /* Source routine where error occurs: */
10238         name = ST_name(&St_Table[PU_Info_proc_sym(Current_PU_Info)]);
10239         kids[1] = WN_LdaString ( name, 0, strlen(name)+1 );
10240 
10241         /* Source line where error occurs: */
10242         kids[2] = WN_Intconst ( MTYPE_I4,
10243                                 Srcpos_To_Line(WN_Get_Linenum(tree)) );
10244 
10245         /* Eventually, this should be a printf format and arguments,
10246          * describing the case that fails (i.e. array and index).
10247          * For now, the ASSERT node doesn't have the right kids.
10248          */
10249         kids[3] = WN_LdaString ( "unknown array", 0, 14 );
10250 
10251         /* Make the call: */
10252         trap = WN_Create_Intrinsic ( OPC_VINTRINSIC_CALL,
10253                                      INTRN_RT_ERR, 4, kids );
10254       } else {
10255 
10256         // 'BRK_RANGE' is SGI specific meaning 'range error check'
10257 #if defined(__sgi)
10258         trap = WN_CreateTrap ( BRK_RANGE );
10259 #else   
10260         fprintf(stderr, "Don't know how to do BRK_RANGE\n");
10261         exit(-1);
10262 #endif  
10263 
10264         // ADD FEEDBACK INFO ??
10265       }
10266       break;
10267 
10268     default:
10269       trap = WN_CreateTrap ( WN_offset(tree) );
10270       // ADD FEEDBACK INFO ??
10271       break;
10272   }
10273 
10274   WN_Set_Linenum(trap, WN_Get_Linenum(tree));
10275   WN_INSERT_BlockLast(if_else, trap);
10276 
10277   IF = WN_CreateIf(cond, if_then, if_else);
10278   // ADD FEEDBACK INFO !!
10279   WN_Set_Linenum(IF, WN_Get_Linenum(tree));
10280   WN_Delete(tree);
10281 
10282   IF = lower_scf(block, IF, actions);
10283   return IF;
10284 }
10285 
10286 
10287 static WN *lower_branch(WN *block, WN *tree, LOWER_ACTIONS actions)
10288 {
10289   Is_True((WN_opcode(tree) == OPC_TRUEBR || WN_opcode(tree) == OPC_FALSEBR),
10290           ("expected true/false"));
10291 
10292   WN * const kid = lower_expr(block, WN_kid0(tree), actions);
10293   WN_kid0(tree) = kid;
10294 
10295   if (WN_operator(kid) == OPR_LNOT)
10296   {
10297     switch(WN_opcode(tree))
10298     {
10299     case OPC_TRUEBR:
10300       WN_set_opcode(tree, OPC_FALSEBR);
10301       break;
10302 
10303     case OPC_FALSEBR:
10304       WN_set_opcode(tree, OPC_TRUEBR);
10305       break;
10306 
10307     default:
10308       break;
10309     }
10310 
10311     WN_kid0(tree) = WN_kid0(kid);
10312     WN_Delete(kid);
10313   }
10314 
10315   return tree;
10316 }
10317  
10318  
10319 /* ====================================================================
10320  *
10321  * WN *lower_return_val(WN *block, WN *tree, LOWER_ACTIONS actions)
10322  *
10323  * Perform lowering (see WN_Lower description) on RETURN_VAL nodes
10324  * turning kid0 expression into an appropriate store and the RETURN_VAL
10325  * into a RETURN.
10326  *
10327  * ==================================================================== */
10328 
10329 static WN *lower_return_val(WN *block, WN *tree, LOWER_ACTIONS actions)
10330 {
10331   PREG_NUM    preg;
10332   ST         *preg_st;
10333   TYPE_ID     mtype;
10334   RETURN_INFO return_info;
10335   WN         *wn;
10336 
10337   Is_True((WN_operator(tree) == OPR_RETURN_VAL),
10338           ("expected RETURN_VAL node, not %s", OPCODE_name(WN_opcode(tree))));
10339 
10340   TYPE_ID return_mtype = WN_rtype(tree);
10341 
10342   if (return_mtype != MTYPE_M) {
10343     TY_IDX return_ty_idx = Be_Type_Tbl(return_mtype);
10344     return_info = Get_Return_Info (return_ty_idx, Use_Simulated);
10345 
10346     WN_kid0(tree) = lower_expr (block, WN_kid0(tree), actions);
10347     if (RETURN_INFO_return_via_first_arg(return_info)) { // fake first parm
10348       // This happens, for example, if a complex result is returned for ia32.
10349       // Create an istore; an mstore with a single complex value seemed
10350       // to confuse things later on.
10351       WN *first_formal = WN_formal(current_function, 0);
10352       TY_IDX tidx = ST_type(WN_st(first_formal));
10353       OPCODE const_op = OPCODE_make_op(OPR_INTCONST, MTYPE_I8, MTYPE_V);
10354       // WN *swn = WN_CreateIntconst (const_op, TY_size(return_ty_idx));
10355       WN *awn = WN_CreateLdid(OPR_LDID, 
10356                               TY_mtype(Ty_Table[tidx]), 
10357                               TY_mtype(Ty_Table[tidx]),
10358                               WN_idname_offset(first_formal), 
10359                               WN_st(first_formal), 
10360                               tidx);
10361       // wn  = WN_CreateMstore (0, tidx, WN_kid0(tree), awn, swn);
10362       wn = WN_CreateIstore(OPR_ISTORE, MTYPE_V,
10363                            return_mtype, 0, tidx, WN_kid0(tree), awn);
10364     } else {  // Returned in preg
10365       Is_True(RETURN_INFO_count(return_info) == 1,
10366               ("expected return_info count to be 1"));
10367 
10368       mtype   = RETURN_INFO_mtype (return_info, 0);
10369       preg    = RETURN_INFO_preg (return_info, 0);
10370       preg_st = (MTYPE_is_float(mtype) ? Float_Preg :
10371                  ((mtype==MTYPE_I8 || mtype==MTYPE_U8) ? MTYPE_To_PREG(mtype) : 
10372                   Int_Preg));
10373 
10374       wn  = WN_CreateStid (OPR_STID, MTYPE_V, Promoted_Mtype[mtype], 
10375                            preg, preg_st, Be_Type_Tbl(mtype), WN_kid0(tree));
10376     }
10377     WN_INSERT_BlockLast (block, wn);
10378   }
10379   else { // MTYPE_M; rhs is one of MLDID or MILOAD or MLOAD
10380     WN *o_rhs = WN_kid0(tree); 
10381     OPERATOR rhs_opr = WN_operator(o_rhs);
10382     TY_IDX ty_idx = WN_ty(o_rhs);
10383     if (OPERATOR_is_load(rhs_opr) && WN_field_id(o_rhs) != 0) {
10384       if (rhs_opr == OPR_ILOAD || rhs_opr == OPR_LDID) 
10385         ty_idx = get_field_type(ty_idx, WN_field_id(o_rhs));
10386       else { // OPR_MLOAD
10387         ty_idx = TY_pointed(Ty_Table[ty_idx]);
10388         ty_idx = get_field_type(ty_idx, WN_field_id(o_rhs));
10389       }
10390     }
10391     return_info = Get_Return_Info(ty_idx, Complex_Not_Simulated);
10392 
10393     if (RETURN_INFO_return_via_first_arg(return_info)) { // fake first parm
10394       Is_True(RETURN_INFO_count(return_info) == 0, 
10395               ("expected RETURN_INFO to have 0 count"));
10396       WN *n_rhs;
10397 
10398       // fix rhs
10399       if (WN_operator(o_rhs) == OPR_LDID)
10400         n_rhs = lower_mldid(block, o_rhs, LOWER_MLDID_MSTID);
10401       else if (WN_operator(o_rhs) == OPR_ILOAD) 
10402         n_rhs = lower_miload(block, o_rhs, LOWER_MLDID_MSTID);
10403       else n_rhs = o_rhs;               // MLOAD
10404 
10405       // create an mstore
10406       WN *first_formal = WN_formal(current_function, 0);
10407       TY_IDX tidx = ST_type(WN_st(first_formal));
10408       WN *awn = WN_CreateLdid(OPR_LDID, 
10409                               TY_mtype(Ty_Table[tidx]), 
10410                               TY_mtype(Ty_Table[tidx]),
10411                               WN_idname_offset(first_formal), 
10412                               WN_st(first_formal), 
10413                               tidx);
10414       WN *swn = WN_CopyNode(WN_kid1(n_rhs));
10415       wn  = WN_CreateMstore (0, tidx, n_rhs, awn, swn);
10416 
10417       WN_INSERT_BlockLast (block, wn);
10418     }
10419     else { // return in return registers
10420       INT32 i;
10421       WN *n_rhs;
10422       UINT algn;
10423       TY_IDX ty_idx_used;
10424 
10425       if (WN_operator(o_rhs) == OPR_LDID) {
10426         Is_True(WN_rtype(o_rhs) == MTYPE_M,
10427                 ("expected RETURN_VAL kid not type M"));
10428 
10429         algn = TY_align(ty_idx);
10430         for (i = 0; i < RETURN_INFO_count(return_info); i++) {
10431           mtype = RETURN_INFO_mtype(return_info, i);
10432           ty_idx_used = Be_Type_Tbl(mtype);
10433           Set_TY_align(ty_idx_used, algn);
10434           n_rhs = WN_CreateLdid (OPR_LDID, mtype, mtype, 
10435                                  WN_load_offset(o_rhs)
10436                                    + i * MTYPE_byte_size(mtype),
10437                                  WN_st_idx(o_rhs), ty_idx_used);
10438           preg    = RETURN_INFO_preg (return_info, i);
10439           preg_st = MTYPE_is_float(mtype) ? Float_Preg : Int_Preg;
10440           wn = WN_CreateStid(OPR_STID, MTYPE_V, mtype, preg, preg_st, 
10441                              Be_Type_Tbl(mtype), n_rhs);
10442           WN_INSERT_BlockLast (block, wn);
10443         }
10444       }
10445       else if (WN_operator(o_rhs) == OPR_ILOAD) {
10446         Is_True(WN_rtype(o_rhs) == MTYPE_M,
10447                 ("expected RETURN_VAL kid not type M"));
10448 
10449         algn = TY_align(ty_idx);
10450         for (i = 0; i < RETURN_INFO_count(return_info); i++) {
10451           mtype = RETURN_INFO_mtype(return_info, i);
10452           ty_idx_used = Be_Type_Tbl(mtype);
10453           Set_TY_align(ty_idx_used, algn);
10454           if (i == 0)
10455             n_rhs = WN_kid0(o_rhs);
10456           else n_rhs = WN_COPY_Tree(WN_kid0(o_rhs));
10457           n_rhs = WN_CreateIload(OPR_ILOAD, mtype, mtype,
10458                                  WN_load_offset(o_rhs)
10459                                    + i * MTYPE_byte_size(mtype),
10460                                  ty_idx_used,
10461                                  Make_Pointer_Type(ty_idx_used), n_rhs);
10462           n_rhs = lower_expr(block, n_rhs, actions);
10463           preg    = RETURN_INFO_preg (return_info, i);
10464           preg_st = MTYPE_is_float(mtype) ? Float_Preg : Int_Preg;
10465           wn = WN_CreateStid(OPR_STID, MTYPE_V, mtype, preg, preg_st, 
10466                              Be_Type_Tbl(mtype), n_rhs);
10467           WN_INSERT_BlockLast (block, wn);
10468         }
10469       }
10470       else { // MLOAD
10471         Is_True(WN_operator(WN_kid1(o_rhs)) == OPR_INTCONST,
10472                 ("expected RETURN_VAL's MLOAD kid to be of constant size"));
10473         algn = TY_align(TY_pointed(WN_load_addr_ty(o_rhs)));
10474         for (i = 0; i < RETURN_INFO_count(return_info); i++) {
10475           mtype = RETURN_INFO_mtype(return_info, i);
10476           ty_idx_used = Be_Type_Tbl(mtype);
10477           Set_TY_align(ty_idx_used, algn);
10478           if (i == 0)
10479             n_rhs = WN_kid0(o_rhs);
10480           else n_rhs = WN_COPY_Tree(WN_kid0(o_rhs));
10481           n_rhs = WN_CreateIload(OPR_ILOAD, mtype, mtype,
10482                                  WN_load_offset(o_rhs)
10483                                    + i * MTYPE_byte_size(mtype),
10484                                  ty_idx_used,
10485                                  Make_Pointer_Type(ty_idx_used), n_rhs);
10486           n_rhs = lower_expr(block, n_rhs, actions);
10487           preg    = RETURN_INFO_preg (return_info, i);
10488           preg_st = MTYPE_is_float(mtype) ? Float_Preg : Int_Preg;
10489           wn = WN_CreateStid(OPR_STID, MTYPE_V, mtype, preg, preg_st, 
10490                              Be_Type_Tbl(mtype), n_rhs);
10491           WN_INSERT_BlockLast (block, wn);
10492         }
10493       }
10494 
10495       WN_Delete (o_rhs);
10496     }
10497   }
10498 
10499   WN *wn_return = WN_CreateReturn ();
10500   if ( Cur_PU_Feedback )
10501     Cur_PU_Feedback->FB_lower_return_val( tree, wn_return );
10502   tree = wn_return;
10503   return tree;
10504 }
10505 
10506 
10507 //Since Parm node allows only integer type, we need to 
10508 //promote char and short to int 
10509 static TYPE_ID get_parm_type(int rtype) {
10510 
10511   if (rtype == MTYPE_I1 || rtype == MTYPE_I2) {
10512     return MTYPE_I4;
10513   }
10514   if (rtype == MTYPE_U1 || rtype == MTYPE_U2) {
10515     return MTYPE_U4;
10516   }
10517   return rtype;
10518 }
10519 
10520 /*
10521   static TY_IDX Get_Field_Type(TY_IDX base, int field_id) {
10522   
10523   if (!(TY_kind(base) == KIND_STRUCT)) {
10524   cerr << "CALLING GET_FIELD_TYPE with a non struct type" << endl;
10525   return base;
10526   }
10527   FLD_HANDLE fh = TY_fld(base);
10528   for (int i = 1; i < field_id; i++, fh = FLD_next(fh));
10529   return FLD_type(fh);
10530   }
10531 */
10532 
10533 static WN* get_TLD_call(TYPE_ID rtype, WN* param, TY_IDX ty_idx) {
10534   
10535   WN* kids[1];
10536   WN* var = WN_CreateParm(rtype, param, ty_idx, WN_PARM_BY_VALUE);
10537   kids[0] = var;
10538   return WN_Create_Intrinsic(OPR_INTRINSIC_OP, TY_mtype(Make_Pointer_Type(ty_idx)), MTYPE_V, INTRN_TLD_ADDR, 1, kids);
10539 }
10540 
10541 static bool TY_not_shared(TY_IDX idx) {
10542   
10543   return !(TY_is_shared(idx) || idx == shared_ptr_idx || idx == pshared_ptr_idx);
10544 }
10545 
10546 /*
10547  * Perform lowering for TLD variables, which must be converted to TLD_ADDR(...) in the output C file
10548  */
10549 static WN* lower_TLD(WN* block, WN* wn, LOWER_ACTIONS actions) {
10550 
10551   if (!Action(LOWER_UPC_TO_INTR)) {
10552     return wn;
10553   }
10554 
10555   ST_IDX idx = WN_st_idx(wn);
10556   ST st = St_Table[idx];
10557   TY_IDX ty_idx = ST_type(idx);
10558   TYPE_ID rtype = TY_mtype(ty_idx);
10559 
10560   int sclass = ST_sclass(st);
10561   if (TY_not_shared(ty_idx) && 
10562       ST_class(st) != CLASS_CONST &&
10563       (sclass == SCLASS_PSTATIC || sclass == SCLASS_FSTATIC || 
10564        sclass == SCLASS_COMMON || sclass == SCLASS_EXTERN ||
10565        sclass == SCLASS_UGLOBAL || sclass == SCLASS_DGLOBAL)) {
10566     //variable is TLD
10567     
10568 
10569     TY_IDX ptr_ty = Make_Pointer_Type(ty_idx);
10570     if (WN_field_id(wn) != 0) {
10571       //storing into a field, set type appropriately
10572       TY_IDX fld_idx = get_field_type(ty_idx, WN_field_id(wn));
10573       ptr_ty = Make_Pointer_Type(fld_idx);
10574       rtype = TY_mtype(fld_idx);
10575     }
10576 
10577     rtype = get_parm_type(rtype);
10578     WN* res;
10579     WN* ld = WN_Ldid(rtype, WN_offset(wn), idx, ty_idx, WN_field_id(wn)); 
10580     res = get_TLD_call(rtype, ld, ty_idx);
10581     switch (WN_operator(wn)) {
10582     case OPR_STID: {
10583       WN* val = lower_expr(block, WN_kid(wn, 0), actions); 
10584       //cout << "DONE TLD STORE: " << ST_name(st) << endl;  
10585       return WN_CreateIstore(OPR_ISTORE, MTYPE_V, WN_rtype(val), 0, ptr_ty, val, res, 0); 
10586     }
10587     case OPR_LDID:
10588       //cout << "DONE TLD LOAD" << endl;
10589       return WN_CreateIload(OPR_ILOAD, rtype, rtype, 0, TY_pointed(ptr_ty), ptr_ty, res, 0); 
10590     default:
10591       Is_True(0, ("Unexpected Operator in lower_TLD: %d", WN_operator(wn)));
10592     }
10593   }
10594   return wn;
10595 }
10596 
10597 static WN* lower_TLD_lda(WN* block, WN* wn, LOWER_ACTIONS actions) {
10598 
10599   if (!Action(LOWER_UPC_TO_INTR)) {
10600     return wn;
10601   }
10602 
10603   ST_IDX idx = WN_st_idx(wn);
10604   ST st = St_Table[idx];
10605   TY_IDX ty_idx = ST_type(idx);
10606   TYPE_ID rtype = TY_mtype(ty_idx);
10607   int sclass = ST_sclass(st);
10608   if (TY_not_shared(ty_idx) && 
10609       ST_class(st) != CLASS_CONST &&
10610       (sclass == SCLASS_PSTATIC || sclass == SCLASS_FSTATIC || 
10611        sclass == SCLASS_COMMON || sclass == SCLASS_EXTERN ||
10612        sclass == SCLASS_UGLOBAL || sclass == SCLASS_DGLOBAL)) {
10613     WN* res;
10614     WN* ld = WN_Ldid(rtype, WN_offset(wn), idx, ST_type(st));
10615     res = get_TLD_call(rtype, ld, ty_idx); 
10616     //cout << "DONE TLD LDA" << endl;
10617     return res;
10618   }
10619   return wn;
10620 }
10621 
10622 
10623 /* ====================================================================
10624  *
10625  * WN *lower_stmt(WN *block, WN *tree, LOWER_ACTIONS actions)
10626  *
10627  * Perform lowering (see WN_Lower description) on statement <tree>,
10628  * returning lowered tree.  Usually a single statement is returned, but
10629  * in some cases, lowering (e.g. of complex stores) produces a BLOCK of
10630  * statements.
10631  *
10632  * ==================================================================== */
10633 
10634 static WN *lower_stmt(WN *block, WN *tree, LOWER_ACTIONS actions)
10635 {
10636   CURRENT_STATE stmtState = pushCurrentState(tree, actions);
10637 
10638   Is_True(OPCODE_is_stmt(WN_opcode(tree)),
10639           ("expected statement node, not %s", OPCODE_name(WN_opcode(tree))));
10640   switch(WN_operator(tree))
10641   {
10642 
10643   case OPR_PRAGMA:
10644     if (Action(LOWER_UPC_TO_INTR)) {
10645       switch(WN_pragma(tree)) {
10646       case WN_PRAGMA_UPC_STRICT_CONSISTENCY_START:
10647         consistency_stack.push(STRICT_CONSISTENCY);
10648         break;
10649       case WN_PRAGMA_UPC_RELAXED_CONSISTENCY_START:
10650         consistency_stack.push(RELAXED_CONSISTENCY);
10651         break;
10652       case WN_PRAGMA_UPC_STRICT_CONSISTENCY_STOP:
10653       case WN_PRAGMA_UPC_RELAXED_CONSISTENCY_STOP:
10654         consistency_stack.pop();
10655         break;
10656       }
10657       return tree;
10658     }
10659     break;
10660   case OPR_CALL:
10661   case OPR_ICALL:
10662   case OPR_PICCALL:
10663     tree = lower_call(block, tree, actions);
10664     break;
10665 
10666   case OPR_INTRINSIC_CALL:
10667     tree = lower_intrinsic_call(block, tree, actions);
10668     break;
10669 
10670   case OPR_ISTORE:
10671   case OPR_STID:
10672   case OPR_MSTORE: {
10673     if (WN_operator(tree) == OPR_STID) {
10674      //  WN* res = lower_TLD(block, tree, actions);
10675 //       if (res != tree) {
10676 //      tree = res;
10677 //      break;
10678 //       }
10679     }
10680 
10681     tree = lower_store(block, tree, actions);
10682     break;
10683   }
10684 
10685   case OPR_COMPGOTO:
10686     tree = lower_compgoto(block, tree, actions);
10687     break;
10688 
10689   case OPR_IO:
10690     if (Action(LOWER_IO_STATEMENT))
10691     {
10692       if (traceIO)
10693       {
10694           fputs(DBar, TFile);
10695           fprintf(TFile, "Io Lower: Before Lowering\n");
10696           fdump_tree(TFile, tree);
10697           fputs(DBar, TFile);
10698       }
10699 
10700       tree = lower_io_statement(tree, actions);
10701 
10702       if (traceIO)
10703       {
10704           fputs(DBar, TFile);
10705           fprintf(TFile, "Io Lower: After Lowering\n");
10706           fdump_tree(TFile, tree);
10707           fputs(DBar, TFile);
10708       }
10709     }
10710     break;
10711   case OPR_ALTENTRY:
10712     tree = lower_entry(tree, actions);
10713     break;
10714 
10715   case OPR_EVAL:
10716     tree = lower_eval(block, tree, actions);
10717     break;
10718 
10719   case OPR_LABEL:
10720    /*
10721     *  lower loop info for CG (it will process these opt>0
10722     */
10723     if (WN_label_loop_info(tree))
10724     {
10725       WN  *infoblock= WN_CreateBlock();
10726       WN  *info=      WN_label_loop_info(tree);
10727 
10728       info = lower_expr(infoblock, info, actions);
10729       WN_set_label_loop_info(tree, info);
10730     }
10731     break;
10732 
10733   case OPR_EXC_SCOPE_BEGIN:
10734    /*
10735     *  We don't want to lower the kids, which are not used to generate code,
10736     * but only to provide information to the optimizer. 
10737     */
10738     break;
10739 
10740   case OPR_REGION_EXIT:
10741    /*
10742     *  convert REGION_EXIT to GOTO
10743     */
10744     if (Action(LOWER_REGION_EXITS)) 
10745       WN_set_opcode(tree, OPC_GOTO);
10746     break;
10747 
10748   case OPR_ASSERT:
10749     tree = lower_assert(block, tree, actions);
10750     break;
10751 
10752   case OPR_TRUEBR:
10753   case OPR_FALSEBR:
10754     tree = lower_branch(block, tree, actions);
10755     break;
10756 
10757   case OPR_RETURN_VAL:
10758     if (Action(LOWER_RETURN_VAL))
10759       tree = lower_return_val(block, tree, actions);
10760     else
10761       WN_kid0(tree) = lower_expr(block, WN_kid0(tree), actions);
10762     break;
10763 
10764   case OPR_ASM_STMT:
10765     {
10766       // Lower only the input expressions
10767       INT16 i;
10768       for (i = 2; i < WN_kid_count(tree); i++) {
10769         WN_kid0(WN_kid(tree,i)) = lower_expr(block, WN_kid0(WN_kid(tree,i)), actions);
10770       }
10771       break;
10772     }
10773 
10774   default: 
10775     {
10776       INT16 i;
10777       for (i = 0; i < WN_kid_count(tree); i++)
10778         WN_kid(tree,i) = lower_expr(block, WN_kid(tree,i), actions);
10779     }
10780   }
10781 
10782   popCurrentState(stmtState);
10783   return tree;
10784 }
10785 
10786 /* ====================================================================
10787  *
10788  * WN *replace_ldidPreg(WN *expr, PREG_NUM reg, WN *replacement)
10789  * 
10790  *  walk expr looking for an ldid of preg reg.
10791  *  if found (expect only one of them), replace the ldid with replacement
10792  *
10793  *  if replacement is NULL we are doing a dryrun to test if there is a value
10794  *
10795  * ==================================================================== */
10796 
10797 static WN *replace_ldidPreg(WN *expr, PREG_NUM reg, WN *replacement)
10798 {
10799   INT16 i;
10800 
10801   if (expr==NULL)
10802     return NULL;
10803 
10804   for (i = 0; i < WN_kid_count(expr); i++)
10805   {
10806     WN  *child= WN_kid(expr, i);
10807 
10808     if ((WN_operator_is(child, OPR_LDID))       &&
10809         (WN_class(child) == CLASS_PREG)         &&
10810         (WN_load_offset(child) == reg))
10811     {
10812       if (replacement)
10813       {
10814         WN_kid(expr, i) = replacement;
10815       }
10816       return child;
10817     }
10818 
10819     {
10820       WN  *tree;
10821       if (tree = replace_ldidPreg(child, reg, replacement))
10822         return tree;
10823     }
10824   }
10825   return NULL;
10826 }
10827 
10828 /* ====================================================================
10829  *
10830  * 
10831  * WN *lower_intrinsic_call(WN *block, WN *tree, LOWER_ACTIONS actions)
10832  *
10833  * intrinsic calls have the special problem of defining a return
10834  * register that is used in the next stmt
10835  *
10836  * It is required that the emulation routine either
10837  *  [1]         passes the corresponding call node back
10838  *      or
10839  *  [2]         returns a value (typically ldid preg)
10840  *              this value must replace the return register which
10841  *              should be in the next whirl statement (fchow says so)
10842  *
10843  * ==================================================================== */
10844 static WN *lower_intrinsic_call(WN *block, WN *tree, LOWER_ACTIONS actions)
10845 { 
10846   WN            *next, *em, *newBlock;
10847   INTRINSIC     id = (INTRINSIC) WN_intrinsic(tree);
10848   SRCPOS srcpos = WN_Get_Linenum(tree);
10849   TYPE_ID       type;
10850   PREG_NUM      reg1, reg2;
10851   BOOL intrinsic_lowered;
10852 
10853   Is_True(OPCODE_is_stmt(WN_opcode(tree)),
10854           ("expected statement node, not %s", OPCODE_name(WN_opcode(tree))));
10855   {
10856    /*
10857     *  first lower the children
10858     */
10859     INT16 i;
10860     for (i = 0; i < WN_kid_count(tree); i++)
10861       WN_kid(tree,i) = lower_expr(block, WN_kid(tree,i), actions);
10862   }
10863 
10864   if (INTRN_cg_intrinsic(id))
10865     return tree;
10866 
10867   if (NotAction(LOWER_INTRINSIC |
10868                 LOWER_INLINE_INTRINSIC |
10869                 LOWER_INL_STACK_INTRINSIC)) {
10870     return tree;
10871   }
10872   else if (NotAction(LOWER_INL_STACK_INTRINSIC)) {
10873     INTRINSIC intr = (INTRINSIC) WN_intrinsic(tree);
10874     if (intr == INTRN_U4I4SETSTACKPOINTER ||
10875         intr == INTRN_U8I8SETSTACKPOINTER ||
10876         intr == INTRN_U4READSTACKPOINTER ||
10877         intr == INTRN_U8READSTACKPOINTER ||
10878         intr == INTRN_U4I4ALLOCA ||
10879         intr == INTRN_U8I8ALLOCA) {
10880       return tree;
10881     }
10882   }
10883 
10884   next = WN_next(tree);
10885   type = WN_rtype(tree);
10886   newBlock = WN_CreateBlock();
10887 
10888  /*
10889   *  see if statement return value exists in the next statement
10890   *  but don't replace it
10891   */
10892   {
10893     TYPE_ID     ty1, ty2;
10894     BOOL        returnValueUnused = FALSE;
10895 
10896     if (WHIRL_Return_Info_On) {
10897 
10898       RETURN_INFO return_info = Get_Return_Info (MTYPE_To_TY(type),
10899                                                  Complex_Not_Simulated);
10900 
10901       if (RETURN_INFO_count(return_info) <= 2) {
10902 
10903         ty1  = RETURN_INFO_mtype (return_info, 0);
10904         ty2  = RETURN_INFO_mtype (return_info, 1);
10905         reg1 = RETURN_INFO_preg (return_info, 0);
10906         reg2 = RETURN_INFO_preg (return_info, 1);
10907       }
10908 
10909       else
10910         ErrMsg (EC_Unimplemented,
10911                 "lower_intrinsic_call: more than 2 return registers");
10912     }
10913 
10914     else {
10915       Get_Return_Mtypes(MTYPE_To_TY(type), Complex_Not_Simulated, &ty1, &ty2);
10916       Get_Return_Pregs(ty1, ty2, &reg1, &reg2);
10917     }
10918 
10919     if (MTYPE_is_void(type))
10920     {
10921       returnValueUnused = TRUE;
10922     }
10923     if (replace_ldidPreg(next, reg1, NULL)==NULL)
10924     {
10925       returnValueUnused = TRUE;
10926     }
10927     if (returnValueUnused && INTRN_has_no_side_effects(id))
10928     {
10929       DevWarn("lower_intrinsic_call(): function %s is void or unused and has"
10930               " no_side_effects. It will be removed", get_intrinsic_name(id));
10931 
10932       return newBlock;
10933     }
10934   }
10935 
10936   em = lower_emulation(newBlock, tree, actions, intrinsic_lowered);
10937 
10938  /*
10939   *  Nothing happened (ie. the intrinsic was not an INLINE
10940   *  and we should go no further
10941   */
10942   if ((Action(LOWER_INLINE_INTRINSIC) ||
10943        Action(LOWER_INL_STACK_INTRINSIC)) && 
10944       NotAction(LOWER_INTRINSIC)          &&
10945       tree == em)
10946   {
10947     WN_Delete(newBlock);
10948     return tree;
10949   }
10950 
10951   WN_Delete(tree);
10952 
10953   if (OPCODE_is_call(WN_opcode(em)))
10954   {
10955     WN_Set_Linenum (em, srcpos);
10956     WN_INSERT_BlockLast(block, newBlock);
10957     return em;
10958   }
10959   else if (WN_is_block(em))
10960   {
10961     WN_INSERT_BlockLast(block, newBlock);
10962     return em;
10963   }
10964   else if (MTYPE_is_void(type))
10965   {
10966     if (OPCODE_is_stmt(WN_opcode(em)))
10967     {
10968       WN_INSERT_BlockLast(newBlock, em);
10969     }
10970     return newBlock;
10971   }
10972   else
10973   {
10974     /*
10975      *  so far we only expand __builtin_alloca() and the memset routines.
10976      *  This code will need to change based on different return sequences
10977      */
10978     Is_True((reg1 != 0), ("expected return value from intrinsic_call"));
10979     Is_True((reg2 == 0), ("cannot evaluate 2 regs into an expression"));
10980     Is_True((OPCODE_is_expression(WN_opcode(em))), ("expected expression"));
10981     {
10982       WN        *replaced = NULL;
10983 
10984       /*
10985        *  In the next statement replace an ldid of preg reg1 with em
10986        *  The use of the function may have been deleted, but the function
10987        *  still may have side effects!
10988        *
10989        *  We are guaranteed the result is in the "next" statement BTW
10990        */
10991       replaced = replace_ldidPreg(next, reg1, em);
10992 
10993       if (replaced)
10994       { /* CVTL-RELATED */
10995         Is_True(Types_are_compatible(WN_rtype(replaced),type),
10996                 ("return reg mismatch type"));
10997       }
10998       return newBlock;
10999     }
11000   }
11001 }
11002 
11003 
11004 
11005 
11006 /* ====================================================================
11007  *
11008  * WN *lower_block(WN *tree, LOWER_ACTIONS actions)
11009  *
11010  * Perform lowering (see WN_Lower description) on statements in BLOCK
11011  * node <tree>, returning (possibly) modified BLOCK.
11012  *
11013  * ==================================================================== */
11014 
11015 WN *lower_block(WN *tree, LOWER_ACTIONS actions)
11016 {
11017   WN *out, *node, *next_node;
11018   CURRENT_STATE blockState;
11019 
11020   Is_True(WN_opcode(tree) == OPC_BLOCK,
11021           ("expected BLOCK node, not %s", OPCODE_name(WN_opcode(tree))));
11022 
11023   blockState = pushCurrentState(tree, actions);
11024 
11025   out = WN_CreateBlock();
11026   WN_Set_Linenum (out, current_srcpos);
11027 
11028   for (node = WN_first(tree); node; node = next_node)
11029   {
11030 
11031     /*  MP pragmas are handled in a very special manner.  There are three forms
11032         of parallel constructs - standalone parallel directive, parallel loop
11033         (doacross) and parallel region.
11034         A standalone parallel directive starts with an MP pragma node and is
11035         followed by (depending on the directive) a series of statements ended
11036         with another, specific MP pragma node.
11037         Parallel loops start with an MP pragma node followed by a series of MP
11038         pragmas and assignment statements ended with a DO_LOOP node.
11039         A parallel region is an OPC_REGION created by the FE which encapsulates
11040         all statements within the region.  It will always have a func_pragma
11041         list containing MP pragmas.  To all but the MP lowerer, this region is
11042         transparent.
11043         If MP lowering is in effect, then this entire set of nodes needs to be
11044         removed from the statement chain, translated and replaced with one or
11045         more statement/scf nodes.  Because a set of nodes must be processed
11046         as a unit, the usual lowering scheme of passing in a single node (tree)
11047         and returning a single node (tree) won't work.  */
11048 
11049     while (Action(LOWER_MP) && node &&
11050       ((((WN_opcode(node) == OPC_PRAGMA) || (WN_opcode(node) == OPC_XPRAGMA))
11051         && (WN_pragmas[WN_pragma(node)].users & PUSER_MP)) ||
11052        ((WN_opcode(node) == OPC_REGION) && WN_first(WN_region_pragmas(node)) &&
11053         ((WN_opcode(WN_first(WN_region_pragmas(node))) == OPC_PRAGMA) ||
11054          (WN_opcode(WN_first(WN_region_pragmas(node))) == OPC_XPRAGMA)) &&
11055         (WN_pragmas[WN_pragma(WN_first(WN_region_pragmas(node)))].users &
11056          PUSER_MP))))
11057         node = lower_mp(out, node, actions);
11058     if (node == NULL) break;
11059 
11060     /*
11061      *  Must read WN_next(node) now since it may be overwritten
11062      */
11063     next_node = WN_next(node);
11064     setCurrentState(node, actions);
11065 
11066     if (OPCODE_is_stmt(WN_opcode(node)))
11067     {
11068         node = lower_stmt(out, node, actions);
11069     }
11070     else if (OPCODE_is_scf(WN_opcode(node)))
11071     {
11072         node = lower_scf(out, node, actions);
11073     }
11074     else
11075     {
11076         Fail_FmtAssertion("expected statement or SCF node, not %s",
11077                           OPCODE_name(WN_opcode(tree)));
11078         /*NOTREACHED*/
11079     }
11080 
11081     if (node == NULL) // lowering an MSTID of Return_Val_Preg can cause NULL
11082       continue;
11083 
11084     WN_INSERT_BlockLast(out, node);
11085   
11086     // if STID(ALLOCA) and trapuv, insert a mstore
11087     if ( Action(LOWER_INL_STACK_INTRINSIC) && DEBUG_Trap_Uv
11088         && WN_operator(node) == OPR_STID
11089         && WN_operator(WN_kid0(node)) == OPR_ALLOCA)
11090     {
11091         lower_trapuv_alloca (out, WN_kid0(node), actions);
11092     }
11093   }
11094 
11095  /*
11096   *  Once we have the integrated block, remove any stmt after
11097   *  a return or goto, until we hit a label or ALTENTRY
11098   *  only if we are not called by lower_scf_non_recursive()
11099   *
11100   *  Curiously enough, this is needed to prevent dead blocks (-O0)
11101   *  which causes exception handling to fail ...
11102   *  
11103   */
11104   if (NotAction(LOWER_TOP_LEVEL_ONLY))
11105   {
11106     for (node = WN_first(out); node; node = next_node)
11107     {
11108       next_node = WN_next(node);
11109   
11110       if (WN_unconditional_goto(node))
11111       {
11112         for(node = next_node; node; node = next_node)
11113         {
11114           next_node = WN_next(node);
11115   
11116           if (WN_operator_is(node, OPR_LABEL))
11117             break;
11118           else if (WN_operator_is(node, OPR_ALTENTRY))
11119             break;
11120           else if (WN_operator_is(node, OPR_EXC_SCOPE_BEGIN))
11121             continue;
11122           else if (WN_operator_is(node, OPR_EXC_SCOPE_END))
11123             continue;
11124           else if (WN_operator_is(node, OPR_PRAGMA))
11125             continue;
11126           else if (WN_operator_is(node, OPR_XPRAGMA))
11127             continue;
11128           else if (WN_operator_is(node, OPR_REGION_EXIT))
11129             continue;
11130           if (OPCODE_is_stmt(WN_opcode(node)))
11131           {
11132             WN_DELETE_FromBlock(out, node);
11133           }
11134           else
11135             break;
11136         }
11137       }
11138     }
11139   }
11140 
11141   WN_Delete(tree);
11142 
11143   popCurrentState(blockState);
11144   return out;
11145 }
11146 
11147 
11148 /* ====================================================================
11149  *
11150  * WN *lower_speculate(WN *block, WN *tree, LOWER_ACTIONS actions)
11151  *
11152  * try to speculate CAND/CIOR to LAND/LIOR
11153  * Edge frequency data is discarded
11154  *
11155  * ==================================================================== */
11156 
11157 static WN *lower_speculate(WN *block, WN *tree, LOWER_ACTIONS actions)
11158 {
11159   INT32 n;
11160   BOOL  speculate = TRUE;
11161 
11162   if (OPT_Lower_Speculate == FALSE)
11163     return tree;
11164 
11165   switch(WN_operator(tree))
11166   {
11167   case OPR_CAND:
11168   case OPR_CIOR:
11169   case OPR_CSELECT:
11170     for (n = 0; n < WN_kid_count(tree); n++)
11171     {
11172       WN_kid(tree, n) = lower_speculate(block, WN_kid(tree, n), actions);
11173       speculate &=      expr_is_speculative(WN_kid(tree, n));
11174     }
11175 
11176     if (speculate)
11177     {
11178       if (WN_operator_is(tree, OPR_CAND))
11179       {
11180         WN *land = WN_LAND( WN_kid0(tree), WN_kid1(tree) );
11181         WN_Delete(tree);
11182         return land;
11183       }
11184       else if (WN_operator_is(tree, OPR_CIOR))
11185       {
11186         WN *lior = WN_LIOR( WN_kid0(tree), WN_kid1(tree) );
11187         WN_Delete(tree);
11188         return lior;
11189       }
11190       else if (WN_operator_is(tree, OPR_CSELECT))
11191       {
11192         WN *select = WN_Select(WN_rtype(tree), WN_kid0(tree), WN_kid1(tree),
11193                                WN_kid2(tree));
11194   
11195         WN_Delete(tree);
11196         return select;
11197       }
11198     }
11199     break;
11200   }
11201 
11202   return tree;
11203 }
11204 
11205 /* ====================================================================
11206  *
11207  * WN *lower_conditional(WN *block, WN *tree, BOOL branchType,
11208  *                       LOWER_ACTIONS actions)
11209  *
11210  * lower CAND/CIOR to scf
11211  *
11212  * ==================================================================== */
11213 
11214 static WN *
11215 lower_conditional(WN *block, WN *tree, LABEL_IDX trueLabel,
11216                   LABEL_IDX falseLabel, BOOL branchType,
11217                   LOWER_ACTIONS actions)
11218 {
11219   WN *shortcircuit, *left_branch = NULL, *right_branch = NULL;
11220 
11221   switch(WN_operator(tree))
11222   {
11223   case OPR_CAND:
11224    /*
11225     *   Process the left child.
11226     *   We need a label for the children to branch to
11227     */
11228     if (WN_operator_is(WN_kid0(tree), OPR_CAND) ||
11229         WN_operator_is(WN_kid0(tree), OPR_CIOR))
11230     {
11231       shortcircuit = WN_NewLabel();
11232 
11233       lower_conditional(block, WN_kid0(tree), WN_label_number(shortcircuit),
11234                         falseLabel, FALSE, actions);
11235       WN_INSERT_BlockLast(block, shortcircuit);
11236     }
11237     else
11238     {
11239       left_branch = WN_Falsebr(falseLabel, WN_kid0(tree));
11240       WN_INSERT_BlockLast(block, left_branch);
11241     }
11242 
11243    /*
11244     *   Process the right child.
11245     */
11246     if (WN_operator_is(WN_kid1(tree), OPR_CAND) ||
11247         WN_operator_is(WN_kid1(tree), OPR_CIOR))
11248     {
11249       lower_conditional(block, WN_kid1(tree), trueLabel, falseLabel,
11250                         branchType, actions);
11251     }
11252     else {
11253       if ( branchType /*==TRUE*/ ) {
11254         right_branch = WN_Truebr(trueLabel, WN_kid1(tree));
11255         WN_INSERT_BlockLast(block, right_branch);
11256       }
11257       else {
11258         /* branchType == FALSE */
11259         right_branch = WN_Falsebr(falseLabel, WN_kid1(tree));
11260         WN_INSERT_BlockLast(block, right_branch);
11261       }
11262     }
11263     if (Cur_PU_Feedback) {
11264       Cur_PU_Feedback->FB_lower_circuit( tree, left_branch, right_branch );
11265     }
11266     return NULL;
11267 
11268   case OPR_CIOR:
11269    /*
11270     *   Process the left child.
11271     *   We need a label for the children to branch to
11272     */
11273     if (WN_operator_is(WN_kid0(tree), OPR_CAND) ||
11274         WN_operator_is(WN_kid0(tree), OPR_CIOR))
11275     {
11276       shortcircuit = WN_NewLabel();
11277 
11278       lower_conditional(block, WN_kid0(tree), trueLabel,
11279                         WN_label_number(shortcircuit), TRUE, actions);
11280       WN_INSERT_BlockLast(block, shortcircuit);
11281     }
11282     else
11283     {
11284       left_branch = WN_Truebr(trueLabel, WN_kid0(tree));
11285       WN_INSERT_BlockLast(block, left_branch);
11286     }
11287 
11288    /*
11289     *   Process the right child.
11290     */
11291     if (WN_operator_is(WN_kid1(tree), OPR_CAND) ||
11292         WN_operator_is(WN_kid1(tree), OPR_CIOR))
11293     {
11294       lower_conditional(block, WN_kid1(tree), trueLabel, falseLabel,
11295                         branchType, actions);
11296     }
11297     else {
11298       if ( branchType /*==TRUE*/ ) {
11299         right_branch = WN_Truebr(trueLabel, WN_kid1(tree));
11300         WN_INSERT_BlockLast(block, right_branch);
11301       }
11302       else {
11303         /* branchType == FALSE */
11304         right_branch = WN_Falsebr(falseLabel, WN_kid1(tree));
11305         WN_INSERT_BlockLast(block, right_branch);
11306       }
11307     }
11308     if (Cur_PU_Feedback) {
11309       Cur_PU_Feedback->FB_lower_circuit( tree, left_branch, right_branch );
11310     }
11311     return NULL;
11312 
11313   default:
11314     tree = lower_expr(block, tree, actions);
11315     break;
11316   }
11317 
11318   return tree;
11319 }
11320 
11321 static WN *lower_branch_condition(BOOL branchType, LABEL_IDX label, WN *cond,
11322                                   WN **branch, LOWER_ACTIONS actions)
11323 {
11324   WN *condBlock = WN_CreateBlock();
11325 
11326   cond = lower_speculate(condBlock, cond, actions);
11327 
11328   *branch = NULL;
11329 
11330   switch(WN_operator(cond))
11331   {
11332   case OPR_CAND:
11333   case OPR_CIOR:
11334     {
11335       LABEL_IDX shortcircuit_lbl;
11336       shortcircuit_lbl = NewLabel();
11337 
11338       if (branchType == TRUE)
11339       {
11340         cond = lower_conditional(condBlock, cond, label, shortcircuit_lbl,
11341                                  branchType, actions);
11342       }
11343       else
11344       {
11345         cond = lower_conditional(condBlock, cond, shortcircuit_lbl, label,
11346                                  branchType, actions);
11347       }
11348 
11349       condBlock = lower_block(condBlock, actions);
11350       WN_INSERT_BlockLast(condBlock, WN_Label(shortcircuit_lbl));
11351     }
11352     break;
11353   default:
11354     {
11355       cond = lower_expr(condBlock, cond, actions);
11356 
11357       if (branchType)
11358         *branch = WN_Truebr(label, cond);
11359       else
11360         *branch = WN_Falsebr(label, cond);
11361       WN_INSERT_BlockLast(condBlock, *branch);
11362     }
11363   }
11364   return condBlock;
11365 }
11366 
11367 #ifdef SHORTCIRCUIT_HACK
11368 /* return TRUE if the expression <tree> has a CAND/CIOR that cannot
11369  * be converted into LAND/LIOR respectively.
11370  */
11371 static BOOL tree_has_cand_cior (WN *tree)
11372 {
11373   WN_ITER *wni;
11374   WN *wn;
11375 
11376   for (wni = WN_WALK_TreeIter (tree); 
11377        wni != NULL;
11378        wni = WN_WALK_TreeNext (wni))
11379   {
11380     wn = WN_ITER_wn (wni);
11381     /* TODO: check if the CAND/CIOR can be converted to LAND/LIOR */
11382     if (WN_operator_is(wn, OPR_CAND)    ||
11383         WN_operator_is(wn, OPR_CIOR)    ||
11384         WN_operator_is(wn, OPR_CSELECT))
11385       return TRUE;
11386   }
11387   return FALSE;
11388 }
11389 #endif
11390 
11391 /* ====================================================================
11392  *
11393  * WN *lower_if(WN *block, WN *tree, LOWER_ACTIONS actions)
11394  *
11395  * Perform lowering (see WN_Lower description) on statements in IF
11396  * node <tree>, returning lowered statements.  Returned tree will always
11397  * have a structured control flow node (at least a BLOCK) at the top.
11398  *
11399  * ==================================================================== */
11400 
11401 static WN *lower_if(WN *block, WN *tree, LOWER_ACTIONS actions)
11402 {
11403   Is_True(WN_opcode(tree) == OPC_IF,
11404           ("expected IF node, not %s", OPCODE_name(WN_opcode(tree))));
11405 
11406   if (WN_Is_If_MpVersion(tree))
11407     return lower_block(lower_mp(block, tree, actions), actions);
11408 
11409 #ifndef SHORTCIRCUIT_HACK
11410   if (Action(LOWER_IF))
11411 #else
11412   if (Action(LOWER_IF) || 
11413       (Action(LOWER_SHORTCIRCUIT) && tree_has_cand_cior(WN_if_test(tree))))
11414 #endif
11415   {
11416    /*
11417     *  Lower IF.  This is done differently depending on
11418     *  whether the "then" or "else" clauses are empty.
11419     * 
11420     *  Pay close attention to the block scope and state while creating nodes
11421     */
11422     WN *body = WN_CreateBlock();
11423     WN *wn_branch = NULL;
11424     LABEL_IDX cont_lbl;
11425     cont_lbl = NewLabel();
11426 
11427     if (Action(LOWER_TOP_LEVEL_ONLY))
11428     {
11429       actions = RemoveScfAction(actions);
11430     }
11431 
11432     if (WN_block_nonempty(WN_then(tree)))
11433     {
11434       if (WN_block_nonempty(WN_else(tree)))
11435       {
11436        /*
11437         * Both "then" and "else" clauses exist.  Generate:
11438         *       (FALSEBR <cond> <else_lbl>)
11439         *       <then_clause>
11440         *       (GOTO <cont_lbl>)
11441         *       (LABEL <else_lbl>)
11442         *       <else_clause>
11443         *       (LABEL <cont_lbl>)
11444         */
11445         LABEL_IDX else_lbl;
11446         else_lbl = NewLabel();
11447 
11448         WN *falsebr_block = lower_falsebr(else_lbl, WN_if_test(tree),
11449                                           &wn_branch, actions);
11450         WN_INSERT_BlockFirst(body, falsebr_block);
11451 
11452         setCurrentStateBlockLast(WN_then(tree), actions);
11453         WN_INSERT_BlockLast(body, lower_block(WN_then(tree), actions));
11454         WN *wn_goto = WN_Goto(cont_lbl);
11455         WN_INSERT_BlockLast(body, wn_goto);
11456 
11457         WN *wn_else_lbl = WN_Label(else_lbl);
11458         WN_INSERT_BlockLast(body, wn_else_lbl);
11459         setCurrentStateBlockLast(WN_else(tree), actions);
11460         WN_INSERT_BlockLast(body, lower_block(WN_else(tree), actions));
11461         WN *wn_cont_lbl = WN_Label(cont_lbl);
11462         WN_INSERT_BlockLast(body, wn_cont_lbl);
11463       } 
11464       else
11465       {
11466        /*
11467         * Only "then" clause exists.  Generate:
11468         *       (FALSEBR <cond> <cont_lbl>)
11469         *       <then_clause>
11470         *       (LABEL <cont_lbl>)
11471         */
11472         WN *falsebr_block = lower_falsebr(cont_lbl, WN_if_test(tree),
11473                                           &wn_branch, actions);
11474         WN_INSERT_BlockFirst(body, falsebr_block);
11475 
11476         setCurrentStateBlockLast(WN_then(tree), actions);
11477         WN_INSERT_BlockLast(body, lower_block(WN_then(tree), actions));
11478         WN *wn_cont_lbl = WN_Label(cont_lbl);
11479         WN_INSERT_BlockLast(body, wn_cont_lbl);
11480       }
11481 
11482       if (Cur_PU_Feedback) {
11483         Cur_PU_Feedback->FB_lower_branch( tree, wn_branch );
11484       }
11485 
11486       WN_Delete(tree);
11487       return body;
11488     } 
11489     else if (WN_block_nonempty(WN_else(tree)))
11490     {
11491      /*
11492       * Only "else" clause exists.  Generate:
11493       *         (TRUEBR <cond> <cont_lbl>)
11494       *         <else_clause>
11495       *         (LABEL <cont_lbl>)
11496       */
11497       WN *truebr_block = lower_truebr(cont_lbl, WN_if_test(tree),
11498                                       &wn_branch, actions);
11499       WN_INSERT_BlockFirst(body, truebr_block);
11500 
11501       setCurrentStateBlockLast(WN_else(tree), actions);
11502       WN_INSERT_BlockLast(body, lower_block(WN_else(tree), actions));
11503       WN *wn_cont_lbl = WN_Label(cont_lbl);
11504       WN_INSERT_BlockLast(body, wn_cont_lbl);
11505 
11506       if (Cur_PU_Feedback) {
11507         Cur_PU_Feedback->FB_lower_branch( tree, wn_branch );
11508       }
11509 
11510       WN_Delete(tree);
11511       return body;
11512     }
11513     else
11514     {
11515      /*
11516       * Neither "then" or "else" clause exists.  Generate:
11517       *         (EVAL <cond>)
11518       */
11519       WN *eval;
11520 
11521       eval = WN_CreateExp1(OPC_EVAL, lower_expr(block, WN_if_test(tree),
11522                                                 actions));
11523       WN_Set_Linenum (eval, current_srcpos);
11524 
11525       if (Cur_PU_Feedback) {
11526         Cur_PU_Feedback->FB_lower_branch( tree, NULL );
11527       }
11528 
11529       WN_DELETE_Tree(WN_then(tree));
11530       WN_DELETE_Tree(WN_else(tree));
11531       WN_Delete(tree);
11532       return eval;
11533     }
11534   }
11535   else if (NotAction(LOWER_TOP_LEVEL_ONLY))
11536   {
11537     WN_if_test(tree) = lower_expr(block, WN_if_test(tree),
11538                                   RemoveShortCircuitAction(actions));
11539     WN_then(tree) = lower_block(WN_then(tree), actions);
11540     WN_else(tree) = lower_block(WN_else(tree), actions);
11541   }
11542 
11543   return tree;
11544 }
11545 
11546 
11547 
11548 
11549 /* ====================================================================
11550  *
11551  * WN *lower_do_loop(WN *block, WN *tree, LOWER_ACTIONS actions)
11552  *
11553  * Perform lowering (see WN_Lower description) on statements in DO_LOOP
11554  * node <tree>, returning lowered statements.  Returned tree will always
11555  * have a structured control flow node (at least a BLOCK) at the top.
11556  *
11557  * ==================================================================== */
11558 
11559 static WN *lower_do_loop(WN *block, WN *tree, LOWER_ACTIONS actions)
11560 {
11561   WN *loop_info;
11562 
11563   Is_True(WN_opcode(tree) == OPC_DO_LOOP,
11564           ("expected DO_LOOP node, not %s", OPCODE_name(WN_opcode(tree))));
11565 
11566   loop_info = WN_do_loop_info(tree);  
11567   loop_nest_depth = loop_info ? WN_loop_depth(loop_info) : loop_nest_depth+1;
11568 
11569   if (Action(LOWER_DO_LOOP))
11570   {
11571    /*
11572     *  Lower DO_LOOP.  Generate:
11573     *   <start>
11574     *   (FALSEBR <end> <cont_lbl>)              ; unless nz_trip flag set
11575     *   (LABEL <top_lbl> <loop_info>)
11576     *   <body>
11577     *   <step>
11578     *   (TRUEBR <end> <top_lbl>)
11579     *  (LABEL <cont_lbl>)                       ; unless nz_trip flag set
11580     */
11581     BOOL nz_trip = loop_info && WN_Loop_Nz_Trip(loop_info);
11582     WN *wn_top_branch = NULL, *wn_back_branch = NULL;
11583     WN *body = WN_CreateBlock();
11584 
11585     if (Action(LOWER_TOP_LEVEL_ONLY))
11586     {
11587       actions = RemoveScfAction(actions);
11588     }
11589 
11590     contains_a_loop = FALSE;
11591    /*
11592     *  create loop info for CG
11593     *  it must be lowered as CG processes this
11594     */
11595     if (loop_info == NULL)
11596     {
11597       WN *infoblock = WN_CreateBlock();
11598       WN *trip_count = WN_LOOP_TripCount(tree);
11599 
11600       /* Set the nz_trip if we can */
11601       if (trip_count && WN_operator_is(trip_count, OPR_INTCONST) &&
11602           WN_const_val(trip_count) > 0) {
11603          nz_trip = TRUE;
11604       }
11605       loop_info = WN_CreateLoopInfo(WN_index(tree),
11606                                     trip_count,
11607                                     0,
11608                                     loop_nest_depth,
11609                                     contains_a_loop ? 0 : WN_LOOP_INNERMOST);
11610       loop_info = lower_expr(infoblock, loop_info, actions);
11611       WN_Set_Loop_Nz_Trip(loop_info);
11612       WN_DELETE_Tree(infoblock);
11613     }
11614     else if (WN_loop_induction(loop_info) != WN_index(tree))
11615     {
11616       WN_DELETE_Tree(WN_index(tree));
11617     }
11618 
11619     WN_INSERT_BlockLast(body, lower_stmt(block, WN_start(tree), actions));
11620 
11621     WN *cont_lbl;
11622     if (nz_trip == FALSE)
11623     {
11624       WN *end = lower_copy_tree(WN_end(tree), actions);
11625 
11626       if (Cur_PU_Feedback)
11627         Cur_PU_Feedback->FB_clone_loop_test( WN_end(tree), end, tree );
11628 
11629       cont_lbl = WN_NewLabel();
11630       WN *top_branch_block = lower_falsebr(WN_label_number(cont_lbl), end,
11631                                            &wn_top_branch, actions);
11632       WN_INSERT_BlockLast(body, top_branch_block);
11633     }
11634 
11635     setCurrentState(WN_do_body(tree), actions);
11636 
11637     LABEL_IDX top_lbl_idx;
11638     top_lbl_idx = NewLabel();
11639 
11640     WN *top_lbl = WN_CreateLabel(ST_IDX_ZERO, top_lbl_idx, 0, loop_info);
11641     WN_INSERT_BlockLast(body, top_lbl);
11642 
11643     WN_INSERT_BlockLast(body, lower_block(WN_do_body(tree), actions));
11644 
11645     setCurrentState(WN_step(tree), actions);
11646     WN_INSERT_BlockLast(body, lower_stmt(block, WN_step(tree), actions));
11647     WN *back_branch_block = lower_truebr(WN_label_number(top_lbl),
11648                                          WN_end(tree), &wn_back_branch,
11649                                          actions);
11650     WN_INSERT_BlockLast(body, back_branch_block);
11651 
11652     if (nz_trip == FALSE) {
11653       WN_INSERT_BlockLast(body, cont_lbl);
11654     }
11655 
11656     if ( Cur_PU_Feedback )
11657       Cur_PU_Feedback->FB_lower_loop( tree, wn_top_branch, wn_back_branch );
11658 
11659     WN_Delete(tree);
11660 
11661     tree = body;
11662   }
11663   else if (NotAction(LOWER_TOP_LEVEL_ONLY))
11664   {
11665     WN_start(tree) = lower_stmt(block, WN_start(tree), actions);
11666     WN_end(tree) = lower_expr(block, WN_end(tree), actions);
11667     WN_step(tree) = lower_stmt(block, WN_step(tree), actions);
11668     WN_do_body(tree) = lower_block(WN_do_body(tree), actions);
11669   }
11670 
11671   --loop_nest_depth;
11672   contains_a_loop = TRUE;
11673   return tree;
11674 }
11675 
11676 
11677 
11678 /* ====================================================================
11679  *
11680  * WN *lower_do_while(WN *block, WN *tree, LOWER_ACTIONS actions)
11681  *
11682  * Perform lowering (see WN_Lower description) on statements in DO_WHILE
11683  * node <tree>, returning lowered statements.  Returned tree will always
11684  * have a structured control flow node (at least a BLOCK) at the top.
11685  *
11686  * ==================================================================== */
11687 
11688 static WN *lower_do_while(WN *block, WN *tree, LOWER_ACTIONS actions)
11689 {
11690   Is_True(WN_opcode(tree) == OPC_DO_WHILE,
11691           ("expected DO_WHILE node, not %s", OPCODE_name(WN_opcode(tree))));
11692 
11693   ++loop_nest_depth;
11694 #ifndef SHORTCIRCUIT_HACK
11695   if (Action(LOWER_DO_WHILE))
11696 #else
11697   if (Action(LOWER_DO_WHILE) || 
11698       (Action(LOWER_SHORTCIRCUIT) && tree_has_cand_cior (WN_while_test(tree))))
11699 #endif
11700   {
11701    /*
11702     * Lower DO_WHILE.  Generate:
11703     *   (LABEL <top_lbl>)
11704     *   <body>
11705     *   (TRUEBR <test> <top_lbl>)
11706     */
11707     WN *body = WN_CreateBlock();
11708     WN *top_lbl = WN_NewLabel();
11709 
11710     if (Action(LOWER_TOP_LEVEL_ONLY))
11711     {
11712       actions = RemoveScfAction(actions);
11713     }
11714     WN_INSERT_BlockFirst(body, top_lbl);
11715     WN_INSERT_BlockLast(body, lower_block(WN_while_body(tree), actions));
11716 
11717     WN *wn_back_branch = NULL;
11718     WN *back_branch_block
11719       = lower_truebr(WN_label_number(top_lbl), WN_while_test(tree),
11720                      &wn_back_branch, actions);
11721     WN_INSERT_BlockLast(body, back_branch_block);
11722 
11723     if ( Cur_PU_Feedback )
11724       Cur_PU_Feedback->FB_lower_loop( tree, NULL, wn_back_branch );
11725 
11726     WN_Delete(tree);
11727     tree = body;
11728   }
11729   else if (NotAction(LOWER_TOP_LEVEL_ONLY))
11730   {
11731     WN *testBlock = WN_CreateBlock();
11732 
11733     WN_while_body(tree) = lower_block(WN_while_body(tree), actions);
11734 
11735     WN_while_test(tree) = lower_expr(testBlock, WN_while_test(tree), actions);
11736 
11737     WN_INSERT_BlockLast(WN_while_body(tree), testBlock);
11738   }
11739 
11740   --loop_nest_depth;
11741   contains_a_loop = TRUE;
11742   return tree;
11743 }
11744 
11745 // map the old label name to the new one
11746 static map<int, int> label_map;
11747 #if defined(USING_HASH_SET)
11748 static hash_set<int> labels;
11749 #else
11750 static set<int> labels;
11751 #endif
11752 
11753 static WN *lower_while_do(WN *block, WN *tree, LOWER_ACTIONS actions);
11754 
11761 static WN* rename_labels(WN* wn) {
11762 
11763   WN* result;
11764   switch ( WN_operator(wn) ) {
11765     
11766   case OPR_BLOCK: {
11767     result = WN_CreateBlock();
11768     WN* next = WN_first(wn);
11769     while (next != NULL) {
11770       WN_INSERT_BlockLast(result, rename_labels(next));
11771       next = WN_next(next);
11772     }
11773     break;
11774   }
11775 
11776   case OPR_DO_WHILE:
11777     result = WN_CreateDoWhile(WN_COPY_Tree(WN_while_test(wn)), rename_labels(WN_while_body(wn)));
11778     break;
11779 
11780   case OPR_WHILE_DO:
11781     result = WN_CreateWhileDo(WN_COPY_Tree(WN_while_test(wn)), rename_labels(WN_while_body(wn)));
11782     break;
11783 
11784   case OPR_IF:
11785     result = WN_CreateIf(WN_COPY_Tree(WN_if_test(wn)), rename_labels(WN_then(wn)), rename_labels(WN_else(wn)));
11786     break;
11787 
11788   case OPR_CASEGOTO:
11789   case OPR_TRUEBR:
11790   case OPR_FALSEBR:
11791   case OPR_GOTO:
11792   case OPR_LABEL: {
11793     result = WN_COPY_Tree(wn);
11794     int label = WN_label_number(wn);
11795     if (WN_operator(wn) == OPR_GOTO) {
11796       //catch the break out of affinity loop case
11797       if (labels.find(label) == labels.end()) {
11798         //cout << "label not present: " << label << endl;
11799         break;
11800         //this is a goto to the end of loop, so we don't rename it
11801       }
11802     }
11803 
11804     if (label_map[label] == 0) {
11805       LABEL_IDX new_label; 
11806       LABEL_Init (New_LABEL (CURRENT_SYMTAB, new_label), 0, LKIND_DEFAULT);
11807       label_map[label] = new_label;
11808     }
11809     //update the label number
11810     WN_label_number(result) = label_map[label];
11811     break;
11812   }
11813 
11814   case OPR_SWITCH: 
11815     result = WN_COPY_Tree(wn);
11816     for (int i = 0; i < WN_kid_count(result); i++) {
11817       WN_kid(result, i) = rename_labels(WN_kid(result, i));
11818     }
11819     break;
11820 
11821   default:
11822     result = WN_COPY_Tree(wn);
11823   }
11824 
11825   return result;
11826 }
11827 
11832 static void find_labels(WN* wn) {
11833  
11834   switch ( WN_operator(wn) ) {
11835     
11836   case OPR_BLOCK: {
11837     WN* next = WN_first(wn);
11838     while (next != NULL) {
11839       find_labels(next);
11840       next = WN_next(next);
11841     }
11842     break;
11843   }
11844 
11845   case OPR_DO_WHILE:
11846     find_labels(WN_while_body(wn));
11847     break;
11848 
11849   case OPR_WHILE_DO:
11850     find_labels(WN_while_body(wn));
11851     break;
11852 
11853   case OPR_IF:
11854     find_labels(WN_then(wn));
11855     find_labels(WN_else(wn));
11856     break;
11857 
11858   case OPR_SWITCH: 
11859     for (int i = 0; i < WN_kid_count(wn); i++) {
11860       find_labels(WN_kid(wn, i));
11861     }
11862     break;
11863 
11864   case OPR_LABEL: 
11865     labels.insert(WN_label_number(wn));
11866     break;
11867   default:
11868     break;
11869   }
11870 }
11871 
11906 static WN* lower_forall_ctrl(WN* block, WN* tree, WN* prag, LOWER_ACTIONS actions) {
11907 
11908    //reinit the data structures
11909   label_map.clear();
11910   labels.clear();
11911 
11912   WN* test = WN_while_test(tree);
11913   //WN* aff_body = WN_first(WN_while_body(tree));
11914   //WN* loop_body = WN_then(aff_body);  
11915   //This relies on the front end always inserting the pragma right after the affinity test
11916   WN* aff_body = WN_prev(prag);
11917   Is_True(WN_opcode(aff_body) == OPC_IF,
11918           ("expected IF node for affinity test, not %s", OPCODE_name(WN_opcode(tree))));
11919   WN* loop_body = WN_then(aff_body);  
11920   WN* label = WN_next(WN_next(aff_body));  
11921   WN* incr = WN_next(label);
11922 
11923   WN* if_expr = WN_Ldid(MTYPE_I4, 0, upc_forall_control_st, ST_type(upc_forall_control_st));
11924   //WN* if_expr = WN_CreateExp2(OPC_I4I4EQ, WN_Intconst(MTYPE_I4, 0), WN_Intconst(MTYPE_I4, 1));
11925 
11926   find_labels(tree);
11927   loop_body = rename_labels(loop_body);
11928 
11929   label = WN_COPY_Tree(label);
11930   int label_num = WN_label_number(label);
11931   if (label_map[label_num] == 0) {
11932     LABEL_IDX new_label; 
11933     LABEL_Init (New_LABEL (CURRENT_SYMTAB, new_label), 0, LKIND_DEFAULT);
11934     label_map[label_num] = new_label;
11935   }
11936   //update the label number
11937   WN_label_number(label) = label_map[label_num];  
11938   
11939   WN_INSERT_BlockLast(loop_body, label);
11940   for (; incr != NULL; incr = WN_next(incr)) {
11941     WN_INSERT_BlockLast(loop_body, WN_COPY_Tree(incr));
11942   }
11943 
11944   WN* new_loop = WN_CreateWhileDo(WN_COPY_Tree(test), loop_body);
11945   new_loop = lower_while_do(block, new_loop, actions);
11946   WN* then_body = WN_CreateBlock();
11947   WN_INSERT_BlockLast(then_body, new_loop);
11948   
11949   WN* else_body = WN_CreateBlock();
11950   WN* control_val = WN_CreateIntconst(OPR_INTCONST, MTYPE_I4, MTYPE_V, 1); 
11951   WN* set_control = WN_Stid(MTYPE_I4, 0, upc_forall_control_st, TY_align(ST_type(upc_forall_control_st)), control_val);
11952   WN_INSERT_BlockLast(else_body, set_control);
11953   WN_INSERT_BlockLast(else_body, tree);
11954   control_val = WN_CreateIntconst(OPR_INTCONST, MTYPE_I4, MTYPE_V, 0);
11955   set_control = WN_Stid(MTYPE_I4, 0, upc_forall_control_st, TY_align(ST_type(upc_forall_control_st)), control_val);
11956   WN_INSERT_BlockLast(else_body, set_control);
11957 
11958   return WN_CreateIf(if_expr, then_body, else_body);
11959 
11960 } 
11961 
11962 
11963 /* ====================================================================
11964  *
11965  * WN *lower_while_do(WN *block, WN *tree, LOWER_ACTIONS actions)
11966  *
11967  * Lower WHILE_DO.  Generate:
11968  *      (FALSEBR (<test>) <cont_lbl>)
11969  *      (LABEL <top_lbl>)
11970  *      <body>
11971  *      (TRUEBR <test> <top_lbl>)
11972  *  (LABEL <cont_lbl>)
11973  *
11974  *
11975  * Perform lowering (see WN_Lower description) on statements in WHILE_DO
11976  * node <tree>, returning lowered statements.  Returned tree will always
11977  * have a structured control flow node (at least a BLOCK) at the top.
11978  *
11979  * ==================================================================== */
11980 
11981 static WN *lower_while_do(WN *block, WN *tree, LOWER_ACTIONS actions)
11982 {
11983   Is_True(WN_opcode(tree) == OPC_WHILE_DO,
11984           ("expected WHILE_DO node, not %s", OPCODE_name(WN_opcode(tree))));
11985 
11986   ++loop_nest_depth;
11987 
11988   //WEI: see if we have a forall_ctrl loop
11989   if (Action(LOWER_UPC_FORALL)) {
11990     WN* body = WN_while_body(tree);
11991     for (WN* prag = WN_last(body); prag != NULL; prag = WN_prev(prag)) {
11992       if (WN_opcode(prag) == OPC_PRAGMA && 
11993           WN_pragma(prag) == WN_PRAGMA_UPC_FORALL_AFFINITY) {
11994         tree = lower_forall_ctrl(block, tree, prag, actions);
11995         break;
11996       }
11997     }
11998   }
11999 
12000 #ifndef SHORTCIRCUIT_HACK
12001   if (Action(LOWER_WHILE_DO))
12002 #else
12003   if (Action(LOWER_WHILE_DO) || 
12004       (Action(LOWER_SHORTCIRCUIT) && tree_has_cand_cior (WN_while_test(tree))))
12005 #endif
12006   {
12007    /*
12008     *   (FALSEBR <test> <cont_lbl>) into block
12009     *   (LABEL <top_lbl>)
12010     *   <body>
12011     *   (TRUEBR <test> <top_lbl>)
12012     *  (LABEL <cont_lbl>)
12013     */
12014     LABEL_IDX top_lbl, cont_lbl;
12015     top_lbl  = NewLabel();
12016     cont_lbl = NewLabel();
12017 
12018     WN *test = lower_copy_tree( WN_while_test(tree), actions);
12019     WN *body = WN_CreateBlock();
12020     if (Cur_PU_Feedback)
12021       Cur_PU_Feedback->FB_clone_loop_test( WN_while_test(tree), test, tree );
12022 
12023     if (Action(LOWER_TOP_LEVEL_ONLY))
12024     {
12025       actions = RemoveScfAction(actions);
12026     }
12027 
12028     WN *wn_top_branch = NULL;
12029     WN *top_branch_block = lower_falsebr(cont_lbl, test, &wn_top_branch,
12030                                          actions);
12031     WN_INSERT_BlockLast(block, top_branch_block);
12032 
12033     setCurrentState(WN_while_body(tree), actions);
12034     WN *wn_top_lbl = WN_Label(top_lbl);
12035     WN_INSERT_BlockLast(body, wn_top_lbl);
12036 
12037     setCurrentStateBlockLast(WN_while_body(tree), actions);
12038     WN_INSERT_BlockLast(body, lower_block(WN_while_body(tree), actions));
12039 
12040     WN *wn_back_branch = NULL;
12041     WN *back_branch_block = lower_truebr(top_lbl, WN_while_test(tree),
12042                                          &wn_back_branch, actions);
12043     WN_INSERT_BlockLast(body, back_branch_block);
12044     WN *wn_cont_lbl = WN_Label(cont_lbl);
12045     WN_INSERT_BlockLast(body, wn_cont_lbl);
12046 
12047     if ( Cur_PU_Feedback )
12048       Cur_PU_Feedback->FB_lower_loop( tree, wn_top_branch, wn_back_branch );
12049 
12050     WN_Delete(tree);
12051 
12052     tree = body;
12053   }
12054  /*
12055   * We're not lowering WHILE_DOs, so just lower children.
12056   * The semantics of the WHILE_DO require any statement level whirl
12057   * created during the lowering of the while test be copied to both the
12058   * block (before the WHILE_DO) and in the end of while_body
12059   */
12060   else if (NotAction(LOWER_TOP_LEVEL_ONLY))
12061   {
12062     WN *copytestBlock;
12063     WN *testBlock = WN_CreateBlock();
12064 
12065     WN_while_body(tree) = lower_block(WN_while_body(tree), actions);
12066 
12067     WN_while_test(tree) = lower_expr(testBlock, WN_while_test(tree), actions);
12068     copytestBlock = lower_copy_tree(testBlock, actions);
12069 
12070     if (Cur_PU_Feedback)
12071       Cur_PU_Feedback->FB_clone_loop_test( testBlock, copytestBlock, tree );
12072 
12073     WN_INSERT_BlockLast(block, copytestBlock);
12074     WN_INSERT_BlockLast(WN_while_body(tree), testBlock);
12075   }
12076 
12077   --loop_nest_depth;
12078   contains_a_loop = TRUE;
12079   return tree;
12080 }
12081 
12082 
12083 
12084 /* ====================================================================
12085  *
12086  *  The parameter types may not be correct, and as usual, we have to
12087  *  make up for it. Integral types are canonicalized [I,U][1,2] types
12088  *  (to [I,U]4) and do not require explicit conversion
12089  *  (the conversion happens when the value is loaded)
12090  *
12091  *  Mostly floats are passed as doubles and must be converted 
12092  *
12093  * ==================================================================== */
12094 static WN *lower_promoted_formal(PLOC ploc, ST *formalST)
12095 {
12096   WN            *ldid, *cvt;
12097   TYPE_ID       regType, formalType;
12098 
12099   formalType = TY_mtype(Ty_Table[ST_type(formalST)]);
12100 
12101   regType = Mtype_comparison(TY_mtype(Promoted_Parm_Type(formalST)));
12102 
12103   if (!PLOC_on_stack(ploc))
12104   {
12105     formalST = MTYPE_To_PREG(regType);
12106   }
12107 
12108   ldid = WN_Ldid(regType, PLOC_reg(ploc), formalST, ST_type(formalST));
12109 
12110   cvt = WN_Type_Conversion(ldid, formalType);
12111 
12112   return cvt;
12113 }
12114 
12115 /* ====================================================================
12116  *
12117  * PLOC lower_formals(WN *block, WN *tree, LOWER_ACTIONS actions)
12118  *
12119  *  lower formal tree returning a ploc
12120  *
12121  * ==================================================================== */
12122 
12123 static void lower_formals(WN *block, WN *formal, PLOC ploc,
12124                           LOWER_ACTIONS actions)
12125 {
12126   BOOL    altentry = PU_has_altentry(Get_Current_PU());
12127   ST     *sym      = WN_st(formal);
12128   TY_IDX  formalTY = WN_type(formal);
12129 
12130   if (PLOC_on_stack(ploc))
12131   {
12132     /* on stack already */
12133     if (altentry)
12134     {
12135       ST        *upformal;
12136       WN        *ldid, *stid;
12137 
12138       upformal = Get_Altentry_UpFormal_Symbol (sym, ploc);
12139 
12140       ldid = WN_Ldid(TY_mtype(Ty_Table[formalTY]), 0, upformal, formalTY);
12141 
12142       stid = WN_Stid(TY_mtype(Ty_Table[formalTY]), 0, sym, formalTY, ldid);
12143 
12144       stid = lower_store(block, stid, actions);
12145       WN_Set_Linenum (stid, current_srcpos);
12146       WN_INSERT_BlockLast(block, stid);
12147     }
12148     else if (ST_promote_parm(sym))
12149     {
12150       if (MTYPE_is_float(TY_mtype(Ty_Table[formalTY])))
12151       {
12152         WN      *cvt;
12153         WN      *stid;
12154 
12155         cvt  = lower_promoted_formal(ploc, sym);
12156         stid = WN_Stid(TY_mtype(Ty_Table[formalTY]), 0, sym,
12157                                 formalTY, cvt);
12158 
12159         WN_Set_Linenum (stid, current_srcpos);
12160         WN_INSERT_BlockLast(block, stid);
12161       }
12162     }
12163   }
12164   else if (MTYPE_is_m(TY_mtype(Ty_Table[formalTY])))
12165   {
12166     /* structure parameter */
12167     lower_mload_formal (block, formal, ploc, actions);
12168   }
12169   else
12170   {
12171     WN  *cvt, *stid;
12172 
12173     cvt  = lower_promoted_formal(ploc, sym);
12174 
12175     stid = WN_Stid(TY_mtype(Ty_Table[formalTY]), 0, sym, formalTY, cvt);
12176 
12177     WN_Set_Linenum (stid, current_srcpos);
12178     WN_INSERT_BlockLast(block, stid);
12179   }
12180 }
12181 
12182 
12183 
12184 /* ====================================================================
12185  *
12186  * PLOC lower_entry_formals(WN *block, WN *tree, LOWER_ACTIONS actions)
12187  *
12188  * Perform lowering on ENTRY and ALTENTRY nodes
12189  *
12190  * for LOWER_ENTRY_EXIT
12191  *              lower all but sclass formal refs
12192  * for LOWER_ENTRY_FORMAL_REF
12193  *              lower just sclass formal refs
12194  *
12195  * ==================================================================== */
12196 
12197 static PLOC lower_entry_formals(WN *block, WN *tree, LOWER_ACTIONS actions)
12198 {
12199   PLOC  ploc;
12200   INT32 i, n;
12201 
12202   ploc = Setup_Input_Parameter_Locations(ST_pu_type(WN_st(tree)));
12203 
12204   if (WN_opcode(tree) == OPC_ALTENTRY)
12205   {
12206     n = WN_kid_count(tree);
12207     Reset_UPFORMAL_Segment();
12208   }
12209   else
12210   {
12211     n = WN_num_formals(tree);
12212   }
12213 
12214   for (i = 0; i < n; i++)
12215   {
12216     WN *formal = WN_formal(tree, i);
12217         
12218     if (WN_sclass(formal) == SCLASS_FORMAL_REF)
12219     {
12220       ST *base;
12221 
12222       base = Get_ST_formal_ref_base(WN_st(formal));
12223       ploc = Get_Input_Parameter_Location(ST_type(base));
12224 
12225       if (NotAction(LOWER_ENTRY_FORMAL_REF))
12226       {
12227         continue;
12228       }
12229       else
12230       {
12231         formal = WN_CreateIdname(WN_idname_offset(formal), base);
12232       }
12233     }
12234     else
12235     {
12236       ploc = Get_Input_Parameter_Location(WN_type(formal));
12237 
12238       if (NotAction(LOWER_ENTRY_EXIT))
12239       {
12240         continue;
12241       }
12242     }
12243     lower_formals(block, formal, ploc, actions);
12244   }
12245 
12246   return ploc;
12247 }
12248 
12249 static WN *
12250 Create_Mcount_Call (void)
12251 {
12252     // don't do anything here,
12253     // because ia64 mcount call is non-standard calling convention,
12254     // so implement it in target-dependent cg.
12255     return NULL;
12256 }
12257 
12258 /* ====================================================================
12259  *
12260  * WN *lower_entry(WN *tree, LOWER_ACTIONS actions)
12261  *
12262  * Perform lowering on ENTRY and ALTENTRY nodes
12263  *
12264  * for ENTRY
12265  *              return entry node
12266  * for ALTENTRY
12267  *              return block with lowered formals 
12268  *
12269  * for LOWER_ENTRY_EXIT
12270  *              create trapuv code (uninitialized variable)
12271  *              create varargs register assignment
12272  *              create slink sym initialization
12273  *
12274  * for LOWER_RETURN_VAL
12275  *              create fake first parameter for struct return if needed
12276  *
12277  * ==================================================================== */
12278 
12279 static WN *lower_entry(WN *tree, LOWER_ACTIONS actions)
12280 {
12281   PLOC  ploc;
12282   WN    *block;
12283 
12284   Is_True(((WN_opcode(tree) == OPC_FUNC_ENTRY)
12285            || (WN_opcode(tree) == OPC_ALTENTRY)),
12286           ("expected ENTRY/ALTENTRY node, not %s",
12287            OPCODE_name(WN_opcode(tree))));
12288 
12289   if (WHIRL_Return_Val_On && Action(LOWER_RETURN_VAL) && 
12290       WN_operator(tree) == OPR_FUNC_ENTRY)
12291   { // create fake first parameter for struct return if needed 
12292     ST_IDX func_stidx = WN_st_idx(tree);
12293     PU_IDX puidx = ST_pu(St_Table[func_stidx]);
12294     TY_IDX prototype = PU_prototype(Pu_Table[puidx]);
12295     RETURN_INFO return_info = Get_Return_Info(TY_ret_type(prototype), 
12296                                               Complex_Not_Simulated);
12297     if (RETURN_INFO_return_via_first_arg(return_info)) {
12298       ST *return_st = Gen_Temp_Symbol(
12299                               Make_Pointer_Type(TY_ret_type(prototype), FALSE),
12300                               Index_To_Str(Save_Str2(".return.",
12301                                                        ST_name(func_stidx))));
12302       Set_ST_sclass(return_st, SCLASS_FORMAL);
12303       Set_ST_is_value_parm(return_st);
12304       WN *idname = WN_CreateIdname(0, return_st);
12305       // create the new func_entry node
12306       WN *n_tree = WN_CreateEntry(WN_num_formals(tree)+1, func_stidx,
12307                                   WN_func_body(tree), WN_func_pragmas(tree),
12308                                   WN_func_varrefs(tree));
12309       WN_Set_Linenum(n_tree, WN_Get_Linenum(tree));
12310       WN_map_id(n_tree) = WN_map_id(tree);
12311       WN_kid0(n_tree) = idname;
12312       for (INT32 i = 0; i < WN_kid_count(tree); i++)
12313         WN_kid(n_tree, i+1) = WN_kid(tree, i);
12314       // fix pu pointer from RID
12315       if (RID_map != WN_MAP_UNDEFINED) {
12316         RID *rid = (RID *)WN_MAP_Get(RID_map, tree);
12317         if (RID_rwn(rid) == tree)
12318           RID_rwn(rid) = n_tree;
12319       }
12320       WN_Delete(tree);
12321       tree = n_tree;
12322     }
12323   }
12324 
12325   setCurrentState(tree, actions);
12326   block =               WN_CreateBlock();
12327   
12328   if (Action(LOWER_ENTRY_EXIT))
12329   {
12330     ploc = lower_entry_formals(block, tree, actions);
12331 
12332     if (TY_is_varargs(Ty_Table[PU_prototype(Pu_Table[ST_pu(WN_st(tree))])]))
12333     {
12334      /*
12335       *  For varargs, the func-entry just has the list of fixed
12336       *  parameters, so also have to store the vararg registers. 
12337       */
12338       TYPE_ID   type = Def_Int_Mtype;
12339 
12340       if (PLOC_is_nonempty(ploc) && !PLOC_on_stack(ploc)) {
12341         /* don't do if already reached stack params */
12342         ploc = Get_Vararg_Input_Parameter_Location (ploc);
12343       }
12344 
12345       while (!PLOC_on_stack(ploc))
12346       {
12347        /*
12348         *  vararg registers must be integer registers
12349         */
12350         WN      *wn;
12351         ST      *st;
12352 
12353         wn = WN_Ldid (type, PLOC_reg(ploc), Int_Preg, ST_type(Int_Preg));
12354        /*
12355         *  get the symbol for the vararg formal
12356         */
12357         st = Get_Vararg_Symbol (ploc);
12358 
12359         wn = WN_Stid (type, 0, st, ST_type(st), wn);
12360         WN_Set_Linenum (wn, current_srcpos);
12361         WN_INSERT_BlockLast(block, wn);
12362 
12363         ploc = Get_Vararg_Input_Parameter_Location (ploc);
12364       }
12365     }
12366 
12367    /*
12368     * add initialization code for trapuv
12369     */
12370     {
12371       WN *trapuvBlock = WN_CreateBlock();
12372 
12373       trapuvBlock = lower_trapuv(trapuvBlock, tree, actions);
12374 
12375       trapuvBlock= lower_block(trapuvBlock, actions);
12376 
12377       WN_INSERT_BlockLast(block, trapuvBlock);
12378     }
12379   }
12380   else if (Action(LOWER_ENTRY_FORMAL_REF))
12381   {
12382     ploc = lower_entry_formals(block, tree, actions);
12383   }
12384 
12385   if (Action(LOWER_SPLIT_SYM_ADDRS))
12386   {
12387     /*
12388      *  Initialize the static link if required ($2 should have callers $fp)
12389      */
12390     ST *slink = Find_Slink_Symbol(CURRENT_SYMTAB);
12391     if (slink)
12392     {
12393       WN        *ld, *wn;
12394 
12395       ld = WN_LdidPreg(Pointer_type, Static_Link_Preg_Offset);
12396 
12397       wn = WN_Stid (Pointer_type, 0, slink, ST_type(slink), ld);
12398 
12399       WN_Set_Linenum (wn, current_srcpos);
12400       WN_INSERT_BlockFirst(block, wn);
12401     }
12402   }
12403 
12404   if (WN_opcode(tree) == OPC_FUNC_ENTRY)
12405   {
12406     /* Process any PU-scope MP pragmas */
12407     if (WN_func_pragmas(tree) && Action(LOWER_MP)) {
12408       WN *wn;
12409       for (wn = WN_first(WN_func_pragmas(tree)); wn; wn = WN_next(wn)) {
12410         if (((WN_opcode(wn) == OPC_PRAGMA) || (WN_opcode(wn) == OPC_XPRAGMA))
12411             && (WN_pragmas[WN_pragma(wn)].users & PUSER_MP)) {
12412           (void) lower_mp(NULL, wn, actions);
12413         }
12414       }
12415     }
12416 
12417     if (Call_Mcount && Action(LOWER_ENTRY_EXIT)) {
12418         WN *profcall = Create_Mcount_Call ();
12419         if (profcall) { // possible that we won't create call yet
12420                 WN_Set_Linenum (profcall, current_srcpos);
12421                 WN_INSERT_BlockLast(block, profcall);
12422         }
12423     }
12424 
12425     WN_INSERT_BlockFirst(WN_func_body(tree), block);
12426 
12427     /* Lower statements in function body. */
12428     WN_func_body(tree) = lower_block(WN_func_body(tree), actions);
12429     return tree;
12430   }
12431   else
12432   {
12433     block  = lower_block(block, actions);
12434     WN_INSERT_BlockFirst(block, tree);
12435   }
12436   return block;
12437 }
12438 
12439 
12440 
12441 
12442 /* ====================================================================
12443  *
12444  * WN *lower_region(WN *tree, LOWER_ACTIONS actions)
12445  *
12446  * Perform lowering on REGION node
12447  * <tree> returning lowered REGION tree.
12448  *
12449  * ==================================================================== */
12450 
12451 static WN *lower_region(WN *tree, LOWER_ACTIONS actions)
12452 {
12453   Is_True(WN_opcode(WN_region_body(tree)) == OPC_BLOCK,
12454           ("kid of REGION should be OPC_BLOCK, not %s",
12455            OPCODE_name(WN_opcode(WN_region_body(tree)))));
12456 
12457   setCurrentState(tree, actions);
12458   if (current_function == NULL) {
12459     // haven't seen FUNC_ENTRY yet
12460     current_function = PU_Info_tree_ptr(Current_PU_Info);
12461   }
12462 
12463   if (Action(LOWER_REGION))
12464   {
12465     RID *rid = REGION_get_rid( tree );
12466 
12467     Is_True(rid, ("expected valid region id"));
12468 
12469     max_region++;
12470 
12471    /*
12472     *  first time thru. Set region lowered flags
12473     *  otherwise remove flags that have already been processed.
12474     */
12475     if (RID_lowered(rid) == (LOWER_ACTIONS) NULL)
12476     {
12477       RID_lowered(rid) = actions;
12478     }
12479     else
12480     {
12481       actions ^= (RID_lowered(rid) & (LOWER_CALL | LOWER_ENTRY_EXIT));
12482     }
12483 
12484     if (actions)
12485     {
12486       WN_region_body(tree) = lower_block(WN_region_body(tree), 
12487                                          actions | LOWER_REGION);
12488     }
12489   }
12490   else
12491   {
12492     WN_region_body(tree) = lower_block(WN_region_body(tree), actions);
12493   }
12494 
12495   return tree;
12496 }
12497 
12498 WN *lower_scf_non_recursive(WN *block, WN *tree, LOWER_ACTIONS actions)
12499 {
12500   return lower_scf(block,tree,actions | LOWER_TOP_LEVEL_ONLY);
12501 }
12502 
12503 /* ====================================================================
12504  *
12505  * WN *lower_scf(WN *block, WN *tree, LOWER_ACTIONS actions)
12506  *
12507  * Perform lowering (see WN_Lower description) on structured control
12508  * flow node <tree>.  Returned tree will always have a structured
12509  * control flow node (at least a BLOCK) at the top.
12510  *
12511  * ==================================================================== */
12512 
12513 static WN *lower_scf(WN *block, WN *tree, LOWER_ACTIONS actions)
12514 {
12515   CURRENT_STATE scfState = pushCurrentState(tree, actions);
12516 
12517   switch (WN_opcode(tree))
12518   {
12519   case OPC_DO_WHILE:
12520     block = lower_do_while(block, tree, actions);
12521     break;
12522 
12523   case OPC_WHILE_DO:
12524     block = lower_while_do(block, tree, actions);
12525     break;
12526 
12527   case OPC_DO_LOOP:
12528     block = lower_do_loop(block, tree, actions);
12529     break;
12530       
12531   case OPC_IF:
12532     block = lower_if(block, tree, actions);
12533     break;
12534 
12535   case OPC_BLOCK:
12536     block = lower_block(tree, actions);
12537     break;
12538     
12539   case OPC_REGION:
12540     block = lower_region(tree, actions);
12541     break;
12542   }
12543 
12544   popCurrentState(scfState);
12545   return block;
12546 }
12547 
12548 
12549 /* ====================================================================
12550  *
12551  * WN *lower_trapuv(WN *block, WN *tree, LOWER_ACTIONS actions)
12552  *
12553  * Initialize stack variables as per trapuv
12554  *
12555  * ==================================================================== */
12556 
12557 static WN *lower_trapuv(WN *block, WN *tree, LOWER_ACTIONS actions)
12558 {
12559   if ( DEBUG_Trap_Uv == FALSE)
12560     return block;
12561 
12562   {
12563     ST  *st;
12564     ST  *slink = Find_Slink_Symbol(CURRENT_SYMTAB);
12565 
12566     INT32 i;
12567     FOREACH_SYMBOL(CURRENT_SYMTAB, st, i)
12568     {
12569       TY_IDX  type;
12570       TYPE_ID btype;
12571       INT32   size;
12572 
12573       if (ST_class(st) != CLASS_VAR)
12574         continue;
12575 
12576       if (ST_sclass(st) != SCLASS_AUTO)
12577         continue;
12578 
12579       if (Has_Base_Block(st))
12580         continue;
12581 
12582       if (ST_is_uplevelTemp(st) || st == slink)
12583         continue;
12584 
12585       if (ST_is_not_used(st)) 
12586         continue;
12587       if (Is_Allocated(st))
12588         continue;
12589 
12590       type  = ST_type(st);
12591       btype = TY_mtype(Ty_Table[type]);
12592       size  = TY_size(type);
12593 
12594       Is_True(ST_pu_defined(st), ("trapuv auto or temp not ST_pu_defined"));
12595 
12596       switch(TY_kind(type))
12597       {
12598       case KIND_SCALAR:
12599       case KIND_POINTER:
12600       case KIND_FUNCTION:
12601         {
12602           WN  *con, *stid;
12603 
12604           Is_True((MTYPE_RegisterSize(btype) == size),
12605                   ("bad size for scalar/pointer"));;
12606 
12607           con = WN_UVConst(btype);
12608 
12609           stid = WN_Stid(btype, 0, st, type, con);
12610           WN_Set_Linenum(stid, WN_Get_Linenum(tree));
12611           WN_INSERT_BlockLast(block, stid);
12612         }
12613         break;
12614 
12615       case KIND_ARRAY:
12616       case KIND_STRUCT:
12617         {
12618          /*
12619           *  Assign bit pattern just on basis of size.
12620           *  We cannot truncate the pattern, so we set ST_use_reg_align();
12621           *  We always start at offset 0 (we know it is aligned)
12622           *  and replicate the following pattern  (0xFFFA5A5A)
12623           *
12624           *     size    right-justify           left-justify
12625           *     ----    -------------           ------------
12626           *     1       5A                      FF
12627           *     2       5A5A                    FFFA
12628           *     3       FA5A5A                  FFFA5A
12629           *     4       FFFA5A5A                FFFA5A5A
12630           *     5       5AFFFA5A 5A             FFFA5A5A FF
12631           *     6       5A5AFFFA 5A5A           FFFA5A5A FFFA
12632           *     7       FA5A5AFF FA5A5A         FFFA5A5A FFFA5A
12633           *
12634           *  We do the assignment in chunks, special casing the
12635           *  last assigment.
12636           *  These weird patterns are only relevant for character
12637           *  and structure assignment
12638           */
12639           TY_IDX        ptype = Make_Pointer_Type(type);
12640           WN           *conUV4 = NULL;
12641           INT32         todo = size;
12642           INT32         offset = 0;
12643           UINT32        ncon;
12644           TYPE_ID       q;
12645 
12646           for (q= Max_Uint_Mtype; q!=MTYPE_UNKNOWN; q= Mtype_prev_alignment(q))
12647           {
12648             WN     *con, *lda, *num, *store;
12649             INT32  qSize   = MTYPE_RegisterSize(q);
12650             INT32  qBits   = MTYPE_size_reg(q);
12651             INT32  nMoves  = todo / qSize;
12652             INT32  residue = todo % qSize;
12653 
12654             if (q >= MTYPE_U4)
12655             { 
12656               if (nMoves)
12657               {
12658                 con = WN_UVConst(q);
12659 
12660                 if ( DEBUG_Trap_Uv_Rjustify )
12661                 {
12662                   con = WN_RotateIntconst(con, residue*8);
12663                 }
12664 
12665                 lda = WN_Lda(Pointer_type, 0, st);
12666                 num = WN_Intconst(MTYPE_I4, nMoves * qSize);
12667 
12668                 store = WN_CreateMstore(offset, ptype, con, lda, num);
12669 
12670                 WN_Set_Linenum(store, WN_Get_Linenum(tree));
12671                 WN_INSERT_BlockLast(block, store);
12672 
12673                 todo   -= (nMoves * qSize);
12674                 offset += (nMoves * qSize);
12675               }
12676             }
12677             else
12678             {
12679              /*
12680               *  very tricky residue code (size 1,2,3).
12681               */
12682               if (todo > 0)
12683               {
12684                 if (conUV4==NULL)
12685                 {
12686                   conUV4 = WN_UVConst(MTYPE_U4);
12687                   ncon   = WN_const_val(conUV4);
12688                 }
12689                 if (nMoves)
12690                 {
12691                   if ( DEBUG_Trap_Uv_Rjustify )
12692                   {
12693                     con = WN_Intconst(MTYPE_U4, ncon>>(todo*8 - qBits));
12694                   }
12695                   else
12696                   {
12697                     con = WN_Intconst(MTYPE_U4,
12698                                       ncon>>(MTYPE_size_reg(MTYPE_U4)-qBits));
12699                     ncon <<= qBits;
12700                   }
12701 
12702                   store = WN_Stid(q, offset, st, type, con);
12703                   WN_Set_Linenum(store, WN_Get_Linenum(tree));
12704                   WN_INSERT_BlockLast(block, store);
12705                 
12706                   todo   -= (nMoves * qSize);
12707                   offset += (nMoves * qSize);
12708                 }
12709               }
12710             }
12711           }
12712           if (conUV4)
12713             WN_Delete(conUV4);
12714 
12715         }
12716         break;
12717       }
12718     }
12719   }
12720   return block;
12721 }
12722 
12723 
12724 static void lower_actions_fprintf(FILE *f, LOWER_ACTIONS actions)
12725 {
12726   LOWER_ACTIONS i = 1;
12727 
12728   while (actions)
12729   {
12730     if (Action(i))
12731     {
12732       fprintf(f, "%s ", LOWER_ACTIONS_name(i));
12733       actions = actions ^ i;
12734     }
12735     i <<= 1;
12736   }
12737   fprintf(f, "\n");
12738 }
12739 
12740 
12741 /* ====================================================================
12742  *
12743  * const char * LOWER_ACTIONS_name(LOWER_ACTIONS actions)
12744  *
12745  * Exported.  See interface description in "wn_lower.h".
12746  *
12747  * ==================================================================== */
12748 const char * LOWER_ACTIONS_name(LOWER_ACTIONS actions)
12749 {
12750   if ((actions-1) & actions)
12751   {
12752     DevWarn("LOWER_ACTION_name(0x%llx): expected only one flag at a time",
12753             actions);
12754   }
12755 
12756   switch(actions)
12757   {
12758   case LOWER_NULL:                      return "LOWER_NULL";
12759   case LOWER_DO_LOOP:                   return "LOWER_DO_LOOP";
12760   case LOWER_DO_WHILE:                  return "LOWER_DO_WHILE";
12761   case LOWER_WHILE_DO:                  return "LOWER_WHILE_DO";
12762   case LOWER_IF:                        return "LOWER_IF";
12763   case LOWER_COMPLEX:                   return "LOWER_COMPLEX";
12764   case LOWER_ARRAY:                     return "LOWER_ARRAY";
12765   case LOWER_SPLIT_CONST_OFFSETS:       return "LOWER_SPLIT_CONST_OFFSETS";
12766   case LOWER_ENTRY_EXIT:                return "LOWER_ENTRY_EXIT";
12767   case LOWER_CALL:                      return "LOWER_CALL";
12768   case LOWER_SPLIT_SYM_ADDRS:           return "LOWER_SPLIT_SYM_ADDRS";
12769   case LOWER_IO_STATEMENT:              return "LOWER_IO_STATEMENT";
12770   case LOWER_MSTORE:                    return "LOWER_MSTORE";
12771   case LOWER_CVT:                       return "LOWER_CVT";
12772   case LOWER_MP:                        return "LOWER_MP";
12773   case LOWER_8X_ARRAY:                  return "LOWER_8X_ARRAY";
12774   case LOWER_INTRINSIC:                 return "LOWER_INTRINSIC";
12775   case LOWER_INLINE_INTRINSIC:          return "LOWER_INLINE_INTRINSIC";
12776   case LOWER_INL_STACK_INTRINSIC:       return "LOWER_INL_STACK_INTRINSIC";
12777   case LOWER_REGION:                    return "LOWER_REGION";
12778   case LOWER_QUAD:                      return "LOWER_QUAD";
12779   case LOWER_COMPGOTO:                  return "LOWER_COMPGOTO";
12780   case LOWER_MADD:                      return "LOWER_MADD";
12781   case LOWER_TOP_LEVEL_ONLY:            return "LOWER_TOP_LEVEL_ONLY";
12782   case LOWER_PREFETCH_MAPS:             return "LOWER_PREFETCH_MAPS";
12783   case LOWER_ALIAS_MAPS:                return "LOWER_ALIAS_MAPS";
12784   case LOWER_DEPGRAPH_MAPS:             return "LOWER_DEPGRAPH_MAPS";
12785   case LOWER_PARITY_MAPS:               return "LOWER_PARITY_MAPS";
12786     // NOTE: Delete LOWER_FREQUENCY_MAPS
12787   case LOWER_FREQUENCY_MAPS:            return "LOWER_FREQUENCY_MAPS";
12788   case LOWER_PICCALL:                   return "LOWER_PICCALL";
12789   case LOWER_BASE_INDEX:                return "LOWER_BASE_INDEX";
12790   case LOWER_TO_CG:                     return "LOWER_TO_CG";
12791   case LOWER_ASSERT:                    return "LOWER_ASSERT";
12792   case LOWER_FORMAL_REF:                return "LOWER_FORMAL_REF";
12793   case LOWER_UPLEVEL:                   return "LOWER_UPLEVEL";
12794   case LOWER_ENTRY_FORMAL_REF:          return "LOWER_ENTRY_FORMAL_REF";
12795   case LOWER_SHORTCIRCUIT:              return "LOWER_SHORTCIRCUIT";
12796   case LOWER_TREEHEIGHT:                return "LOWER_TREEHEIGHT";
12797   case LOWER_RETURN_VAL:                return "LOWER_RETURN_VAL";
12798   case LOWER_MLDID_MSTID:               return "LOWER_MLDID_MSTID";
12799   case LOWER_BIT_FIELD_ID:              return "LOWER_BIT_FIELD_ID";
12800   case LOWER_BITS_OP:                   return "LOWER_BITS_OP";
12801   default:                              return "<unrecognized>";
12802   }
12803 }
12804 
12805 static const char * MSTORE_ACTIONS_name(MSTORE_ACTIONS actions)
12806 {
12807   switch(actions)
12808   {
12809   case MSTORE_aggregate:                return "scalar moves    ";
12810   case MSTORE_loop:                     return "generate loop   ";
12811   case MSTORE_intrinsic_bzero:          return "intrinsic bzero ";
12812   case MSTORE_intrinsic_memset:         return "intrinsic memset";
12813   case MSTORE_intrinsic_bcopy:          return "intrinsic bcopy";
12814   default:                              return "<unrecognized>";
12815   }
12816 }
12817 
12818 
12819 void WN_Lower_Checkdump(char *msg, WN *tree, LOWER_ACTIONS actions)
12820 {
12821   traceAlignment   = Get_Trace(TP_LOWER, 0x004);
12822   traceSplitSymOff = Get_Trace(TP_LOWER, 0x010);
12823   traceIO          = Get_Trace(TP_LOWER, 0x020);
12824   traceSpeculate   = Get_Trace(TP_LOWER, 0x040);
12825   traceTreeHeight  = Get_Trace(TP_LOWER, 0x080);
12826   traceMload       = Get_Trace(TP_LOWER, 0x100);
12827   // traceUplevel    = Get_Trace(TP_LOWER, 0x200);
12828 
12829   if (Get_Trace(TP_LOWER, 0x008))
12830   {
12831     enable_tree_freq_display();
12832   }
12833 
12834   if (Get_Trace(TKIND_IR, TP_LOWER))
12835   {
12836     fputs(DBar, TFile);
12837     fprintf(TFile, "WN_Lower: \"%s\"\n", msg);
12838     if (actions)
12839     {
12840       fprintf(TFile, "flags are:\n");
12841       lower_actions_fprintf(TFile, actions);
12842     }
12843     fdump_tree(TFile, tree);
12844     fputs(DBar, TFile);
12845   }
12846 
12847   if (Get_Trace(TP_LOWER, 0x001))
12848   {
12849     IR_dump_map_info = TRUE;
12850 
12851     fprintf(TFile, "WN_Lower: LNO DEP GRAPH\n");
12852     LNOPrintDepGraph(TFile);
12853   }
12854   if (Get_Trace(TP_LOWER, 0x002))
12855   {
12856     IR_dump_map_info = TRUE;
12857 
12858     fprintf(TFile, "WN_Lower: WOPT ALIAS INFO\n");
12859     fdump_dep_tree(TFile, tree, alias_manager);
12860   }
12861 
12862   if (Get_Trace(TKIND_SYMTAB,TP_LOWER)) {
12863     fprintf(TFile,"\n\n========== Symbol tables after Lowering ==========\n");
12864     Print_symtab (TFile, GLOBAL_SYMTAB);
12865     Print_symtab (TFile, CURRENT_SYMTAB);
12866   }
12867 
12868   /*
12869    * these options can lead to infinite regress
12870    */
12871   if (Action(LOWER_SPLIT_SYM_ADDRS))
12872   {
12873     if (Enable_WN_Simp && WN_Simp_Fold_ILOAD)
12874     {
12875       DevWarn("disabling option WN_Simp_Fold_ILOAD"
12876               " while lowering action LOWER_SPLIT_SYM_ADDRS");
12877       WN_Simp_Fold_ILOAD = FALSE;
12878     }
12879   }
12880   /*
12881    * get any relevant pragmas
12882    * I need to know if wopt was run to generate some eval warnings
12883    */
12884   {
12885     WN  *pragma=        NULL;
12886           
12887     traceWoptFinishedOpt=       FALSE;
12888 
12889     switch(WN_operator(tree))
12890     {
12891     case OPR_FUNC_ENTRY:
12892       pragma=   WN_func_pragmas(tree);
12893       break;
12894     case OPR_REGION:
12895       pragma=   WN_region_pragmas(tree);
12896       break;
12897     }
12898     if (pragma)
12899     {
12900       WN        *wn;
12901       for(wn= WN_first(pragma); wn; wn= WN_next(wn))
12902       {
12903         if (WN_pragma(wn) == WN_PRAGMA_WOPT_FINISHED_OPT)
12904           traceWoptFinishedOpt= TRUE;
12905       }
12906     }
12907   }
12908 }
12909 
12910 
12911 /* ====================================================================
12912  *
12913  * LOWER_ACTIONS lower_to_cg(LOWER_ACTIONS, LOWER_ACTIONS)
12914  *
12915  * The last lowering is special in that it may require lowering
12916  * already specified and lowering that has been avoided
12917  * 
12918  * Some lowering should not be done more than once (ENTRY_EXIT, CALL)
12919  *
12920  * Keep track and add/subtract any lowering already processed
12921  *
12922  * ==================================================================== */
12923 
12924 static LOWER_ACTIONS lower_actions(WN *pu, LOWER_ACTIONS actions)
12925 {
12926   if (OPT_Lower_Treeheight && Action(LOWER_TO_CG))
12927     actions |= LOWER_TREEHEIGHT;
12928 
12929   if (Action(LOWER_TO_CG))
12930   {
12931    /*
12932     *  remove/add one-time-only and must-apply flags
12933     */
12934     actions |=  lowering_actions ^ (LOWER_ENTRY_EXIT            |
12935                                     LOWER_ENTRY_FORMAL_REF      |
12936                                     LOWER_FORMAL_REF            |
12937                                     LOWER_UPLEVEL               |
12938                                     LOWER_SPLIT_SYM_ADDRS       |
12939                                     LOWER_CALL                  |
12940                                     LOWER_RETURN_VAL);
12941 
12942    /*
12943     * remove these always
12944     *
12945     * disabling SPLIT_CONST will allow the lowerer to put together addresses
12946     * that have been pulled apart
12947     */
12948     actions &=  ~(LOWER_BASE_INDEX | LOWER_SPLIT_CONST_OFFSETS);
12949 
12950    /*
12951     * these form the major LOWER_TO_CG actions
12952     */
12953     actions |=  LOWER_SCF                 |
12954                 LOWER_ARRAY               |
12955                 LOWER_MP                  |
12956                 LOWER_IO_STATEMENT        |
12957                 LOWER_MSTORE              |
12958                 LOWER_CVT                 |
12959                 LOWER_COMPGOTO            |
12960                 LOWER_COMPLEX             |
12961                 LOWER_QUAD                |
12962                 LOWER_MADD                |
12963                 LOWER_INTRINSIC           |
12964                 LOWER_ASSERT              |
12965                 LOWER_PICCALL             |
12966                 LOWER_ALL_MAPS            |
12967                 LOWER_SHORTCIRCUIT        |
12968                 LOWER_INL_STACK_INTRINSIC |
12969                 LOWER_INLINE_INTRINSIC    |
12970                 LOWER_BIT_FIELD_ID;
12971    /*
12972     *  do not split divides into mul/recip at the CG lowering
12973     */
12974     save_Div_Split_Allowed = Div_Split_Allowed;
12975     Div_Split_Allowed = FALSE;;
12976   }
12977   if (WN_opcode(pu) == OPC_FUNC_ENTRY)
12978   {
12979     lowering_actions |= actions;
12980   }
12981 
12982   if (Action(LOWER_BITS_OP))
12983     actions |= LOWER_BIT_FIELD_ID;
12984 
12985   current_actions = actions;
12986 
12987   lower_maps_init(actions);
12988 
12989   setCurrentState(pu, actions);
12990 
12991   return actions;
12992 }
12993 
12994 
12995 
12996 
12997 /* ====================================================================
12998  *
12999  * Lower_Init(void)
13000  *
13001  * lowering specific initialization
13002  * ==================================================================== */
13003 
13004 void Lower_Init(void)
13005 {
13006    static CURRENT_STATE current_state_NULL;
13007    /*
13008     *  create map for marking parity
13009     */
13010    lowering_parity_map = WN_MAP32_Create(MEM_pu_pool_ptr);
13011 
13012    lowering_actions = 0;
13013    current_state = current_state_NULL;
13014 
13015    // save parity_map in an array becuse it may change in nested PUs
13016    parity_map_index++;
13017    FmtAssert(0 <= parity_map_index && parity_map_index < PARITY_MAP_ARRAY_SIZE,
13018              ("Lower_Init: Index into parity map array is out of range"));
13019    parity_map_array[parity_map_index] = lowering_parity_map;
13020 }
13021 
13022 void Lowering_Finalize(void)
13023 {
13024   /* free lowering_parity_map */
13025   WN_MAP_Delete(lowering_parity_map);
13026   
13027   parity_map_index--;
13028   if (parity_map_index >= 0) {
13029     // if there is a saved parity map, then restore it
13030     lowering_parity_map = parity_map_array[parity_map_index];
13031   }
13032   else {
13033     // otherwise, set it to undefined
13034     lowering_parity_map = WN_MAP_UNDEFINED;
13035   }
13036 }
13037 
13038 
13039 
13040 
13041 static void lower_end(WN *tree, LOWER_ACTIONS actions)
13042 {
13043   lower_maps_reset(actions);
13044 
13045   if (Action(LOWER_TO_CG))
13046   {
13047     Div_Split_Allowed = save_Div_Split_Allowed; /* reset */
13048   }
13049 
13050   popCurrentState(current_state);
13051 }
13052 
13053 /* ====================================================================
13054  *
13055  * WN *WN_Lower(WN *tree, LOWER_ACTIONS actions)
13056  *
13057  * Exported.  See interface description in "wn_lower.h".
13058  *
13059  * ==================================================================== */
13060 
13061 WN *WN_Lower(WN *tree, LOWER_ACTIONS actions, struct ALIAS_MANAGER *alias,
13062              char *msg)
13063 {
13064 #ifdef BACK_END
13065   Start_Timer(T_Lower_CU);
13066 #endif
13067   alias_manager =       alias;
13068   loop_nest_depth =     0;
13069 
13070   // Don't do any lowering on trees that merely wrap up file-scope
13071   // assembly language code.
13072   if (WN_operator(tree) == OPR_FUNC_ENTRY &&
13073       ST_asm_function_st(*WN_st(tree))) {
13074     return tree;
13075   }
13076 
13077   actions = lower_actions(tree, actions);
13078 
13079   if (Action(LOWER_MP)) {
13080     /* Initialize the MP lowerer.
13081      * Note: We're assuming that for MP-lowering,
13082      * this routine (WN_Lower) is called once per PU.
13083      */
13084     LowerMP_PU_Init ();
13085   }
13086 
13087   if (Action(LOWER_UPC_CONSISTENCY)) {
13088     LowerUPC_Init_Consistency();
13089   }
13090 
13091   WN_Lower_Checkdump(msg, tree, actions);
13092 
13093   if (WN_opcode(tree) == OPC_FUNC_ENTRY)
13094   {
13095     tree = lower_entry(tree, actions);
13096   }
13097   else if (OPCODE_is_scf(WN_opcode(tree)))
13098   {
13099     tree = lower_scf(NULL, tree, actions);
13100   }
13101   else if (OPCODE_is_stmt(WN_opcode(tree)))
13102   {
13103     tree = lower_stmt(NULL, tree, actions);
13104   }
13105   else if (OPCODE_is_expression(WN_opcode(tree)))
13106   {
13107     tree = lower_expr(NULL, tree, actions);
13108   }
13109 
13110   lower_end(tree, actions);
13111 
13112   WN_Lower_Checkdump("After lowering", tree, 0);
13113 
13114 #ifdef BACK_END
13115   Stop_Timer(T_Lower_CU);
13116 #endif
13117   
13118   if(!Action(LOWER_UPC_TO_INTR) && !Action(LOWER_UPC_MFIELD))
13119     WN_verifier(tree);
13120 
13121   return tree;
13122 }

Generated on Wed Jan 28 04:36:39 2009 for OpenADFortTk (extended to Open64) by  doxygen 1.5.7.1