• Main Page
  • Modules
  • Data Types
  • Files

osprey/be/com/wn_lower.cxx

Go to the documentation of this file.
00001 /*
00002  *  Copyright (C) 2006. QLogic Corporation. All Rights Reserved.
00003  */
00004 
00005 /*
00006  * Copyright 2002, 2003, 2004, 2005, 2006 PathScale, Inc.  All Rights Reserved.
00007  */
00008 
00009 /*
00010 
00011   Copyright (C) 2000, 2001 Silicon Graphics, Inc.  All Rights Reserved.
00012 
00013   This program is free software; you can redistribute it and/or modify it
00014   under the terms of version 2 of the GNU General Public License as
00015   published by the Free Software Foundation.
00016 
00017   This program is distributed in the hope that it would be useful, but
00018   WITHOUT ANY WARRANTY; without even the implied warranty of
00019   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
00020 
00021   Further, this software is distributed without any warranty that it is
00022   free of the rightful claim of any third person regarding infringement 
00023   or the like.  Any license provided herein, whether implied or 
00024   otherwise, applies only to this software file.  Patent licenses, if 
00025   any, provided herein do not apply to combinations of this program with 
00026   other software, or any other product whatsoever.  
00027 
00028   You should have received a copy of the GNU General Public License along
00029   with this program; if not, write the Free Software Foundation, Inc., 59
00030   Temple Place - Suite 330, Boston MA 02111-1307, USA.
00031 
00032   Contact information:  Silicon Graphics, Inc., 1600 Amphitheatre Pky,
00033   Mountain View, CA 94043, or:
00034 
00035   http://www.sgi.com
00036 
00037   For further information regarding this notice, see:
00038 
00039   http://oss.sgi.com/projects/GenInfo/NoticeExplan
00040 
00041 */
00042 
00043 
00044 //-*-c++-*-
00045 
00046 #define __STDC_LIMIT_MACROS
00047 #include <stdint.h>
00048 #ifdef USE_PCH
00049 #include "be_com_pch.h"
00050 #endif /* USE_PCH */
00051 #pragma hdrstop
00052 #if defined(BUILD_OS_DARWIN)
00053 #include <limits.h>
00054 #else /* defined(BUILD_OS_DARWIN) */
00055 #include <values.h>
00056 #endif /* defined(BUILD_OS_DARWIN) */
00057 #include <isam.h>
00058 #include <alloca.h>
00059 #ifdef __MINGW32__
00060 #include <signal.h>
00061 #else
00062 #include <sys/signal.h>
00063 #endif /* __MINGW32__ */
00064 #if defined(BUILD_OS_DARWIN)
00065 #include <darwin_elf.h>
00066 #else /* defined(BUILD_OS_DARWIN) */
00067 #include <elf.h>
00068 #endif /* defined(BUILD_OS_DARWIN) */
00069 
00070 #include "defs.h"
00071 #include "config.h"
00072 #include "config_asm.h"
00073 #include "config_debug.h"
00074 #include "config_opt.h"
00075 #include "config_targ_opt.h"
00076 #include "errors.h"
00077 #include "erglob.h"
00078 #include "tracing.h"
00079 #include "glob.h"
00080 #include "timing.h"
00081 #include "stab.h"
00082 #include "strtab.h"
00083 #include "util.h"
00084 #include "wn.h"
00085 #include "wn_util.h"
00086 #include "stblock.h"
00087 #include "data_layout.h"
00088 #include "ir_reader.h"
00089 #include "targ_sim.h"
00090 #include "targ_const.h"
00091 #include "const.h"
00092 #include "ttype.h"
00093 #include "wio.h"
00094 #include "wn_mp.h"
00095 #include "wn_pragmas.h"
00096 #include "wn_simp.h"
00097 #include "opt_alias_interface.h"
00098 #include "wn_lower.h"
00099 #include "region_util.h"
00100 #include "wutil.h"
00101 #include "wn_map.h"
00102 #include "wn_fio.h"
00103 #include "wn_trap.h"
00104 #include "pu_info.h"
00105 #include "w2op.h"
00106 #include "be_symtab.h"
00107 #include "betarget.h"
00108 #include "be_util.h"
00109 #include "opt_cvtl_rule.h"
00110 #include "fb_whirl.h"
00111 #include "intrn_info.h"
00112 #ifdef KEY
00113 #include "config_vho.h"   // for VHO_Enable_Simple_If_Conv
00114 #include "targ_const_private.h" // for TCON_R4, TCON_R8, ..
00115 #endif
00116 #include "be_memop_annot.h"
00117 
00118 #ifdef TARG_X8664
00119 #include <ext/hash_set>
00120 #endif
00121 
00122 #include "tls.h"
00123 
00124 #ifdef TARG_NVISA
00125 #define SHORTCIRCUIT_TO_LOGICAL_LIMIT 3
00126 #endif
00127 
00128 /* My changes are a hack till blessed by Steve. (suneel) */
00129 #define SHORTCIRCUIT_HACK 1
00130 #define MMCOPY_MULT 1.2 
00131 #define MEMLIB_THRESHOLD_BYTES OPT_Threshold_To_Memlib  //Parameter to adjust
00132 #define MEMLIB_STRUCT_BYTES 128  //Parameter to adjust
00133 #define MEMLIB_NUM_STORE 5  //Parameter to adjust
00134 #define MEMLIB_MAX_NUM 6
00135 #ifdef KEY
00136 #define DELETED_MAX 100 
00137 #else
00138 #define DELETED_MAX 20 
00139 #endif
00140 
00141 /* this next header should be after the external declarations in the others */
00142 #include "pragma_weak.h"  /* Alias routines defined in wopt.so */
00143 
00144 /* ====================================================================
00145  *       Exported Functions
00146  * ====================================================================
00147  */
00148 extern PREG_NUM AssignExpr(WN *, WN *, TYPE_ID);
00149 
00150 extern BOOL lower_is_aliased(WN *, WN *, INT64 size, BOOL defalt);
00151 
00152 extern INT32 compute_copy_alignment(TY_IDX, TY_IDX, INT32 offset);
00153 
00154 extern TYPE_ID compute_copy_quantum(INT32 );
00155 
00156 extern WN *WN_I1const(TYPE_ID, INT64 con);
00157 
00158 extern void Set_addr_saved_expr(WN *wn, BOOL warn);
00159 /*
00160  * defined in config.c (should be in config.h)
00161  */
00162 extern INT32  MinStructCopyLoopSize;
00163 extern INT32  MinStructCopyMemIntrSize;
00164 
00165 INT32 Total_MLower_Count=0;
00166 INT32 Total_M_Count=0;
00167 
00168 /* ====================================================================
00169  *       Imported Declarations
00170  * ====================================================================
00171  */
00172 extern WN *emulate(WN *, WN *);
00173 
00174 #ifdef KEY // bug 6938
00175 extern WN *emulate_fast_exp(WN *, WN *);
00176 #endif
00177 
00178 extern WN *intrinsic_runtime(WN *, WN *);
00179 
00180 extern WN *make_pointer_to_node(WN *, WN *);
00181 
00182 extern char *INTR_intrinsic_name( WN *);
00183 
00184 extern void fdump_dep_tree(FILE *, WN *, struct ALIAS_MANAGER *);
00185 
00186 extern void InitParityMaps(void);
00187 
00188 extern "C" void LNOPreserveMapPair(WN *, WN *, WN *);
00189 
00190 extern "C" void LNOPruneMapsUsingParity(void);
00191 
00192 extern "C" void LNOPrintDepGraph(FILE *);
00193 
00194 extern void enable_tree_freq_display(void);
00195 
00196 extern TYPE_ID INTR_return_mtype(INTRINSIC id);
00197 
00198 extern BE_ST_TAB   Be_st_tab;
00199 
00200 #ifdef TARG_X8664
00201 // Nesting depth is insanely high (120 or so) for bug 599
00202 #define MAX_LOOP_NEST_DEPTH 150
00203 /* <loop_info_stack> has its own <current_loop_nest_depth>, since <loop_nest_depth>
00204    will be set to 0 by WN_loop_depth(). Most of the time, WN_loop_depth will
00205    give non-zero value inside a do_loop, but IPA could make it be zero, which could
00206    cause some other problems later.
00207    ToDo: Look into IPA to find out what is going on.
00208 */
00209 static UINT8 current_loop_nest_depth;
00210 static WN* loop_info_stack[MAX_LOOP_NEST_DEPTH];
00211 static BOOL last_call_ff2c_abi; // whether the last outgoing call use this abi
00212 #endif
00213 
00214 /* ====================================================================
00215  *       Forward Declarations
00216  * ====================================================================
00217  */
00218 #ifdef LOW_LANDING_PAD
00219 #undef LOW_LANDING_PAD
00220 #endif
00221 #ifdef TARG_X8664
00222 #define LOW_LANDING_PAD
00223 #endif
00224 #ifdef TARG_IA64
00225 #define LOW_LANDING_PAD
00226 #endif
00227 
00228 static WN *lower_scf(WN *, WN *, LOWER_ACTIONS);
00229 static WN *lower_expr(WN *, WN *, LOWER_ACTIONS);
00230 static WN *lower_store(WN *, WN *, LOWER_ACTIONS);
00231 static WN *lower_call(WN *, WN *, LOWER_ACTIONS);
00232 static WN *lower_intrinsic(WN *, WN *, LOWER_ACTIONS);
00233 static WN *lower_intrinsic_call(WN *, WN *, LOWER_ACTIONS);
00234 static WN *lower_intrinsic_op(WN *, WN *, LOWER_ACTIONS);
00235 static WN *lower_if(WN *, WN *, LOWER_ACTIONS);
00236 static WN *lower_stmt(WN *, WN *, LOWER_ACTIONS);
00237 static WN *lower_entry(WN *, LOWER_ACTIONS);
00238 #ifdef LOW_LANDING_PAD
00239 static WN *lower_landing_pad_entry(WN *);
00240 #endif 
00241 static WN *lower_eval(WN *, WN *, LOWER_ACTIONS);
00242 static WN *lower_copy_tree(WN *, LOWER_ACTIONS);
00243 static WN *lower_emulation(WN *, WN *, LOWER_ACTIONS, BOOL &intrinsic_lowered);
00244 static WN *lower_mstore(WN *, WN *, LOWER_ACTIONS);
00245 static WN *lower_nary_madd(WN *, WN *, LOWER_ACTIONS);
00246 static WN *lower_madd(WN *, WN *, LOWER_ACTIONS);
00247 static WN *lower_assert(WN *, WN *, LOWER_ACTIONS);
00248 static WN *lower_trapuv(WN *, WN *, LOWER_ACTIONS);
00249 static WN *lower_base_reference(WN *, ST *, INT64, LOWER_ACTIONS);
00250 static WN *lower_base_register(WN *, ST *, INT64, LOWER_ACTIONS);
00251 static WN *lower_dereference(WN *, INT64, ST *, PREG_NUM, LOWER_ACTIONS);
00252 static WN *lower_split_sym_addrs(WN *, INT64, LOWER_ACTIONS);
00253 static WN *improve_Malignment(WN *, WN *, WN *, INT64);
00254 static WN *lower_branch(WN *, WN *, LOWER_ACTIONS);
00255 static WN *lower_branch_condition(BOOL, LABEL_IDX, WN *, WN **, LOWER_ACTIONS);
00256 static WN *lower_conditional(WN *, WN *, LABEL_IDX, LABEL_IDX, BOOL,
00257            LOWER_ACTIONS);
00258 static WN *lower_tree_height(WN *, WN *, LOWER_ACTIONS);
00259 static void lower_madd_tree_height(WN *, WN *, LOWER_ACTIONS);
00260 
00261 static WN *Lower_Memlib(WN *block, WN *tree, LOWER_ACTIONS actions);
00262 static WN *Lower_Mistore_Memlib(WN *block, WN *tree, LOWER_ACTIONS actions);
00263 static WN *Lower_STID_Memlib(WN *block, WN *tree, LOWER_ACTIONS actions);
00264 
00265 static TY_IDX coerceTY(TY_IDX, TYPE_ID);
00266 static ST *coerceST(const ST *, TYPE_ID);
00267 static ST *coerceST(const ST &, TYPE_ID);
00268 static WN_OFFSET coerceOFFSET(WN *, TYPE_ID, WN_OFFSET);
00269 
00270 
00271 static WN *lower_mload(WN *, WN *, LOWER_ACTIONS);
00272 static void lower_mload_formal(WN *, WN *, PLOC, LOWER_ACTIONS);
00273 static void lower_mload_actual (WN *, WN *, PLOC, LOWER_ACTIONS);
00274 static void lower_complex_emulation(WN *, WN *, LOWER_ACTIONS, WN **, WN **);
00275 static void lower_complex_expr(WN *, WN *, LOWER_ACTIONS, WN **, WN **);
00276 
00277 
00278 static void lower_copy_maps(WN *, WN *, LOWER_ACTIONS);
00279 static void lower_tree_copy_maps(WN *, WN *, LOWER_ACTIONS);
00280 
00281 static INT32 compute_alignment(WN *, INT64);
00282 static TYPE_ID compute_next_copy_quantum(TYPE_ID , INT32);
00283 
00284 static WN *lower_mistore_by_type(WN *block, WN *mistore, LOWER_ACTIONS actions);
00285 #if defined(KEY) 
00286 static WN *lower_malloc_alg(WN *block, WN *tree, LOWER_ACTIONS actions);
00287 static ST_IDX find_trampoline(ST_IDX func_st_idx);
00288 #endif
00289 
00290 // return the WN* from which <derived> was derived
00291 static WN* get_original_wn (WN* derived);
00292 static void set_original_wn (WN* derived, WN* orig);
00293 
00294 /* ====================================================================
00295  *       private variables
00296  * ====================================================================
00297  */
00298 static INT   max_region;
00299 static char *current_preg_name;
00300 static UINT16 loop_nest_depth;
00301 static BOOL contains_a_loop;
00302 static struct ALIAS_MANAGER *alias_manager;
00303 #define NESTED_MAP_ARRAY_SIZE 32
00304 static WN_MAP parity_map_array[NESTED_MAP_ARRAY_SIZE];
00305 static WN_MAP derivation_map_array[NESTED_MAP_ARRAY_SIZE];
00306 static WN_MAP lowering_parity_map = WN_MAP_UNDEFINED;
00307 static WN_MAP wn_derivation_map = WN_MAP_UNDEFINED; 
00308 static INT32 nested_map_index = -1;
00309 static LOWER_ACTIONS lowering_actions= 0;
00310 static BOOL save_Div_Split_Allowed ;
00311 static INT cur_memlib_idx        = 0;
00312 
00313 // for promote ldid/lda in param in call to up level
00314 static BOOL promote_tls_ldst     = FALSE;
00315 static BOOL traceIO              = FALSE;
00316 static BOOL traceSpeculate       = FALSE;
00317 static BOOL traceAlignment       = FALSE;
00318 static BOOL traceTreeHeight      = FALSE;
00319 static BOOL traceSplitSymOff     = FALSE;
00320 static BOOL traceWoptFinishedOpt = FALSE;
00321 static BOOL traceMload           = FALSE;
00322 static BOOL traceMemlib          = FALSE;
00323 
00324 // static BOOL traceUplevel = FALSE;
00325 
00326 typedef struct CURRENT_STATE
00327 {
00328   SRCPOS  srcpos;
00329   WN    *stmt;
00330   WN    *function;
00331   LOWER_ACTIONS actions;
00332 } CURRENT_STATE, *CURRENT_STATEp;
00333 
00334 CURRENT_STATE current_state;
00335 
00336 #define current_srcpos    current_state.srcpos
00337 #define current_stmt    current_state.stmt
00338 #define current_actions   current_state.actions
00339 #define current_function  current_state.function
00340 
00341 typedef enum MSTORE_ACTIONS
00342 {
00343   MSTORE_aggregate,
00344   MSTORE_loop,
00345   MSTORE_intrinsic_bzero,
00346   MSTORE_intrinsic_memset,
00347 #ifdef KEY
00348   MSTORE_intrinsic_memcpy,
00349 #endif
00350   MSTORE_intrinsic_bcopy
00351 } MSTORE_ACTIONS;
00352 
00353 enum MEMLIB_ACTIONS
00354 {
00355   IGNORE,
00356   ABORT_OPT,
00357   CONT_OPT
00358 };
00359 
00360 typedef struct inode {
00361    WN *wn;
00362    INT start_offset;
00363    INT length;
00364    struct inode *next;
00365 } inode_type;
00366 
00367 static const char * MSTORE_ACTIONS_name(MSTORE_ACTIONS);
00368 
00369 static TYPE_ID Promoted_Mtype[MTYPE_LAST + 1] = {
00370   MTYPE_UNKNOWN,  /* MTYPE_UNKNOWN */
00371   MTYPE_UNKNOWN,  /* MTYPE_B */
00372   MTYPE_I4,       /* MTYPE_I1 */
00373   MTYPE_I4,       /* MTYPE_I2 */
00374   MTYPE_I4,       /* MTYPE_I4 */
00375   MTYPE_I8,       /* MTYPE_I8 */
00376   MTYPE_U4,       /* MTYPE_U1 */
00377   MTYPE_U4,       /* MTYPE_U2 */
00378   MTYPE_U4,       /* MTYPE_U4 */
00379   MTYPE_U8,       /* MTYPE_U8 */
00380   MTYPE_F4,       /* MTYPE_F4 */
00381   MTYPE_F8,       /* MTYPE_F8 */
00382 #ifdef TARG_IA64
00383   MTYPE_F10,      /* MTYPE_F10 */
00384 #else
00385   MTYPE_UNKNOWN,  /* MTYPE_F10 */
00386 #endif
00387   MTYPE_UNKNOWN,  /* MTYPE_F16 */
00388   MTYPE_UNKNOWN,  /* MTYPE_STR */
00389   MTYPE_FQ,       /* MTYPE_FQ */
00390   MTYPE_M,        /* MTYPE_M */
00391   MTYPE_C4,       /* MTYPE_C4 */
00392   MTYPE_C8,       /* MTYPE_C8 */
00393   MTYPE_CQ,       /* MTYPE_CQ */
00394   MTYPE_V         /* MTYPE_V */
00395 #ifdef KEY
00396  ,MTYPE_UNKNOWN,  /* MTYPE_BS */
00397   MTYPE_UNKNOWN,  /* MTYPE_A4 */
00398   MTYPE_UNKNOWN,  /* MTYPE_A8 */
00399 #ifdef TARG_IA64
00400   MTYPE_C10,    /* MTYPE_C10 */
00401 #else
00402   MTYPE_UNKNOWN,  /* MTYPE_C10 */
00403 #endif
00404   MTYPE_UNKNOWN,  /* MTYPE_C16 */
00405   MTYPE_UNKNOWN,  /* MTYPE_I16 */
00406   MTYPE_UNKNOWN,  /* MTYPE_U16 */
00407 #if defined(TARG_X8664) || defined(VECTOR_MTYPES)
00408   MTYPE_V16C4,    /* MTYPE_V16C4 */
00409   MTYPE_V16C8,    /* MTYPE_V16C8 */
00410   MTYPE_V16I1,    /* MTYPE_V16I1 */
00411   MTYPE_V16I2,    /* MTYPE_V16I2 */
00412   MTYPE_V16I4,    /* MTYPE_V16I4 */
00413   MTYPE_V16I8,    /* MTYPE_V16I8 */
00414   MTYPE_V16F4,    /* MTYPE_V16F4 */
00415   MTYPE_V16F8,    /* MTYPE_V16F8 */
00416   MTYPE_V8I1,     /* MTYPE_V8I1 */
00417   MTYPE_V8I2,     /* MTYPE_V8I2 */
00418   MTYPE_V8I4,     /* MTYPE_V8I4 */
00419   MTYPE_V8F4,     /* MTYPE_V8F4 */
00420 #if defined(TARG_X8664)
00421   MTYPE_M8I1,     /* MTYPE_M8I1 */
00422   MTYPE_M8I2,     /* MTYPE_M8I2 */
00423   MTYPE_M8I4,     /* MTYPE_M8I4 */
00424   MTYPE_M8F4      /* MTYPE_M8F4 */
00425 #endif // TARG_X8664
00426 #endif // (TARG_X8664) || (VECTOR_MTYPES)
00427 #endif // KEY
00428 };
00429 
00430 /* ====================================================================
00431  *      Private macros
00432  * ====================================================================
00433  */
00434 
00435 #define OPCODE_is_intrinsic(op)                                   \
00436     ((OPCODE_operator((op)) == OPR_INTRINSIC_CALL) ||       \
00437     (OPCODE_operator((op)) == OPR_INTRINSIC_OP))
00438 
00439 #define Action(x)     (actions & (x))
00440 #define NotAction(x)      (Action(x)==0)
00441 #define RemoveScfAction(x)    (x & ~(LOWER_SCF))
00442 #define RemoveShortCircuitAction(x) (x & ~(LOWER_SHORTCIRCUIT))
00443 
00444 
00445 #define WN_has_alias_info(x)  (OPCODE_is_load(WN_opcode(x)) ||  \
00446          OPCODE_is_store(WN_opcode(x))  ||  \
00447          WN_operator_is(x, OPR_PARM))
00448 #define WN_has_offset(x)  (OPCODE_has_offset(WN_opcode(x)))
00449 
00450 #define WN_nary_intrinsic(x)  (WN_operator_is(x, OPR_INTRINSIC_OP) && \
00451               ((WN_intrinsic(x)== INTRN_NARY_ADD) ||  \
00452                (WN_intrinsic(x)== INTRN_NARY_MPY)))
00453 #define WN_nary_add(x)    (WN_operator_is(x, OPR_INTRINSIC_OP) && \
00454                (WN_intrinsic(x)== INTRN_NARY_ADD))
00455 #define WN_nary_mpy(x)    (WN_operator_is(x, OPR_INTRINSIC_OP) && \
00456                (WN_intrinsic(x)== INTRN_NARY_MPY))
00457 
00458 #define WN_is_block(x)    (WN_opcode(x) == OPC_BLOCK)
00459 
00460 #define INTRN_is_nary(x)  (((x)==INTRN_NARY_ADD) || ((x)==INTRN_NARY_MPY))
00461 
00462 #define WN_is_commutative(x)  (WN_opcode(x) == OPCODE_commutative_op(WN_opcode(x)))
00463 
00464 #define TY_is_pointer(x)  (TY_kind(x) == KIND_POINTER)
00465 
00466 #define lower_truebr(l,c,b,a) lower_branch_condition(TRUE,l,c,b,a)
00467 #define lower_falsebr(l,c,b,a)  lower_branch_condition(FALSE,l,c,b,a)
00468 #define WN_same_id(a,b)         (WN_st(a)==WN_st(b) && WN_offset(a)==WN_offset(b))
00469 
00470 /* ====================================================================
00471  *
00472  * BOOL mem_offset_must_be_split(WN_OFFSET offset)
00473  * WN_OFFSET mem_offset_hi(WN_OFFSET offset)
00474  * WN_OFFSET mem_offset_lo(WN_OFFSET offset)
00475  *
00476  * Returns TRUE iff <offset> must be split for a target-machine memory
00477  * reference.  If so, mem_offset_hi(offset) returns the high part of
00478  * the split offset, and mem_offset_lo(offset) returns the low part of
00479  * the split offset.
00480  * 
00481  * ==================================================================== */
00482 
00483 #define mem_offset_hi(offset) ((offset) & ~0x7fff)
00484 #define mem_offset_lo(offset) ((offset) & 0x7fff)
00485 
00486 #define mem_offset_must_be_split(offset)    \
00487         (!(-32768 <= (offset) && (offset) < 32768))
00488 
00489 #define mem_offset_2GB(offset)        \
00490   (!(INT32_MIN <= offset && offset <= INT32_MAX))
00491 
00492 #define PIC_SHARED    (Gen_PIC_Shared || Gen_PIC_Call_Shared)
00493 #define PIC_NONSHARED   (!PIC_SHARED)
00494 
00495 #define ABS(x)      (((x)<0) ? -(x) : (x))
00496 #define IS_POWER_OF_2(val)      ((val != 0) && ((val & (val-1)) == 0))
00497 
00498 static ST *
00499 Standard_Preg_For_Mtype (TYPE_ID mtype)
00500 {
00501 #ifdef TARG_NVISA
00502   // need specific-size preg
00503   if (mtype == MTYPE_F8) 
00504   return Float64_Preg;
00505   else if (MTYPE_is_float(mtype)) 
00506   return Float32_Preg;
00507   else if (MTYPE_byte_size(mtype) == 8)
00508   return Int64_Preg;
00509   else
00510   return Int32_Preg;
00511 #else
00512   return MTYPE_is_float(mtype) ? Float_Preg : Int_Preg;
00513 #endif
00514 }
00515 
00516 #ifdef KEY
00517 static void WN_copy_linenum (WN* src, WN* dest)
00518 {
00519   if (src && dest &&
00520       WN_operator(src) != OPERATOR_UNKNOWN &&
00521       WN_operator(dest) != OPERATOR_UNKNOWN &&
00522       OPCODE_is_stmt(WN_opcode(src)) && OPCODE_is_stmt(WN_opcode(dest)))
00523     WN_linenum(dest) = WN_linenum(src);
00524 
00525   return;
00526 }
00527 #endif
00528 /* ====================================================================
00529  *
00530  * UINT32 compute_offset_alignment(INT32 offset, UINT32 align)
00531  *
00532  * return gcd of offset,align;
00533  * Used for alignment reasons;
00534  * For maximum efficiency, offset should be >= align
00535  *
00536  * ==================================================================== */
00537 UINT32 compute_offset_alignment(INT32 offset, UINT32 align)
00538 {
00539   UINT32 m = ABS(offset);
00540   UINT32 n = align;
00541   while (n != 0) {
00542     INT32 new_n = m % n;
00543     m = n;
00544     n = new_n;
00545   }
00546   return m;
00547 }
00548 
00549 
00550 /* ====================================================================
00551  *
00552  *  The semantics of memset require replicating the byte constant
00553  *  so replicate the constant into a I8/U8 depending on WN_rtype(con)
00554  *
00555  * ==================================================================== */
00556 extern WN *WN_I1const(TYPE_ID type, INT64 con)
00557 {
00558   // assume con is a byte constant, so clear the other bits
00559   // (otherwise replicate will "or" with sign bits).
00560   INT64 n=    con & 0xff;
00561   INT64 maxAlign= MTYPE_alignment(Max_Uint_Mtype);
00562 
00563   if (con)
00564   {
00565     INT64 i;
00566     for(i=1; i<maxAlign; i++)
00567     {
00568       n |=  (n << 8);
00569     }
00570   }
00571 
00572   return WN_Intconst(Mtype_AlignmentClass(maxAlign,
00573             MTYPE_type_class(type)), n);
00574 }
00575 
00576 
00577 /* ====================================================================
00578  *
00579  * void push_current_state(WN *tree, STATE *state)
00580  *
00581  * return and set current state
00582  *
00583  * ==================================================================== */
00584 static void setCurrentState(WN *tree, LOWER_ACTIONS actions)
00585 {
00586   if (tree) {
00587     current_stmt =  tree;
00588     current_srcpos =  WN_Get_Linenum(tree);
00589     current_actions = actions;
00590 
00591     if (WN_opcode(tree) == OPC_FUNC_ENTRY)
00592       current_function = tree;
00593   }
00594 }
00595 
00596 static void setCurrentStateBlockFirst(WN *tree, LOWER_ACTIONS actions)
00597 {
00598   Is_True(WN_opcode(tree) == OPC_BLOCK, ("expected BLOCK node"));
00599 
00600   setCurrentState(WN_first(tree), actions);
00601 }
00602 
00603 static void setCurrentStateBlockLast(WN *tree, LOWER_ACTIONS actions)
00604 {
00605   Is_True(WN_opcode(tree) == OPC_BLOCK, ("expected BLOCK node"));
00606 
00607   setCurrentState(WN_last(tree), actions);
00608 }
00609 
00610 
00611 static CURRENT_STATE pushCurrentState(WN *tree, LOWER_ACTIONS actions)
00612 {
00613   CURRENT_STATE saveState = current_state;
00614 
00615   setCurrentState(tree, actions);
00616 
00617   return saveState;
00618 }
00619 
00620 static void popCurrentState(CURRENT_STATE state)
00621 {
00622   current_state = state;
00623 }
00624     
00625 
00626 /* ====================================================================
00627  *
00628  * BOOL foldConstOffset(WN *con, INT64 offset)
00629  *
00630  * BOOL foldLdaOffset(WN *lda, INT64 offset)
00631  *
00632  * can con and offset be folded to "fit" into a WN_OFFSET (INT32?)
00633  *
00634  * ==================================================================== */
00635 
00636 static BOOL foldConstOffset(WN *con, INT64 offset)
00637 {
00638   if (WN_operator_is(con, OPR_INTCONST))
00639   {
00640     INT64 sum= offset + WN_const_val(con);
00641 
00642     if (INT32_MIN <= sum && sum <= INT32_MAX)
00643       return TRUE;
00644   }
00645   return FALSE;
00646 }
00647 
00648 static BOOL foldLdaOffset(WN *lda, INT64 offset)
00649 {
00650   if (WN_operator_is(lda, OPR_LDA))
00651   {
00652     INT64 sum= offset + WN_lda_offset(lda);
00653 
00654     Is_True((WN_class(lda) != CLASS_PREG), ("lda class is PREG!!!"));
00655 
00656     if (INT32_MIN <= sum && sum <= INT32_MAX)
00657     {
00658       ST  *sym= WN_st(lda);
00659 
00660      /*
00661       * if the offset is greater than the symbol size, we may generate
00662       * a relocation that is out of bounds (ex LFTR). See pv 482353 for
00663       * this rare condition
00664       */
00665       if (ST_class(sym) == CLASS_BLOCK && STB_size(sym) < sum)
00666   return FALSE;
00667 
00668       return TRUE;
00669     }
00670   }
00671   return FALSE;
00672 }
00673 
00674 
00675 
00676 
00677 
00678 
00679 
00680 
00681 /* ====================================================================
00682  *
00683  * WN_OFFSET coerceOFFSET(WN *tree, TYPE_ID realTY, WN_OFFSET offset)
00684  *
00685  * The offset may either be an offset or preg number.
00686  *
00687  * There is an amazing kludge for complex return values where we
00688  * return F0, F2
00689  *
00690  * ==================================================================== */
00691 static WN_OFFSET coerceOFFSET(WN *tree, TYPE_ID realTY, WN_OFFSET offset)
00692 {
00693 
00694   switch (WN_operator(tree))
00695   {
00696   case OPR_ILOAD:
00697   case OPR_ILOADX:
00698   case OPR_ISTORE:
00699   case OPR_ISTOREX:
00700     return offset + MTYPE_RegisterSize(realTY);
00701 
00702   case OPR_LDID:
00703   case OPR_STID:
00704     if (WN_class(tree) == CLASS_PREG)
00705     {
00706 #ifdef TARG_MIPS
00707      /*
00708       *  amazing kludge
00709       *  for dedicated return register (F0) the ABI defines [F0,F2]
00710       *  as the return values
00711       */
00712       if (Preg_Is_Dedicated(offset) && offset == Float_Preg_Min_Offset)
00713       {
00714     return Float_Preg_Min_Offset + 2;
00715       }
00716       else
00717 #endif
00718   return offset + Preg_Increment(realTY);
00719     }
00720     return offset + MTYPE_RegisterSize(realTY);
00721   }
00722   Fail_FmtAssertion("unexpected complex op (%s)",
00723         OPCODE_name(WN_opcode(tree)));
00724   /*NOTREACHED*/
00725 }
00726 
00727 /* ====================================================================
00728  *
00729  *
00730  * ==================================================================== */
00731 
00732 static void rename_preg(const char *f, const char *preg_class)
00733 {
00734   static char name[41];
00735 
00736   name[0] = '\0';
00737   
00738   strncat(name, f, 30);
00739 
00740   if (preg_class)
00741   {
00742     strncat(name, preg_class, 10);
00743   }
00744   current_preg_name = name;
00745 }
00746 
00747 static void rename_reset(void)
00748 {
00749   current_preg_name = NULL;
00750 }
00751 
00752 
00753 static void WN_Set_Flags(WN *src, WN *dst)
00754 {
00755   if (OPCODE_has_flags(WN_opcode(src)))
00756   {
00757     Is_True(OPCODE_has_flags(WN_opcode(dst)), ("expected wn with flags"));
00758     WN_set_flag(dst, WN_flag(src));
00759   }
00760 }
00761 
00762 extern void WN_annotate_intrinsic_flags(INTRINSIC id, ST *sym)
00763 {
00764   if (INTRN_is_pure(id)) {
00765     Set_PU_is_pure(Get_Current_PU());
00766   }
00767   if (INTRN_has_no_side_effects(id)) {
00768     Set_PU_no_side_effects(Get_Current_PU());
00769   }
00770 }
00771 
00772 extern void WN_annotate_call_flags(WN *call, ST *sym)
00773 {
00774   WN_Set_Call_Default_Flags(call);
00775 
00776   if (PU_no_side_effects(Pu_Table[ST_pu(sym)]))
00777   {   
00778     WN_Reset_Call_Non_Data_Mod(call);
00779     WN_Reset_Call_Non_Parm_Mod(call);
00780     WN_Reset_Call_Parm_Mod(call);
00781 
00782   }
00783   if (PU_is_pure(Pu_Table[ST_pu(sym)]))
00784   {
00785     WN_Reset_Call_Non_Data_Mod(call);
00786     WN_Reset_Call_Non_Parm_Mod(call);
00787     WN_Reset_Call_Parm_Mod(call);
00788 
00789     WN_Reset_Call_Non_Data_Ref(call);
00790     WN_Reset_Call_Non_Parm_Ref(call);
00791   }
00792 }
00793 
00794 /* ====================================================================
00795  *
00796  *
00797  * Create a new label with linenum info
00798  *
00799  * ==================================================================== */
00800 static LABEL_IDX NewLabel(void)
00801 {
00802   LABEL_IDX label;
00803   LABEL& lab = New_LABEL(CURRENT_SYMTAB, label);
00804 
00805 #ifdef KEY
00806   /* For IPA's sake, do not generate a specific label name, which will
00807      conflict with some other basic blocks of other PUs.
00808   */
00809 
00810   if( Run_ipl ){
00811     return label;
00812   }
00813 #endif
00814 
00815   // create label name
00816   char *name = (char *) alloca (strlen(".L..") + 8 + 8 + 1);
00817   sprintf(name, "%s%s%d%s%d", LABEL_PREFIX, Label_Name_Separator, 
00818   Current_PU_Count(), Label_Name_Separator, label);
00819   LABEL_Init (lab, Save_Str(name), LKIND_DEFAULT);
00820   return label;
00821 }
00822 
00823 static WN *WN_Label(LABEL_IDX l)
00824 {
00825   WN *label = WN_CreateLabel(ST_IDX_ZERO, l, 0, NULL);
00826   WN_Set_Linenum(label, current_srcpos);
00827   return label;
00828 }
00829 
00830 static WN *WN_NewLabel(void)
00831 {
00832   LABEL_IDX label;
00833   label = NewLabel();
00834   return WN_Label(label);
00835 }
00836 
00837 
00838 
00839 /* ====================================================================
00840  *
00841  *
00842  * Create false/true branch with line info
00843  *
00844  * ==================================================================== */
00845 static WN *WN_Falsebr(LABEL_IDX label, WN *cond)
00846 {
00847   WN *branch = WN_CreateFalsebr(label, cond);
00848   WN_Set_Linenum(branch, current_srcpos);
00849   return branch;
00850 }
00851 
00852 static WN *WN_Truebr(LABEL_IDX label, WN *cond)
00853 {
00854   WN *branch = WN_CreateTruebr(label, cond);
00855   WN_Set_Linenum(branch, current_srcpos);
00856   return branch;
00857 }
00858 
00859 static WN *WN_Goto(LABEL_IDX label)
00860 {
00861   WN *branch =  WN_CreateGoto((ST_IDX) 0, label);
00862   WN_Set_Linenum(branch, current_srcpos);
00863   return branch;
00864 }
00865 
00866 static BOOL expr_is_speculative(WN *tree)
00867 {
00868   if (OPT_Lower_Speculate)
00869   {
00870     BOOL  speculate;
00871 
00872     speculate = WN_Expr_Can_Be_Speculative(tree, alias_manager);
00873     if (traceSpeculate && speculate)
00874     {
00875       DevWarn("WN_lower: found speculative expression: line %d",
00876         Srcpos_To_Line(current_srcpos));
00877     }
00878     return speculate;
00879   }
00880   return FALSE;
00881 }
00882 
00883 /* ====================================================================
00884  *
00885  *
00886  * Create a Nary representation of the expression passed  
00887  *
00888  * ==================================================================== */
00889 
00890 static WN *WN_Nary(WN *tree, WN *x0, WN *x1, WN *x2, WN *x3)
00891 {
00892   TYPE_ID type = WN_rtype(tree);
00893   OPCODE  op;
00894   INTRINSIC id;
00895 
00896   op = OPCODE_make_op (OPR_INTRINSIC_OP, type, MTYPE_V);
00897  /*
00898   *  figure out id from tree
00899   */
00900   switch(WN_operator(tree))
00901   {
00902   case OPR_ADD:
00903   case OPR_SUB:
00904     id = INTRN_NARY_ADD;
00905     break;
00906   case OPR_MPY:
00907     id = INTRN_NARY_MPY;
00908     break;
00909   default:  
00910     Is_True(FALSE,("unexpected nary op"));
00911   }
00912 
00913   {
00914     WN    *args[4], **kids;
00915     INT16 i, n, argN;
00916 
00917    /*
00918     *  if the child is a nary op of the same type, integrate it
00919     */
00920     n= argN = 0;
00921     if (x0)
00922       args[n++] = x0;
00923     if (x1)
00924       args[n++] = x1;
00925     if (x2)
00926       args[n++] = x2;
00927     if (x3)
00928       args[n++] = x3;
00929 
00930     for(i=0; i<n; i++)
00931     {
00932       WN *wn = (WN *) args[i];
00933 
00934       if (WN_opcode(wn) == op && WN_intrinsic(wn) == id)
00935   argN += WN_kid_count(wn);
00936       else
00937         argN++;
00938     }
00939 
00940     kids = (WN **) alloca(argN * sizeof(WN *));
00941 
00942     for(i= argN= 0; i<n; i++)
00943     {
00944       WN *wn = args[i];
00945 
00946       if (WN_opcode(wn) == op && WN_intrinsic(wn) == id)
00947       {
00948   INT16  j;
00949 
00950   for(j=0; j< WN_kid_count(wn); j++)
00951     kids[argN++] = WN_kid(wn, j);
00952 
00953   WN_Delete(wn);
00954       }
00955       else
00956       {
00957   kids[argN++] = wn;
00958       }
00959     }
00960 
00961     WN_Delete(tree);
00962     tree = WN_Create_Intrinsic(op, id, argN, kids);
00963   }
00964   return tree;
00965 }
00966 
00967 
00968 
00969 
00970 
00971 /* ====================================================================
00972  *
00973  * WN *WN_ExprToNary(WN *tree, TYPE_ID type)
00974  *
00975  * Create a Nary representation of the expression passed  
00976  *
00977  * The nary representation looks like an INTRINSIC_OP    
00978  * with an id = INTRN_NARY_ADD | INTRN_NARY_MPY   
00979  *
00980  * ==================================================================== */
00981 extern WN *WN_ExprToNaryType(WN *tree, TYPE_ID type, INT count)
00982 {
00983   WN  *l, *r;
00984 
00985   if (count > 16) {
00986   Lmt_DevWarn(1,("WN_ExprToNaryType more than 16 deep, so stop"));
00987   return tree;
00988   }
00989   switch(WN_operator(tree))
00990   {
00991   case OPR_ADD:
00992   case OPR_MPY:
00993     l = WN_kid0(tree);
00994     r = WN_kid1(tree);
00995 
00996     if ((WN_opcode(tree) == WN_opcode(l)) &&
00997         (WN_opcode(tree) == WN_opcode(r)))
00998     {
00999       WN_kid0(l) = WN_ExprToNaryType(WN_kid0(l), type, count+1);
01000       WN_kid1(l) = WN_ExprToNaryType(WN_kid1(l), type, count+1);
01001       WN_kid0(r) = WN_ExprToNaryType(WN_kid0(r), type, count+1);
01002       WN_kid1(r) = WN_ExprToNaryType(WN_kid1(r), type, count+1);
01003 
01004       tree = WN_Nary(tree, WN_kid0(l), WN_kid1(l), WN_kid0(r), WN_kid1(r));
01005       WN_Delete(l);
01006       WN_Delete(r);
01007     }
01008     else if (WN_opcode(tree) == WN_opcode(l))
01009     {
01010       WN_kid0(l) = WN_ExprToNaryType(WN_kid0(l), type, count+1);
01011       WN_kid1(l) = WN_ExprToNaryType(WN_kid1(l), type, count+1);
01012 
01013       tree = WN_Nary(tree, WN_kid0(l), WN_kid1(l), r, NULL);
01014       WN_Delete(l);
01015     }
01016     else if (WN_opcode(tree) == WN_opcode(r))
01017     {
01018       WN_kid0(r) = WN_ExprToNaryType(WN_kid0(r), type, count+1);
01019       WN_kid1(r) = WN_ExprToNaryType(WN_kid1(r), type, count+1);
01020 
01021       tree = WN_Nary(tree, WN_kid0(r), WN_kid1(r), l, NULL);
01022       WN_Delete(r);
01023     }
01024     break;
01025 
01026   case OPR_SUB:
01027     {
01028       l = WN_kid0(tree);
01029       r = WN_kid1(tree);
01030 
01031       if (WN_operator_is(l, OPR_ADD))
01032       {
01033   TYPE_ID rtype = WN_rtype(tree);
01034 
01035   WN  *neg = WN_Neg(rtype, r);
01036 
01037   WN_kid0(l) = WN_ExprToNaryType(WN_kid0(l), type, count+1);
01038   WN_kid1(l) = WN_ExprToNaryType(WN_kid1(l), type, count+1);
01039 
01040   tree = WN_Nary(tree, WN_kid0(l), WN_kid1(l), neg, NULL);
01041   WN_Delete(l);
01042       }
01043     }
01044     break;
01045   }
01046   return tree;
01047 }
01048 
01049 
01050 
01051 /* ====================================================================
01052  *
01053  * WN *WN_NaryToExpr(WN *tree)
01054  *
01055  * The nary representation looks like an INTRINSIC_OP    
01056  * with an id = INTRN_NARY_ADD | INTRN_NARY_MPY   
01057  *
01058  * ==================================================================== */
01059 extern WN *WN_NaryToExpr(WN *tree)
01060 {
01061   if (WN_nary_intrinsic(tree))
01062   {
01063     INT16 i;
01064     WN    *wn = WN_kid0(tree);
01065     INTRINSIC id = (INTRINSIC) WN_intrinsic(tree);
01066     TYPE_ID rtype = WN_rtype(tree);
01067     INT   num_parms = WN_kid_count(tree);
01068 
01069     for (i = 1; i < num_parms; i++)
01070     {
01071       WN *actual = WN_kid(tree, i);
01072 
01073       actual = WN_NaryToExpr(actual);
01074 
01075       switch(id)
01076       {
01077       case INTRN_NARY_ADD:
01078   if (WN_operator_is(actual, OPR_NEG))
01079   {
01080     wn = WN_Sub(rtype, wn, WN_kid0(actual));
01081     WN_Delete(actual);
01082   }
01083   else
01084   {
01085     wn = WN_Add(rtype, wn, actual);
01086   }
01087         break;
01088       case INTRN_NARY_MPY:
01089   wn = WN_Mpy(rtype, wn, actual);
01090         break;
01091       }
01092     }
01093     return wn;
01094   }
01095 
01096   return tree;
01097 }
01098 
01099 
01100 
01101 /* ====================================================================
01102  *
01103  * WN *WN_NaryDelete(WN *tree, INT32 n)
01104  *
01105  * Delete the nth kid of a nary intrinsic op
01106  * The rest of the children get moved and the num_kids are updated
01107  *
01108  * ==================================================================== */
01109 
01110 static WN *WN_NaryDelete(WN *tree, INT32 n)
01111 {
01112   INT32 i;
01113   INT32 num_kids= WN_kid_count(tree);
01114 
01115   Is_True((n<num_kids),("cannot delete nth kid"));
01116   Is_True(WN_nary_intrinsic(tree),("expected nary op"));
01117 
01118   for(i=n+1; i<num_kids; i++)
01119   {
01120     WN_actual(tree, i-1) = WN_actual(tree, i);
01121   }
01122   WN_set_kid_count(tree, WN_kid_count(tree)-1);
01123 
01124   return tree;
01125 }
01126 
01127 /* ====================================================================
01128  *
01129  * Get offset field (avoid preg offsets)
01130  * amazing I cannot find anything like this
01131  *
01132  * ==================================================================== */
01133 
01134 extern INT64 lower_offset(WN *tree, INT64 offset)
01135 {
01136   if (WN_has_offset(tree))
01137   {
01138     switch(WN_operator(tree))
01139     {
01140     case OPR_LDA:
01141       offset += WN_lda_offset(tree);
01142       break;
01143     case OPR_MSTORE:
01144     case OPR_ISTORE:
01145     case OPR_ISTOREX:
01146       offset += WN_store_offset(tree);
01147       break;
01148     case OPR_STID:
01149       if (WN_class(tree) != CLASS_PREG)
01150         offset += WN_store_offset(tree);
01151       break;
01152     case OPR_LDID:
01153       if (WN_class(tree) != CLASS_PREG)
01154   offset += WN_load_offset(tree);
01155       break;
01156     case OPR_MLOAD:
01157     case OPR_ILOAD:
01158     case OPR_ILOADX:
01159       offset += WN_load_offset(tree);
01160       break;
01161     }
01162   }
01163   return offset;
01164 }
01165 
01166 
01167 /* ====================================================================
01168  *
01169  * Compute alignment consistent with address and offset
01170  *
01171  * The new alignment may be improved (or not. see pv [559228])
01172  *
01173  * ==================================================================== */
01174 extern TY_IDX compute_alignment_type(WN *tree, TY_IDX type, INT64 offset)
01175 {
01176   INT32 newAlign;
01177 
01178   newAlign= compute_alignment(tree, lower_offset(tree, 0));
01179 
01180   newAlign= compute_offset_alignment(offset, newAlign);
01181 
01182   if (TY_align(type) != newAlign)
01183     Set_TY_align(type, newAlign);
01184 
01185   return type;
01186 }
01187 
01188 static INT32 compute_alignment(WN *tree, INT64 offset)
01189 {
01190   WN    *addr;
01191   TY_IDX   type;
01192   INT32    align, align0, align1;
01193 
01194   switch(WN_operator(tree))
01195   {
01196   case OPR_MSTORE:
01197     type = TY_pointed(Ty_Table[WN_ty(tree)]);
01198     addr = WN_kid1(tree);
01199 
01200     if (WN_has_sym(addr) && WN_ty(addr))
01201     {
01202       return compute_alignment(addr, offset+WN_lda_offset(addr));
01203     }
01204     align = TY_align(type);
01205     break;
01206 
01207   case OPR_MLOAD:
01208     type = TY_pointed(Ty_Table[WN_ty(tree)]);
01209     addr = WN_kid0(tree);
01210 
01211     if (WN_has_sym(addr) && WN_ty(addr))
01212     {
01213       return compute_alignment(addr, offset+WN_lda_offset(addr));
01214     }
01215     align = TY_align(type);
01216     break;
01217 
01218   case OPR_ILOAD:
01219   case OPR_ILOADX:
01220   case OPR_LDA:
01221   case OPR_LDID:
01222     type = WN_ty(tree);
01223     if (TY_is_pointer(Ty_Table[type]))
01224     {
01225       type = TY_pointed(Ty_Table[type]);
01226     }
01227     else
01228     {
01229       return 1;
01230     }
01231     align = TY_align(type);
01232     break;
01233 
01234   case OPR_ARRAY:
01235     align=  compute_alignment(WN_array_base(tree), offset);
01236     offset= WN_element_size(tree);
01237     break;
01238 
01239   case OPR_ADD:
01240   case OPR_SUB:
01241     align0= compute_alignment(WN_kid0(tree), 0);
01242     align1= compute_alignment(WN_kid1(tree), 0);
01243     align=  MIN(align0, align1);
01244     break;
01245 
01246   case OPR_INTCONST:
01247     offset= WN_const_val(tree);
01248     align=  MTYPE_alignment(Max_Uint_Mtype);
01249     break;
01250 
01251   default:
01252     if (traceAlignment)
01253     {
01254       DevWarn("compute_alignment(): unrecognized WN returning alignment of 1");
01255     }
01256     return 1;
01257   }
01258 
01259   align=  compute_offset_alignment(offset, MAX(1, align));
01260 
01261   if (WN_has_sym(tree))
01262   {
01263     INT32 newAlign = align;
01264     ST    *sym = WN_st(tree);
01265 
01266     if (WN_operator_is(tree, OPR_LDA))
01267     {
01268       newAlign= ST_alignment(sym);
01269     }
01270     else if (WN_operator_is(tree, OPR_LDID) &&
01271        ST_type(sym)     &&
01272        TY_is_pointer(Ty_Table[ST_type(sym)]))
01273     {
01274       newAlign = TY_align( TY_pointed(Ty_Table[ST_type(sym)]));
01275     }
01276 
01277     align = compute_offset_alignment(offset, MAX(newAlign, align));
01278   }
01279   return align;
01280 }
01281 
01282 
01283 /* ====================================================================
01284  *
01285  * BOOL lower_is_aliased(WN *wn1, WN *wn2, INT64 size)
01286  *
01287  * Are these addresses aliased? (used in bcopy/memcpy/memmove)
01288  *
01289  * ==================================================================== */
01290 extern BOOL lower_is_aliased(WN *wn1, WN *wn2, INT64 size)
01291 {
01292   if (alias_manager &&
01293       Valid_alias(alias_manager, wn1) &&
01294       Valid_alias(alias_manager, wn2) &&
01295       (Aliased(alias_manager, wn1, wn2) == NOT_ALIASED))
01296   {
01297     return FALSE;
01298   }
01299 
01300   if (WN_operator_is(wn1, OPR_LDA) && WN_operator_is(wn2, OPR_LDA)) {
01301     ST  *sym1 = WN_st(wn1);
01302     ST  *sym2 = WN_st(wn2);
01303     ST  *base1, *base2;
01304     INT64 newoffset1, newoffset2;
01305 
01306     if (sym1 != sym2) return FALSE;
01307 
01308     Base_Symbol_And_Offset_For_Addressing(
01309         sym1, WN_lda_offset(wn1), &base1, &newoffset1);
01310     Base_Symbol_And_Offset_For_Addressing(
01311         sym2, WN_lda_offset(wn2), &base2, &newoffset2);
01312 
01313     if (ABS(newoffset1 - newoffset2) >= size) return FALSE;
01314   }
01315 
01316   return TRUE;
01317 }
01318 
01319 
01320 
01321 /* ====================================================================
01322  *
01323  * WN *lower_copy_tree(WN *tree, INT32 n)
01324  *
01325  * Copy the tree and duplicate the maps
01326  *
01327  * ==================================================================== */
01328 
01329 static void lower_tree_copy_maps(WN *tree, WN *dup, LOWER_ACTIONS actions)
01330 {
01331   if (tree == NULL)
01332   {
01333     Is_True((dup == NULL),("inconsistency while copying trees"));
01334   }
01335   Is_True((WN_opcode(tree) == WN_opcode(dup)),
01336     ("inconsistency while copying trees"));
01337 
01338   if (WN_has_map_id(tree) && WN_has_alias_info(tree))
01339   {
01340     lower_copy_maps(tree, dup, actions);
01341   }
01342   
01343   if (WN_opcode(tree) == OPC_BLOCK)
01344   {
01345     WN  *treeStmt = WN_first(tree);
01346     WN  *dupStmt  = WN_first(dup);
01347 
01348     while(treeStmt)
01349     {
01350       lower_tree_copy_maps(treeStmt, dupStmt, actions);
01351       treeStmt = WN_next(treeStmt);
01352       dupStmt  = WN_next(dupStmt);
01353     }
01354   }
01355   else
01356   {
01357     INT n;
01358     for(n = 0; n < WN_kid_count(tree); n++)
01359     {
01360       if (WN_kid(tree, n))
01361       {
01362   lower_tree_copy_maps(WN_kid(tree,n), WN_kid(dup,n), actions);
01363       }
01364     }
01365   }
01366 }
01367 
01368 static WN *lower_copy_tree(WN *tree, LOWER_ACTIONS actions)
01369 {
01370   WN  *dup;
01371 
01372   dup = WN_COPY_Tree(tree);
01373 
01374   lower_tree_copy_maps(tree, dup, actions);
01375 
01376   return dup;
01377 }
01378 
01379 /* ====================================================================
01380  *
01381  * PREG_NUM AssignPregExprPos(WN *block, WN *tree, TY_IDX ty, SRCPOS srcpos,
01382  *                            LOWER_ACTIONS actions)
01383  *
01384  * PREG_NUM AssignExprPos(WN *block, WN *tree, TYPE_ID type, SRCPOS srcpos,
01385  *                        LOWER_ACTIONS)
01386  *
01387  * PREG_NUM AssignExpr(WN *block, WN *tree, TYPE_ID type)
01388  *
01389  * PREG_NUM AssignExprTY(WN *block, WN *tree, TY_IDX ty)
01390  *
01391  * Allocate a preg of type ST_type(preg) and assign expression tree to it
01392  * and attach it to block. 
01393  *
01394  * Assign srcpos (if not NULL)
01395  *
01396  * ==================================================================== */
01397 
01398 static PREG_NUM AssignPregExprPos(WN *block, WN *tree, TY_IDX ty,
01399           SRCPOS srcpos, LOWER_ACTIONS actions)
01400 {
01401   PREG_NUM  pregNo;
01402   TYPE_ID type;
01403   ST    *preg = MTYPE_To_PREG(TY_mtype(Ty_Table[ty]));
01404 
01405   Is_True((WN_operator_is(tree, OPR_PARM)==FALSE),("bad parm"));
01406 
01407   type = TY_mtype(Ty_Table[ty]);
01408   pregNo = Create_Preg(type, current_preg_name);
01409 #ifdef TARG_NVISA
01410   // we need to track what memory is being accessed when storing
01411   // an lda into a preg.  So if tree has an lda, or indirects to lda
01412   // through another preg, put that in preg table.
01413   WN *lda = Find_Lda (tree);
01414   if (lda) Set_Preg_Lda (pregNo, lda);
01415 #endif
01416 
01417   {
01418     WN  *stBlock, *stid;
01419 
01420     stid = WN_Stid(type, pregNo, preg, ty, tree);
01421 
01422 #ifdef TARG_NVISA
01423     Set_addr_saved_expr(tree, TRUE);
01424 #endif
01425 
01426     if (srcpos)
01427       WN_Set_Linenum (stid, srcpos);
01428 
01429     stBlock = WN_CreateBlock();
01430 
01431    /*
01432     * This lowering may leed to infinite regress if the
01433     *   children cannot be lowered (and are allocated a temp, for example) 
01434     */
01435     if (actions)
01436       stid = lower_store(stBlock, stid, actions);
01437 
01438     WN_INSERT_BlockLast(stBlock, stid);
01439 
01440     WN_INSERT_BlockLast(block, stBlock);
01441   }
01442 
01443   return pregNo;
01444 }
01445 
01446 
01447 extern PREG_NUM AssignExprTY(WN *block, WN *tree, TY_IDX type)
01448 {
01449   return AssignPregExprPos(block, tree, type, current_srcpos,
01450          current_actions);
01451 }
01452 
01453 extern PREG_NUM AssignExpr(WN *block, WN *tree, TYPE_ID type)
01454 {
01455   return AssignPregExprPos(block, tree, MTYPE_To_TY(type), current_srcpos,
01456          current_actions);
01457 }
01458 
01459 
01460 
01461 static BOOL WN_unconditional_goto(WN *tree)
01462 {
01463   switch(WN_operator(tree))
01464   {
01465   case OPR_GOTO:
01466   case OPR_REGION_EXIT:
01467   case OPR_RETURN:
01468   case OPR_RETURN_VAL:
01469 #ifdef KEY
01470   case OPR_GOTO_OUTER_BLOCK:
01471 #endif
01472     return TRUE;
01473   }
01474   return FALSE;
01475 }
01476 
01477 
01478 
01479 
01480 /* ====================================================================
01481  *
01482  * PARITY WN_parity(WN *tree)
01483  *
01484  * return the PARITY associated with a tree.
01485  *
01486  * Parity encapsulates dependence information, like complex real, imag
01487  * ==================================================================== */
01488 
01489 PARITY WN_parity(WN *tree)
01490 {
01491   if (WN_map_id(tree) != -1)
01492   {
01493     INT32 map;
01494 
01495     Is_True((lowering_parity_map != WN_MAP_UNDEFINED), ("parity map not initialized"));
01496 #ifdef KEY
01497     // Node may be deleted in which case the corresponding vertex and the 
01498     // associated edges should be deleted in the dependence graph but there
01499     // are lots of places in wn_lower.cxx that delete WNs without doing the
01500     // appropriate update to the dependence graph. So, assume the worst here.
01501     if (WN_operator(tree) == OPERATOR_UNKNOWN) return PARITY_UNKNOWN;
01502 #endif
01503     map = WN_MAP32_Get(lowering_parity_map, tree);
01504    
01505     if (map!=0)
01506       return (PARITY) map;
01507   }
01508   return PARITY_UNKNOWN;
01509 }
01510 
01511 BOOL WN_parity_independent(WN *wn1, WN *wn2)
01512 {
01513 
01514   if (wn1 == NULL   ||
01515       wn2 == NULL   ||
01516       WN_map_id(wn1) == -1  ||
01517       WN_map_id(wn2) == -1)
01518     return FALSE;
01519 
01520   {
01521     PARITY p1 = WN_parity(wn1);
01522     PARITY p2 = WN_parity(wn2);
01523 
01524    return (p1 & p2) ? FALSE : TRUE;
01525   }
01526 }
01527 
01528 
01529 static WN* get_original_wn (WN* derived) {
01530   WN* orig = NULL;
01531   if (wn_derivation_map != WN_MAP_UNDEFINED) {
01532     orig = (WN*)WN_MAP_Get (wn_derivation_map, derived);
01533   }
01534   
01535   return orig;
01536 }
01537  
01538 static void set_original_wn (WN* derived, WN* orig) {
01539   if (wn_derivation_map != WN_MAP_UNDEFINED) {
01540     WN_MAP_Set (wn_derivation_map, derived, (void*)orig);
01541   }
01542 }
01543 
01544 
01545 /* ====================================================================
01546  *
01547  *  MAP PRESERVATION
01548  *
01549  *
01550  * void lower_copy_maps(WN *orig, WN *tree, LOWER_ACTIONS action)
01551  *
01552  * void lower_complex_maps(WN *orig, WN *real, WN *imag, LOWER_ACTIONS action)
01553  *
01554  * void lower_quad_maps(WN *orig, WN *hipart, WN *lopart, LOWER_ACTIONS action)
01555  *
01556  *
01557  *  copy alias information to tree
01558  *
01559  * ==================================================================== */
01560 
01561 static void lower_maps_init(LOWER_ACTIONS actions)
01562 {
01563 
01564 }
01565 
01566 static void lower_maps_reset(LOWER_ACTIONS actions)
01567 {
01568   if (Action(LOWER_DEPGRAPH_MAPS))
01569   {
01570     LNOPruneMapsUsingParity();
01571   }
01572 }
01573 
01574 static void lower_map(WN *tree, LOWER_ACTIONS actions)
01575 {
01576   if (Action(LOWER_ALIAS_MAPS))
01577   {
01578     if (alias_manager)
01579     {
01580       if (Valid_alias(alias_manager, tree) == FALSE) {
01581         WN* orig = get_original_wn (tree);
01582         if (orig && Valid_alias (alias_manager, orig)) {
01583     Copy_alias_info(alias_manager, orig, tree);
01584   } else {
01585     Create_alias(alias_manager, tree);
01586   }
01587       }
01588     }
01589   }
01590 }
01591 
01592 static void lower_copy_maps(WN *orig, WN *tree, LOWER_ACTIONS actions)
01593 {
01594   if (orig == NULL)
01595     return;
01596 
01597  /*
01598   * The tree may no longer be valid at the point of call
01599   * (ie. may be deleted) so we must check validity
01600   */
01601   if (WN_has_map_id(orig))
01602   {
01603     if (WN_has_alias_info(orig) &&
01604         WN_has_alias_info(tree))
01605     {
01606       if (Action(LOWER_PREFETCH_MAPS))
01607       {
01608         WN_CopyMap(tree, WN_MAP_PREFETCH, orig);
01609       }
01610       if (Action(LOWER_ALIAS_MAPS))
01611       {
01612         if (alias_manager)
01613     Copy_alias_info(alias_manager, orig, tree);
01614       }
01615 
01616       // maintain the annotation whenever possible
01617       WN_MEMOP_ANNOT_MGR* p = WN_MEMOP_ANNOT_MGR::WN_mem_annot_mgr();
01618       if (p) {
01619         p->Copy_annot (orig, tree); 
01620       }
01621     }
01622   }
01623   WN_Set_Flags(orig, tree);
01624 }
01625 
01626 
01627 /*
01628  * If an original node has a TY with an f90_pointer attribute on it, copy it
01629  * to the TYs of the new nodes. node2 might be NULL (for cases in which we
01630  * only produce one new node)
01631  */
01632 static void lower_copy_tys (WN *orig, WN *node1, WN *node2) 
01633 {
01634   TY_IDX  ty;
01635 
01636   if (WN_operator_is(orig, OPR_ILOAD))
01637   {
01638     ty =  WN_load_addr_ty(orig);
01639 
01640     if (TY_is_f90_pointer(Ty_Table[ty]))
01641     {
01642       if (node1 && WN_operator_is(node1, OPR_ILOAD))
01643   WN_set_load_addr_ty(node1, ty);
01644 
01645       if (node2 && WN_operator_is(node2, OPR_ILOAD))
01646   WN_set_load_addr_ty(node2, ty);
01647     }
01648   }
01649   else if (WN_operator_is(orig, OPR_ISTORE))
01650   {
01651     ty =  WN_ty(orig);
01652     if (TY_is_f90_pointer(Ty_Table[ty]))
01653     {
01654       if (node1 && WN_operator_is(node1, OPR_ISTORE))
01655   WN_set_ty(node1, ty);
01656       if (node2 && WN_operator_is(node2, OPR_ISTORE))
01657   WN_set_ty(node2, ty);
01658     }
01659   }
01660 }
01661 
01662 
01663 static void lower_quad_maps(WN *orig, WN *hipart, WN *lopart,
01664           LOWER_ACTIONS actions)
01665 {
01666   lower_copy_maps(orig, hipart, actions);
01667   lower_copy_maps(orig, lopart, actions);
01668   lower_copy_tys(orig,hipart,lopart);
01669 
01670   if (Action(LOWER_DEPGRAPH_MAPS))
01671   {
01672     LNOPreserveMapPair(orig, hipart, lopart);
01673   }
01674 
01675   if (Action(LOWER_PARITY_MAPS))
01676   {
01677     WN_MAP32_Set(lowering_parity_map, hipart, PARITY_QUAD_HI);
01678     WN_MAP32_Set(lowering_parity_map, lopart, PARITY_QUAD_LO);
01679   }
01680 }
01681 
01682 static void lower_complex_maps(WN *orig, WN *real, WN *imag,
01683              LOWER_ACTIONS actions)
01684 {
01685   lower_copy_maps(orig, real, actions);
01686   lower_copy_maps(orig, imag, actions);
01687   lower_copy_tys(orig,real,imag);
01688 
01689   if (Action(LOWER_DEPGRAPH_MAPS))
01690   {
01691     LNOPreserveMapPair(orig, real, imag);
01692   }
01693 
01694   if (Action(LOWER_PARITY_MAPS))
01695   {
01696     WN_MAP32_Set(lowering_parity_map, real, PARITY_COMPLEX_REAL);
01697     WN_MAP32_Set(lowering_parity_map, imag, PARITY_COMPLEX_IMAG);
01698   }
01699 
01700 }
01701 
01702 static WN *add_to_base(WN **base, WN *tree)
01703 {
01704   if (*base)
01705   {
01706     return WN_Add(Pointer_type, *base, tree);
01707   }
01708   return tree;
01709 }
01710 
01711 static WN *sub_from_base(WN **base, WN *tree)
01712 {
01713   if (*base)
01714   {
01715     return WN_Sub(Pointer_type, *base, tree);
01716   }
01717   return tree;
01718 }
01719 
01720 static BOOL baseAddress(WN *tree)
01721 {
01722   switch(WN_operator(tree))
01723   {
01724   case OPR_LDA:
01725   case OPR_LDID:
01726   case OPR_ILOAD:
01727   case OPR_ILOADX:
01728     return TRUE;
01729   }
01730   return FALSE;
01731 }
01732 
01733 
01734 /* ====================================================================
01735  *
01736  * void lower_to_base_index(WN *addr, WN **base, WN **index) 
01737  *
01738  * Pattern match an address and create a bad/index for it
01739  *
01740  * Before this routine we would store the address in a preg
01741  * and use it (twice).  This would require the ST being marked
01742  * addr_taken_stored (very bad)
01743  *
01744  * This is getting worse and worse. Now the routine is recursive
01745  * for OPR_ADD.
01746  * 
01747  * 17 Dec 1998, R. Shapiro - Add a default case so that this routine never 
01748  *   fails. At worst, the trees get a little bigger. 
01749  *
01750  * ==================================================================== */
01751 
01752 static void lower_to_base_index(WN *addr, WN **base, WN **index) 
01753 {
01754   WN  *l, *r;
01755 
01756   switch (WN_operator(addr))
01757   {
01758   case OPR_ARRAY:
01759     *base  = add_to_base(base, WN_array_base(addr));
01760     *index = add_to_base(index, addr);
01761     WN_array_base(addr) = WN_Zerocon(WN_rtype(addr));
01762     break;
01763 
01764   case OPR_ADD:
01765     l = WN_kid0(addr);
01766     r = WN_kid1(addr);
01767 
01768     if (baseAddress(l))
01769     {
01770       *base  = add_to_base(base, l);
01771       *index = add_to_base(index, r);
01772     }
01773     else if (baseAddress(r))
01774     {
01775       *base  = add_to_base(base, r);
01776       *index = add_to_base(index, l);
01777     }
01778     else if (WN_operator_is(r, OPR_ARRAY))
01779     {
01780       *base  = add_to_base(base, WN_array_base(r));
01781       WN_array_base(r) = WN_Zerocon(WN_rtype(r));
01782       *index = add_to_base(index, addr);
01783     }
01784     else if (WN_operator_is(l, OPR_ARRAY))
01785     {
01786       *base  = add_to_base(base, WN_array_base(l));
01787       WN_array_base(l) = WN_Zerocon(WN_rtype(l));
01788       *index = add_to_base(index, addr);
01789     }
01790     else if ((WN_operator_is(r, OPR_ADD)  ||  WN_operator_is(r, OPR_SUB))
01791        && WN_operator_is(l, OPR_INTCONST))
01792     {
01793       lower_to_base_index(r, base, index);
01794       *index = add_to_base(index, l);
01795     }
01796     else if ((WN_operator_is(l, OPR_ADD)  ||  WN_operator_is(l, OPR_SUB)) 
01797        && WN_operator_is(r, OPR_INTCONST))
01798     {
01799       lower_to_base_index(l, base, index);
01800       *index = add_to_base(index, r);
01801     }
01802     else
01803     {
01804       // Give up
01805       *base  = add_to_base(base, addr);
01806       *index = add_to_base(index, WN_Zerocon(WN_rtype(addr)));
01807     }
01808     break;
01809 
01810   case OPR_SUB:
01811     l = WN_kid0(addr);
01812     r = WN_kid1(addr);
01813 
01814     if (baseAddress(l))
01815     {
01816       *base  = add_to_base(base, l);
01817       *index = sub_from_base(index, r);
01818     }
01819     else if (baseAddress(r))
01820     {
01821       *base  = sub_from_base(base, r);
01822       *index = add_to_base(index, l);
01823     }
01824     else if (WN_operator_is(r, OPR_ARRAY))
01825     {
01826       *base  =  sub_from_base(base, WN_array_base(r));
01827       WN_array_base(r) = WN_Zerocon(WN_rtype(r));
01828       *index =  add_to_base(index, addr);
01829     }
01830     else if (WN_operator_is(l, OPR_ARRAY))
01831     {
01832       *base  = add_to_base(base, WN_array_base(l));
01833       WN_array_base(l) = WN_Zerocon(WN_rtype(l));
01834       *index = add_to_base(index, addr);
01835     }
01836     else if ((WN_operator_is(r, OPR_ADD) ||  WN_operator_is(r, OPR_SUB))
01837        && WN_operator_is(l, OPR_INTCONST))
01838     {
01839       lower_to_base_index(r, base, index);
01840       *base  = WN_Neg(WN_rtype(*base),*base);
01841       *index = sub_from_base(&l,*index);
01842     }
01843     else if ((WN_operator_is(l, OPR_ADD) || WN_operator_is(l, OPR_SUB)) 
01844        && WN_operator_is(r, OPR_INTCONST))
01845     {
01846       lower_to_base_index(l, base, index);
01847       *index = sub_from_base(index, r);
01848     }
01849     else
01850     {
01851       // Give up
01852       *base  = add_to_base(base, addr);
01853       *index = add_to_base(index, WN_Zerocon(WN_rtype(addr)));
01854     }
01855     break;
01856   default:
01857     // Give up
01858     *base  = add_to_base(base, addr);
01859     *index = add_to_base(index, WN_Zerocon(WN_rtype(addr)));
01860     break;
01861   }
01862 }
01863 
01864 
01865 /*
01866  * Describe a leaf expression (see Make_Leaf/Load_Leaf).
01867  */
01868 typedef enum {LEAF_IS_CONST, LEAF_IS_INTCONST, LEAF_IS_PREG} LEAF_KIND;
01869 typedef struct {
01870   LEAF_KIND kind;
01871   TYPE_ID type;
01872   union {
01873     PREG_NUM n;
01874     INT64 intval;
01875     TCON tc;
01876   } u;
01877 } LEAF;
01878 
01879 /* ====================================================================
01880  *
01881  * LEAF Make_Leaf(WN *block, WN *tree, TYPE_ID type)
01882  *
01883  * Make an aribtrary expression tree into a leaf.
01884  * If the expression is an integer or floating point constant
01885  * no transformation is made. However, other expressions are stored
01886  * into a PREG.
01887  *
01888  * Make_Leaf is used in place of AssignExpr when performing a sort
01889  * of "poor man's" CSE, and you want to avoid creating unnecessary
01890  * PREGs for constants (which can also thwart the simplifier).
01891  *
01892  * ==================================================================== */
01893 
01894 static LEAF Make_Leaf(WN *block, WN *tree, TYPE_ID type)
01895 {
01896   LEAF leaf;
01897   leaf.type = type;
01898   switch (WN_operator(tree)) {
01899   case OPR_CONST:
01900     leaf.kind = LEAF_IS_CONST;
01901     leaf.u.tc = Const_Val(tree);
01902     WN_Delete(tree);
01903     break;
01904   case OPR_INTCONST:
01905     leaf.kind = LEAF_IS_INTCONST;
01906     leaf.u.intval = WN_const_val(tree);
01907     WN_Delete(tree);
01908     break;
01909   default:
01910     leaf.kind = LEAF_IS_PREG;
01911     leaf.u.n = AssignExpr(block, tree, type);
01912     break;
01913   }
01914   return leaf;
01915 }
01916 
01917 /* ====================================================================
01918  *
01919  * WN *Load_Leaf(const LEAF &leaf)
01920  *
01921  * Generate whirl to load the value of a leaf expression created by
01922  * Make_Leaf().
01923  *
01924  * ==================================================================== */
01925 
01926 static WN *Load_Leaf(const LEAF &leaf)
01927 {
01928   switch (leaf.kind) {
01929   case LEAF_IS_CONST:
01930     return Make_Const(leaf.u.tc);
01931   case LEAF_IS_INTCONST:
01932     return WN_CreateIntconst(OPR_INTCONST, leaf.type, MTYPE_V, leaf.u.intval);
01933   case LEAF_IS_PREG:
01934     return WN_LdidPreg(leaf.type, leaf.u.n);
01935   }
01936   FmtAssert(FALSE, ("unhandled leaf kind in Load_Leaf"));
01937   /*NOTREACHED*/
01938 }
01939 
01940 /* ====================================================================
01941  *
01942  * void lower_complex_expr(WN *block, WN *tree, LOWER_ACTIONS actions,
01943  *         WN **realpart, WN **imagpart)
01944  *
01945  * Split complex-type expression <tree> into its lowered real and
01946  * imaginary parts.  <actions> must include LOWER_COMPLEX.  Note that
01947  * like the other lowering functions, this one destroys <tree>.  Upon
01948  * return, *<realpart> points to the real part, and *<imagpart> points
01949  * to the imaginary part.
01950  *
01951  * ==================================================================== */
01952 
01953 static void lower_complex_expr(WN *block, WN *tree, LOWER_ACTIONS actions,
01954              WN **realpart, WN **imagpart)
01955 {
01956   TYPE_ID type;
01957 
01958 
01959   Is_True(OPCODE_is_expression(WN_opcode(tree)),
01960     ("expected expression node, not %s", OPCODE_name(WN_opcode(tree))));
01961   Is_True(Action(LOWER_COMPLEX), ("actions does not contain LOWER_COMPLEX"));
01962 #ifndef TARG_X8664 // could be MTYPE_F8 that contains a MTYPE_C4
01963   Is_True((MTYPE_is_complex(WN_rtype(tree))),
01964     ("expected complex-type node, not %s",
01965      OPCODE_name(WN_opcode(tree))));
01966 #endif
01967   type = Mtype_complex_to_real(WN_rtype(tree));
01968 
01969  /*
01970   *  Complex Arithmetic Notation
01971   *
01972   *  Let R(c) = real part of c
01973   *      I(c) = imaginary part of c
01974   *
01975   *  then, if z is complex it can be represented as follows
01976   *
01977   *      z= R(z) + I(z)i
01978   *
01979   */
01980   switch (WN_operator(tree))
01981   {
01982   case OPR_LDID:
01983     {
01984      /*
01985       *  we must create a new ST of type real
01986       *  we implicitly assume the storage of complex is
01987       *    z =  {  R(z) , I(z) }
01988       */
01989       TY_IDX    beTY   = MTYPE_To_TY(type);
01990       WN_OFFSET offset = WN_load_offset(tree);
01991 
01992       if (WN_class(tree) == CLASS_CONST && offset == 0)
01993       {
01994   TCON  val = WN_val(tree);
01995   TYPE_ID valType = WN_val_type(tree);
01996 
01997   if (WN_rtype(tree) == valType)
01998   {
01999     *realpart = Make_Const( Extract_Complex_Real(val));
02000     *imagpart = Make_Const( Extract_Complex_Imag(val));
02001     break;
02002   }
02003       }
02004 
02005       *realpart = WN_Ldid(type, offset,
02006         coerceST(WN_st(tree), type),
02007         beTY);
02008 
02009       *imagpart = WN_Ldid(type,
02010         coerceOFFSET(tree, type, offset),
02011         coerceST(WN_st(tree), type),
02012         beTY);
02013     }
02014     break;
02015 
02016   case OPR_ILOAD:
02017     {
02018      /*
02019       *  we implicitly assume the storage of complex is
02020       *    z =  {  R(z) , I(z) }
02021       *
02022       *  The LOWER_BASE_INDEX will try to split the address into a
02023       *  base and index. The index is put in a preg (and reused) while
02024       *  the base is cloned.
02025       */
02026       WN_OFFSET offset = WN_load_offset(tree);
02027 
02028       if (Action(LOWER_BASE_INDEX))
02029       {
02030   WN  *addr, *base, *index;
02031   LEAF  indexN;
02032 
02033   base = index= NULL;
02034   lower_to_base_index(WN_kid0(tree), &base, &index) ;
02035 
02036   base = lower_expr(block, base, actions);
02037   index = lower_expr(block, index, actions);
02038 
02039   indexN = Make_Leaf(block, index, Pointer_type);
02040   
02041   addr = WN_Add(Pointer_type,
02042           Load_Leaf(indexN),
02043           lower_copy_tree(base, actions)); 
02044 
02045   *realpart = WN_Iload(type,
02046            offset,
02047            coerceTY(WN_ty(tree), type),
02048            addr);
02049 
02050   addr = WN_Add(Pointer_type, Load_Leaf(indexN), base);
02051 
02052   *imagpart = WN_Iload(type,
02053            coerceOFFSET(tree, type, offset),
02054            coerceTY(WN_ty(tree), type),
02055            addr);
02056       }
02057       else
02058       {
02059   WN  *addr;
02060   LEAF  addrN;
02061   
02062   addr = lower_expr(block, WN_kid0(tree), actions);
02063   
02064   addrN = Make_Leaf(block, addr, Pointer_type);
02065   
02066   *realpart = WN_Iload(type,
02067            offset,
02068            coerceTY(WN_ty(tree), type),
02069            Load_Leaf(addrN));
02070   
02071   *imagpart = WN_Iload(type,
02072            coerceOFFSET(tree, type, offset),
02073            coerceTY(WN_ty(tree), type),
02074            Load_Leaf(addrN));
02075       }
02076       lower_complex_maps(tree, *realpart, *imagpart, actions);
02077     }
02078     break;
02079 
02080   case OPR_ILOADX:
02081     Is_True(FALSE, ("unexpected complex ILOADX"));
02082     break;
02083 
02084   case OPR_NEG:
02085     {
02086      /*
02087       *    -z  = -R(z) + -I(z)i
02088       */
02089       WN  *rz, *iz;
02090 
02091       lower_complex_expr(block, WN_kid0(tree), actions, &rz, &iz);
02092       *realpart = WN_Neg( type, rz);
02093       *imagpart = WN_Neg( type, iz);
02094 
02095     }
02096     break;
02097 
02098   case OPR_ADD:
02099     {
02100       WN  *rz, *rw, *iz, *iw;
02101      /*
02102       *    z + w = (R(z) + R(w)) + (I(z) + I(w))i
02103       */
02104 
02105       lower_complex_expr(block, WN_kid0(tree), actions, &rz, &iz);
02106       lower_complex_expr(block, WN_kid1(tree), actions, &rw, &iw);
02107  
02108       *realpart = WN_Add( type, rz, rw);
02109       *imagpart = WN_Add( type, iz, iw);
02110     }
02111     break;
02112 
02113   case OPR_SUB:
02114     {
02115      /*
02116       *    z - w = (R(z) - R(w)) + (I(z) - I(w))i
02117       */
02118       WN  *rz, *rw, *iz, *iw;
02119 
02120       lower_complex_expr(block, WN_kid0(tree), actions, &rz, &iz);
02121       lower_complex_expr(block, WN_kid1(tree), actions, &rw, &iw);
02122  
02123       *realpart = WN_Sub( type, rz, rw);
02124       *imagpart = WN_Sub( type, iz, iw);
02125     }
02126     break;
02127 
02128   case OPR_MPY:
02129     {
02130      /*
02131       *    z * w = (R(z)*R(w) - I(z)*I(w)) + (R(z)*I(w)+ R(w)*I(z))i
02132       *
02133       */
02134       WN  *rz, *rw, *iz, *iw;
02135       LEAF  rzN, rwN, izN, iwN;
02136 
02137       lower_complex_expr(block, WN_kid0(tree), actions, &rz, &iz);
02138       lower_complex_expr(block, WN_kid1(tree), actions, &rw, &iw);
02139 
02140       rzN = Make_Leaf(block, rz, type);
02141       rwN = Make_Leaf(block, rw, type);
02142       izN = Make_Leaf(block, iz, type);
02143       iwN = Make_Leaf(block, iw, type);
02144 
02145       *realpart = WN_Sub(type,
02146        WN_Mpy(type, Load_Leaf(rzN), Load_Leaf(rwN)),
02147        WN_Mpy(type, Load_Leaf(izN), Load_Leaf(iwN)));
02148 
02149       *imagpart = WN_Add(type,
02150        WN_Mpy(type, Load_Leaf(rzN), Load_Leaf(iwN)),
02151        WN_Mpy(type, Load_Leaf(rwN), Load_Leaf(izN)));
02152     }
02153     break;
02154 
02155   case OPR_COMPLEX:
02156     /*
02157      *  Create a complex number from two real children, ie.
02158      *    z = CMPLX(x,y)
02159      *    z = (x) + (y) i
02160      */
02161     *realpart = lower_expr(block, WN_kid0(tree), actions);
02162     *imagpart = lower_expr(block, WN_kid1(tree), actions);
02163     // Fix for bug# 414
02164     //WN_Delete(tree);
02165     break;
02166 
02167   case OPR_MADD:
02168   case OPR_MSUB:
02169   case OPR_NMADD:
02170   case OPR_NMSUB:
02171     Is_True( FALSE, ("unexpected complex madd"));
02172     break;
02173 
02174   case OPR_CVT:
02175     {
02176       WN  *rz, *iz;
02177       TYPE_ID desc = WN_desc(tree);
02178 
02179       lower_complex_expr(block, WN_kid0(tree), actions, &rz, &iz);
02180  
02181       *realpart = WN_Cvt( type, Mtype_complex_to_real(desc), rz);
02182       *imagpart = WN_Cvt( type, Mtype_complex_to_real(desc), iz);
02183     }
02184     break;
02185 
02186   case OPR_CONST:
02187     {
02188      /*
02189       * extract the real and imaginary parts of the complex number
02190       */
02191       TCON  val = Const_Val(tree);
02192 
02193       *realpart = Make_Const( Extract_Complex_Real(val));
02194       *imagpart = Make_Const( Extract_Complex_Imag(val));
02195 
02196       // Fix for Bug# 496
02197       //WN_Delete(tree);
02198     }
02199     break;
02200 
02201   case OPR_RSQRT:
02202     {
02203       TYPE_ID desc = WN_desc(tree);
02204       WN  *div;
02205 
02206       div = WN_Div(desc,
02207        WN_Floatconst(desc, 1.0),
02208        WN_Sqrt(desc, WN_kid0(tree)));
02209 
02210       lower_complex_expr(block, div, actions, realpart, imagpart);
02211 
02212       WN_Delete(tree);
02213     }
02214     break;
02215 
02216   case OPR_SQRT:
02217     lower_complex_emulation(block, tree, actions, realpart, imagpart);
02218     break;
02219 
02220 
02221   case OPR_PAREN:
02222     {
02223       lower_complex_expr(block, WN_kid0(tree), actions, realpart, imagpart);
02224 
02225       *realpart = WN_Paren(type, *realpart);
02226       *imagpart = WN_Paren(type, *imagpart);
02227       WN_Delete(tree);
02228     }
02229     break;
02230 
02231   case OPR_ARRAY:
02232     break;
02233 
02234   case OPR_RECIP:
02235     {
02236       /* TODO_FEEDBACK: Get frequencies right, especially when we
02237        * create an IF statement. We have to assume half the frequency
02238        * goes to the then part and half goes to the else part; there's
02239        * no other information available, is there?
02240        */
02241 
02242       LEAF  rzN, izN;
02243       {
02244        /*
02245   *  assign pregs to their corresponding expressions
02246   *  Since the expressions will be reused, this avoids building a DAG
02247   */
02248   WN  *rz, *iz; 
02249     
02250   lower_complex_expr(block, WN_kid0(tree), actions, &rz, &iz);
02251       
02252   rzN = Make_Leaf(block, rz, type);
02253   izN = Make_Leaf(block, iz, type);
02254       }
02255     
02256       if (Fast_Complex_Allowed)
02257       {
02258        /*
02259   *   1 / z
02260   *    real = (   R(z) ) /  ( R(z)**2 + I(z)**2 )
02261   *    imag = ( - I(z) ) /  ( R(z)**2 + I(z)**2 )
02262   *
02263   */
02264   LEAF  denomN;
02265   WN  *rz2, *iz2, *add;
02266     
02267   rz2 = WN_Mpy(type, Load_Leaf(rzN), Load_Leaf(rzN));
02268   iz2 = WN_Mpy(type, Load_Leaf(izN), Load_Leaf(izN));
02269   add = WN_Add(type, rz2, iz2);
02270   denomN = Make_Leaf(block, add, type);
02271     
02272   *realpart = WN_Div(type, Load_Leaf(rzN), Load_Leaf(denomN));
02273   *imagpart = WN_Neg(type,
02274          WN_Div(type, Load_Leaf(izN), Load_Leaf(denomN)));
02275       }
02276       else
02277       {
02278        /*
02279   *   1 / z
02280   *    real = (   R(z) ) /  ( R(z)**2 + I(z)**2 )
02281   *    imag = ( - I(z) ) /  ( R(z)**2 + I(z)**2 )
02282   *
02283   *    After factoring out max( |R(z)| , |I(z)| )
02284   *
02285   * | R(z) | >  | I(z) |
02286   *
02287   * Let x = I(z) / R(z)
02288   * real = ( 1 )    /  ( R(z) + I(z)*x)
02289   * imag = ( - x )  /  ( R(z) + I(z)*x)
02290   *
02291   * | I(z) | >  | R(z) |
02292   *
02293   * Let x = R(z) / I(z)
02294   * real = ( x )   /  ( R(z)*x + I(z) )
02295   * imag = (-1 )   /  ( R(z)*x + I(z) )
02296   *
02297   */
02298   WN    *if_then, *if_else, *IF;
02299   PREG_NUM  realpartN, imagpartN;
02300   LEAF    xN, arzN, aizN;
02301     
02302   {
02303     WN  *numer, *denom, *div;
02304     
02305     arzN = Make_Leaf(block,
02306          WN_Abs(type, Load_Leaf(rzN)),
02307              type);
02308     
02309     aizN = Make_Leaf(block,
02310              WN_Abs(type, Load_Leaf(izN)),
02311              type);
02312     
02313    /*
02314     *  numer =  | R(w) | >  | I(w) |  ?  I(w) : R(x)
02315     *  denom =  | R(w) | >  | I(w) |  ?  R(w) : I(x)
02316     *
02317     *  Let x = numer / denom
02318     */
02319     numer = WN_Select(type,
02320           WN_GT(type, Load_Leaf(arzN), Load_Leaf(aizN)),
02321               Load_Leaf(izN),
02322               Load_Leaf(rzN));
02323     denom = WN_Select(type,
02324           WN_GT(type, Load_Leaf(arzN), Load_Leaf(aizN)),
02325               Load_Leaf(rzN),
02326                 Load_Leaf(izN));
02327 
02328     div = WN_Div(type, numer, denom);
02329 
02330     xN = Make_Leaf(block, div, type);
02331   }
02332 
02333   if_then = WN_CreateBlock();
02334   {
02335    /*
02336     * scale = ( R(z) + I(z)*x )
02337     * real = ( 1 )    /  scale
02338     * imag = ( - x )  /  scale
02339     */
02340     WN  *scale, *div;
02341     LEAF  scaleN;
02342     
02343     scale = WN_Add(type,
02344        Load_Leaf(rzN),
02345        WN_Mpy(type, Load_Leaf(izN), Load_Leaf(xN)));
02346     scaleN = Make_Leaf(if_then, scale, type);
02347 
02348     div = WN_Inverse(type, Load_Leaf(scaleN));
02349 
02350     realpartN = AssignExpr(if_then, div, type);
02351 
02352     div =  WN_Div(type,
02353       WN_Neg(type, Load_Leaf(xN)),
02354       Load_Leaf(scaleN));
02355     
02356     imagpartN = AssignExpr(if_then, div, type);
02357   }
02358 
02359   if_else = WN_CreateBlock();
02360   {
02361    /*
02362     * scale = ( R(z)*x + I(z) )
02363     * real = ( x )   /  scale
02364     * imag = ( 1 )   /  scale
02365     */
02366     WN  *scale, *div, *stid;
02367     LEAF  scaleN;
02368     ST  *preg = MTYPE_To_PREG(type);
02369     
02370     scale = WN_Add(type,
02371        WN_Mpy(type, Load_Leaf(rzN), Load_Leaf(xN)),
02372        Load_Leaf(izN));
02373     scaleN = Make_Leaf(if_else, scale, type);
02374 
02375     div =  WN_Div(type, Load_Leaf(xN), Load_Leaf(scaleN));
02376     stid = WN_StidIntoPreg(type, realpartN, preg, div);
02377     WN_Set_Linenum(stid, current_srcpos);  // Bug 1268
02378     WN_INSERT_BlockLast(if_else, stid);
02379     
02380     div = WN_Neg(type,WN_Inverse(type, Load_Leaf(scaleN)));
02381     stid = WN_StidIntoPreg(type, imagpartN, preg, div);
02382     WN_Set_Linenum(stid, current_srcpos);  // Bug 1268
02383     WN_INSERT_BlockLast(if_else, stid);
02384   }
02385     
02386   IF =  WN_CreateIf(WN_GT(type, Load_Leaf(arzN), Load_Leaf(aizN)),
02387         if_then, if_else);
02388 
02389   if ( Cur_PU_Feedback ) {
02390     Cur_PU_Feedback->Annot( IF, FB_EDGE_BRANCH_TAKEN, FB_FREQ_UNKNOWN );
02391     Cur_PU_Feedback->Annot( IF, FB_EDGE_BRANCH_NOT_TAKEN,
02392           FB_FREQ_UNKNOWN );
02393   }
02394 
02395   WN_INSERT_BlockLast(block, lower_if(block, IF, actions));
02396     
02397   *realpart = WN_LdidPreg(type, realpartN);
02398   *imagpart = WN_LdidPreg(type, imagpartN);
02399       }
02400       WN_Delete(tree);
02401     }
02402     break;
02403 
02404   case OPR_DIV:
02405     {
02406      /*
02407       *  assign pregs to their corresponding expressions
02408       *  Since the expressions will be reused, this avoids building a DAG
02409       */
02410       WN  *rz, *rw, *iz, *iw; 
02411       LEAF  rzN, rwN, izN, iwN;
02412 
02413       lower_complex_expr(block, WN_kid0(tree), actions, &rz, &iz);
02414       lower_complex_expr(block, WN_kid1(tree), actions, &rw, &iw);
02415   
02416       rzN = Make_Leaf(block, rz, type);
02417       izN = Make_Leaf(block, iz, type);
02418       rwN = Make_Leaf(block, rw, type);
02419       iwN = Make_Leaf(block, iw, type);
02420 
02421       if (Fast_Complex_Allowed)
02422       {
02423        /*
02424   *   z / w
02425   *    real = (R(z)*R(w) + I(z)*I(w) /  ( R(w)**2 + I(w)**2 )
02426   *    imag = (I(z)*R(w) - R(z)*I(w) /  ( R(w)**2 + I(w)**2 )
02427   *
02428   */
02429   LEAF  denomN;
02430   {
02431     WN  *rw2, *iw2, *add;
02432     
02433     rw2 = WN_Mpy(type,Load_Leaf(rwN), Load_Leaf(rwN));
02434     iw2 = WN_Mpy(type, Load_Leaf(iwN), Load_Leaf(iwN));
02435     add = WN_Add(type, rw2, iw2);
02436     denomN = Make_Leaf(block, add, type);
02437   }
02438   {
02439     WN  *rzrw, *iziw;
02440     
02441     rzrw = WN_Mpy(type, Load_Leaf(rzN), Load_Leaf(rwN));
02442     iziw = WN_Mpy(type, Load_Leaf(izN), Load_Leaf(iwN));
02443     *realpart = WN_Div(type,
02444            WN_Add(type, rzrw, iziw),
02445            Load_Leaf(denomN));
02446   }
02447   {
02448     WN  *rziw, *izrw;
02449     
02450     izrw = WN_Mpy(type, Load_Leaf(izN), Load_Leaf(rwN));
02451     rziw = WN_Mpy(type, Load_Leaf(rzN), Load_Leaf(iwN));
02452     *imagpart = WN_Div(type,
02453            WN_Sub(type, izrw, rziw),
02454            Load_Leaf(denomN));
02455   }
02456       }
02457       else
02458       {
02459        /*
02460   *   z / w
02461   *    real = (R(z)*R(w) + I(z)*I(w) /  ( R(w)**2 + I(w)**2 )
02462   *    imag = (I(z)*R(w) - R(z)*I(w) /  ( R(w)**2 + I(w)**2 )
02463   *
02464   *    After factoring out max( |R(w)| , |I(w)| )
02465   *
02466   * | R(w) | >  | I(w) |
02467   *
02468   * Let x = I(w) / R(w)
02469   *   real = ( R(z) + I(z)*x ) /  ( R(w) + I(w)*x )
02470   *   imag = ( I(z) - R(z)*x ) /  ( R(w) + I(w)*x )
02471   *
02472   * | I(w) | >  | R(w) |
02473   *
02474   * Let x = R(w) / I(w)
02475   *   real = ( R(z)*x + I(z) ) /  ( R(w)*x + I(w) )
02476   *   imag = ( I(z)*x - R(z) ) /  ( R(w)*x + I(w) )
02477   *
02478   */
02479   WN    *if_then, *if_else, *IF;
02480   LEAF    xN, arwN, aiwN;
02481   PREG_NUM  realpartN, imagpartN;
02482   {
02483     WN  *numer, *denom, *div;
02484     
02485     arwN = Make_Leaf(block,
02486              WN_Abs(type, Load_Leaf(rwN)),
02487              type);
02488     aiwN = Make_Leaf(block,
02489              WN_Abs(type, Load_Leaf(iwN)),
02490              type);
02491     
02492    /*
02493     *  numer =  | R(w) | >  | I(w) |  ?  I(w) : R(x)
02494     *  denom =  | R(w) | >  | I(w) |  ?  R(w) : I(x)
02495     *
02496     *  Let x = numer / denom
02497     */
02498     numer = WN_Select(type,
02499           WN_GT(type, Load_Leaf(arwN), Load_Leaf(aiwN)),
02500               Load_Leaf(iwN),
02501           Load_Leaf(rwN));
02502     denom = WN_Select(type,
02503           WN_GT(type, Load_Leaf(arwN), Load_Leaf(aiwN)),
02504               Load_Leaf(rwN),
02505               Load_Leaf(iwN));
02506     div = WN_Div(type, numer, denom);
02507     xN = Make_Leaf(block, div, type);
02508   }
02509 
02510   if_then = WN_CreateBlock();
02511   {
02512     WN    *scale;
02513     LEAF  scaleN;
02514     
02515     scale = WN_Add(type,
02516        Load_Leaf(rwN),
02517        WN_Mpy(type, Load_Leaf(iwN), Load_Leaf(xN)));
02518     scaleN = Make_Leaf(if_then, scale, type);
02519     {
02520      /*
02521           *  real = ( R(z)   + I(z)*x )  / scale
02522           */
02523           WN  *numer, *div;
02524     
02525           numer = WN_Add(type,
02526            Load_Leaf(rzN),
02527            WN_Mpy(type, Load_Leaf(izN), Load_Leaf(xN)));
02528       div = WN_Div(type, numer, Load_Leaf(scaleN));
02529       realpartN = AssignExpr(if_then, div, type);
02530     }
02531     {
02532      /*
02533       *  imag = ( I(z) - R(z)*x ) /  scale
02534           */
02535           WN  *numer, *div;
02536     
02537       numer = WN_Sub(type,
02538              Load_Leaf(izN),
02539          WN_Mpy(type, Load_Leaf(rzN), Load_Leaf(xN)));
02540       div = WN_Div(type, numer, Load_Leaf(scaleN));
02541           imagpartN = AssignExpr(if_then, div, type);
02542     }
02543   }
02544     
02545   if_else = WN_CreateBlock();
02546   {
02547     WN  *scale;
02548     LEAF  scaleN;
02549     ST  *preg = MTYPE_To_PREG(type);
02550 
02551     scale = WN_Add(type,
02552        WN_Mpy(type, Load_Leaf(rwN), Load_Leaf(xN)),
02553            Load_Leaf(iwN));
02554     scaleN = Make_Leaf(if_else, scale, type);
02555     {
02556      /*
02557           *  real = ( R(z)*x + I(z) ) /  scale
02558           *  store away result in an already defined preg
02559           */
02560           WN  *numer, *div, *stid;
02561     
02562           numer =  WN_Add(type,
02563               WN_Mpy(type, Load_Leaf(rzN), Load_Leaf(xN)),
02564               Load_Leaf(izN));
02565       div = WN_Div(type, numer, Load_Leaf(scaleN));
02566       stid = WN_StidIntoPreg(type, realpartN, preg, div);
02567       WN_Set_Linenum(stid, current_srcpos);  // Bug 1268
02568       WN_INSERT_BlockLast(if_else, stid);
02569     }
02570     {
02571      /*
02572       *  imag = ( I(z)*x - R(z) ) /  scale
02573           *  store away result in an already defined preg
02574           */
02575           WN  *numer, *div, *stid;
02576     
02577           numer = WN_Sub(type,
02578              WN_Mpy(type, Load_Leaf(izN), Load_Leaf(xN)),
02579              Load_Leaf(rzN));
02580       div = WN_Div(type, numer, Load_Leaf(scaleN));
02581       stid = WN_StidIntoPreg(type, imagpartN, preg, div);
02582       WN_Set_Linenum(stid, current_srcpos);  // Bug 1268
02583       WN_INSERT_BlockLast(if_else, stid);
02584     }
02585   }
02586     
02587   IF =  WN_CreateIf(WN_GT(type, Load_Leaf(arwN), Load_Leaf(aiwN)),
02588         if_then, if_else);
02589 
02590   if ( Cur_PU_Feedback ) {
02591     Cur_PU_Feedback->Annot( IF, FB_EDGE_BRANCH_TAKEN, FB_FREQ_UNKNOWN );
02592     Cur_PU_Feedback->Annot( IF, FB_EDGE_BRANCH_NOT_TAKEN,
02593           FB_FREQ_UNKNOWN );
02594   }
02595     
02596   WN_INSERT_BlockLast(block, lower_if(block, IF, actions));
02597     
02598   *realpart = WN_LdidPreg(type, realpartN);
02599   *imagpart = WN_LdidPreg(type, imagpartN);
02600       }
02601       WN_Delete(tree);
02602     }
02603     break;
02604 
02605   case OPR_RND:
02606   case OPR_TRUNC:
02607   case OPR_MOD:
02608   case OPR_REM:
02609   case OPR_ABS:
02610     Fail_FmtAssertion("unexpected complex op (%s)",
02611           OPCODE_name(WN_opcode(tree)));
02612     /*NOTREACHED*/
02613 
02614   case OPR_INTRINSIC_OP:
02615     {
02616       INTRINSIC     id = (INTRINSIC) WN_intrinsic(tree);
02617 
02618       switch(id)
02619       {
02620       case INTRN_C4CONJG:
02621       case INTRN_C8CONJG:
02622       case INTRN_CQCONJG:
02623   {
02624     WN  *iz;
02625 
02626     lower_complex_expr(block, WN_actual(tree, 0), actions,
02627            realpart, &iz);
02628 
02629     *imagpart = WN_Neg(type, iz);
02630 
02631     WN_Delete(tree);
02632   }
02633         break;
02634 
02635   //*****************************************************************
02636   //
02637   // N.B. Any complex intrinsic which does not have an emulation must
02638   // appear in the list below.
02639   //
02640 
02641   //       case INTRN_F4CIS:
02642   //case INTRN_F8CIS:
02643   //case INTRN_FQCIS:
02644   //  actions |= LOWER_INTRINSIC;
02645     /* Fall Through */
02646 
02647       default:
02648   if (INTRN_is_actual(WN_intrinsic(tree)))
02649   {
02650     tree = lower_intrinsic(block, tree, actions);
02651   }
02652   else
02653   {
02654     lower_complex_emulation(block, tree, actions, realpart, imagpart);
02655   }
02656         break;
02657       }
02658     }
02659     break;
02660 
02661   case OPR_SELECT:
02662     {
02663        WN *r1, *i1;
02664        WN *r2, *i2;
02665        LEAF cond;
02666        
02667        cond = Make_Leaf(block, WN_kid0(tree), WN_rtype(WN_kid0(tree)));
02668        
02669        lower_complex_expr(block, WN_kid1(tree), actions, &r1, &i1);
02670        lower_complex_expr(block, WN_kid2(tree), actions, &r2, &i2);
02671        
02672        *realpart = WN_Select(type, Load_Leaf(cond), r1, r2);
02673        *imagpart = WN_Select(type, Load_Leaf(cond), i1, i2);
02674     }
02675     break;
02676 
02677   case OPR_PARM:
02678     lower_complex_expr(block, WN_kid0(tree), actions, realpart, imagpart);
02679     break;
02680   }
02681 }
02682 
02683 
02684 
02685 
02686 /* ====================================================================
02687  *
02688  * void lower_quad_expr(WN *block, WN *tree, LOWER_ACTIONS actions,
02689  *         WN **hipart, WN **lopart)
02690  *
02691  * ==================================================================== */
02692 
02693 static void lower_quad_expr(WN *block, WN *tree, LOWER_ACTIONS actions,
02694              WN **hipart, WN **lopart)
02695 {
02696   TYPE_ID type =  MTYPE_F8;
02697 
02698 
02699   Is_True(OPCODE_is_expression(WN_opcode(tree)),
02700     ("expected expression node, not %s", OPCODE_name(WN_opcode(tree))));
02701   Is_True(actions & LOWER_QUAD, ("actions does not contain LOWER_QUAD"));
02702   Is_True((MTYPE_is_quad(WN_rtype(tree))),
02703     ("expected quad-type node, not %s", OPCODE_name(WN_opcode(tree))));
02704  /*
02705   *  first lower the quad as expressions.
02706   *
02707   *  This will create and serialize a call chain
02708   *  that should always return a leaf that can be decomposed
02709   */
02710   tree = lower_expr(block, tree, actions);
02711 
02712   switch (WN_operator(tree))
02713   {
02714   case OPR_LDID:
02715     {
02716      /*
02717       *  we must create a new ST of type real*8
02718       */
02719       TY_IDX    beTY   = MTYPE_To_TY(type);
02720       WN_OFFSET offset = WN_load_offset(tree);
02721 
02722       *hipart = WN_Ldid(type, offset,
02723       coerceST(WN_st(tree), type), beTY);
02724 
02725       *lopart = WN_Ldid(type,
02726       coerceOFFSET(tree, type, offset),
02727       coerceST(WN_st(tree), type),
02728       beTY);
02729 
02730       lower_quad_maps(tree, *hipart, *lopart, actions);
02731     }
02732     break;
02733 
02734   case OPR_ILOAD:
02735     {
02736       WN  *addr;
02737       WN_OFFSET offset = WN_load_offset(tree);
02738       LEAF  addrN;
02739 
02740       addr = lower_expr(block, WN_kid0(tree), actions);
02741 
02742       addrN = Make_Leaf(block, addr, Pointer_type);
02743 
02744       *hipart = WN_Iload(type,
02745        offset,
02746        coerceTY(WN_ty(tree), type),
02747        Load_Leaf(addrN));
02748 
02749       *lopart = WN_Iload(type,
02750        coerceOFFSET(tree, type, offset),
02751        coerceTY(WN_ty(tree), type),
02752        Load_Leaf(addrN));
02753 
02754       lower_quad_maps(tree, *hipart, *lopart, actions);
02755     }
02756     break;
02757 
02758   case OPR_CONST:
02759     {
02760       TCON  val = Const_Val(tree);
02761 
02762       *hipart = Make_Const( Extract_Quad_Hi(val));
02763       *lopart = Make_Const( Extract_Quad_Lo(val));
02764 
02765     }
02766     break;
02767 
02768   case OPR_PAREN:
02769     {
02770      /*
02771       * preserve the parens
02772       */
02773       lower_quad_expr(block, WN_kid0(tree), actions, hipart, lopart);
02774 
02775       *hipart = WN_Paren(type, *hipart);
02776       *lopart = WN_Paren(type, *lopart);
02777     }
02778     break;
02779 
02780   case OPR_PARM:
02781     lower_quad_expr(block, WN_kid0(tree), actions, hipart, lopart);
02782     break;
02783 
02784   case OPR_ILOADX:
02785     Is_True( FALSE, ("unexpected QUAD ILOADX"));
02786     break;
02787 
02788   default:
02789     Is_True((FALSE),
02790       ("lower_quad_expr didn't %s", OPCODE_name(WN_opcode(tree))));
02791   }
02792 }
02793 
02794 
02795 
02796 
02797 static WN *WN_Coerce(TYPE_ID dst, WN *expr)
02798 {
02799   TYPE_ID src= WN_rtype(expr);
02800 
02801   if (MTYPE_size_min(dst) == MTYPE_size_min(src))
02802     return expr;
02803 #ifdef KEY // avoid ambiguity
02804   if (src == MTYPE_I4 && dst == MTYPE_U8)
02805     dst = MTYPE_I8;
02806   if (src == MTYPE_U4 && dst == MTYPE_I8)
02807     src = MTYPE_I4;
02808 #endif
02809   return WN_Cvt(src, dst, expr);
02810 }
02811 
02812 
02813 
02814 
02815 /* ====================================================================
02816  *
02817  * WN *lower_linearize_array_addr(WN *block, WN *tree, LOWER_ACTIONS actions)
02818  *
02819  * Perform lowering (see WN_Lower description) on ARRAY expr <tree>,
02820  * returning linearized address expression tree.  <actions> must
02821  * contain LOWER_ARRAY.
02822  *
02823  *  We are assuming that the index and array_dim information are unique
02824  *
02825  * Note: If the element size is < 0, it means that we have a non-contiguous F90
02826  *       array. These are linearized slightly differently. Instead of
02827  *       the extent children being extents, they are stride multiplier factors. 
02828  *       The sum of the products of the index and stride multiplier is scaled
02829  *       by -element_size to get the offset from the base.  
02830  * ==================================================================== */
02831 
02832 static WN *lower_linearize_array_addr(WN *block, WN *tree,
02833               LOWER_ACTIONS actions)
02834 {
02835   TYPE_ID rtype = WN_rtype(tree);
02836   WN    *result, *product;
02837   INT32         i;
02838   BOOL          is_non_contig=FALSE;
02839   WN_ESIZE      element_size;
02840 
02841   Is_True((WN_operator_is(tree,OPR_ARRAY)),
02842     ("expected ARRAY node, not %s", OPCODE_name(WN_opcode(tree))));
02843   Is_True(Action(LOWER_ARRAY), ("actions doesn't contain LOWER_ARRAY"));
02844   Is_True(WN_num_dim(tree) > 0, ("WN_num_dim of ARRAY node not > 0"));
02845 
02846   const INT32 n = WN_num_dim(tree);
02847   element_size = WN_element_size(tree);
02848   if (element_size < 0) {
02849      is_non_contig = TRUE;
02850      element_size = -element_size;
02851   }
02852   if (element_size == 0) {
02853     // This is an array of empty struct
02854     element_size = 1;
02855   }
02856   
02857 #ifdef TARG_X8664
02858   BOOL do_reassociate = FALSE;
02859 #endif
02860 
02861   if (is_non_contig)
02862   {
02863      WN *stride_mult;
02864      
02865      result = WN_Coerce(rtype, WN_array_index(tree, n-1));
02866      stride_mult = WN_Coerce(rtype, WN_array_dim(tree, n-1));
02867      result = WN_Mpy(rtype,result,stride_mult);
02868 
02869      for (i = n-2; i >= 0; i--) {
02870   product = WN_Coerce(rtype, WN_array_index(tree, i));
02871   stride_mult = WN_Coerce(rtype, WN_array_dim(tree, i));
02872   product = WN_Mpy(rtype,product,stride_mult);
02873   result = WN_Add(rtype,result,product);
02874      }
02875   }
02876   else
02877   {
02878 #ifdef TARG_X8664
02879     result = NULL;
02880     do_reassociate = FALSE;
02881 
02882     if( n > 1 && loop_info_stack[current_loop_nest_depth] != NULL ){
02883       WN* idv = WN_array_index( tree, n-1 );
02884       while( idv != NULL ){
02885   if( WN_has_sym(idv) )
02886     break;
02887   if( WN_kid_count(idv) == 0 ){
02888     idv = NULL;
02889     break;
02890   }
02891   idv = WN_kid0( idv );
02892       }
02893 
02894       if( idv != NULL ){
02895   do_reassociate = 
02896     WN_st_idx( idv ) == WN_st_idx( loop_info_stack[current_loop_nest_depth] );
02897   // for stride cases ...
02898   do_reassociate |= ( WN_class(idv) == CLASS_PREG );
02899 
02900   // You can turn me off if you don't like me :(
02901   //do_reassociate = FALSE;
02902       }
02903     }
02904 
02905     if( !do_reassociate ){
02906       result = WN_Coerce(rtype, WN_array_index(tree, n-1));
02907     }
02908 #else
02909    /*
02910     *  result <- index[n-1]
02911     */
02912     result = WN_Coerce(rtype, WN_array_index(tree, n-1));
02913 #endif
02914      
02915    /*
02916     *  result <- result + index[i] * ( dim[n-1] * dim[n-2] ... dim[i+1] )
02917     */
02918     for (i = n-2; i >= 0; i--)
02919     {
02920       INT32 m;
02921       WN  *mpy;
02922        
02923       product = WN_Coerce(rtype, lower_copy_tree(WN_array_dim(tree, n-1),
02924              actions));
02925       for (m=n-2; m>i; m--)
02926       {
02927   product = WN_Mpy(rtype,
02928        product,
02929        WN_Coerce(rtype, lower_copy_tree(WN_array_dim(tree, m),
02930                 actions)));
02931       }
02932 
02933       mpy = WN_Mpy(rtype,
02934        WN_Coerce(rtype, WN_array_index(tree,i)),
02935        product);
02936 #ifdef TARG_X8664
02937       if( result == NULL ){
02938   result = mpy;
02939   continue;
02940       }
02941 #endif
02942       result = WN_Add(rtype, result, mpy);
02943     }
02944   }  
02945   
02946 
02947   /*
02948    *  result <- base + result * elm_size
02949    */
02950   {
02951     WN  *elm_size;
02952 
02953     elm_size = WN_Intconst(rtype, element_size);
02954     result = WN_Add(rtype,
02955         WN_array_base(tree),
02956         WN_Mpy(rtype, result, elm_size));
02957 #ifdef TARG_X8664
02958     if( do_reassociate ){
02959       /*
02960        *  result <- result +  index[n-1] * elm_size
02961        */
02962       WN* elm_size1 = WN_Intconst(rtype, element_size);
02963       WN* inv_wn = WN_Coerce(rtype, WN_array_index( tree, n-1 ));    
02964       result = WN_Add(rtype,
02965           result,
02966           WN_Mpy(rtype, inv_wn, elm_size1) );
02967     }
02968 #endif
02969   }
02970 
02971   result = lower_expr(block, result, actions);
02972 
02973   WN_Delete(tree);      /* ARRAY node not used */
02974 
02975   return result;
02976 }
02977 
02978 
02979 
02980 
02981 /* ====================================================================
02982  *
02983  * WN *lower_unsigned_to_float(WN *block, WN *tree, LOWER_ACTIONS actions)
02984  *
02985  * Perform lowering (see WN_Lower description) on conversions <tree>,
02986  * returning lowered expression tree.
02987  *
02988  * ==================================================================== */
02989 
02990 static WN *lower_unsigned_to_float(WN *block, WN *expr, TYPE_ID src,
02991            TYPE_ID dst, LOWER_ACTIONS actions)
02992 {
02993   LEAF  srcNo, dstNo;
02994 
02995 
02996   /* Special case of U4. Don't do this special case if the cvt.d.l 
02997    * instruction is slow. This is true on the R5000 which emulates
02998    * this in software due to a chip bug.
02999    */
03000   if (src == MTYPE_U4 && !Slow_CVTDL)
03001   {
03002      BOOL  simp=  WN_Simplifier_Enable(FALSE);
03003      WN * r;
03004 
03005      r = WN_Cvt(MTYPE_I8,dst,WN_Cvt(MTYPE_U4, MTYPE_U8, expr));
03006 
03007      WN_Simplifier_Enable(simp);
03008      return (r);
03009   }
03010 
03011 
03012   /*
03013    *  store the expr into a preg to avoid building a dag
03014    *  src = expr;
03015    */
03016   srcNo = Make_Leaf(block, expr, src);
03017 
03018   /*
03019    *  dst = (signed cvt) src ;
03020    */
03021   {
03022     WN  *ldid, *cvt;
03023 
03024     ldid = Load_Leaf(srcNo);
03025 
03026     cvt  = WN_Cvt(MTYPE_complement(src), dst, ldid);
03027 
03028     dstNo = Make_Leaf(block, cvt, dst);
03029   }
03030 
03031   /*
03032    *  build the select tree that looks like
03033    *  (src < 0) ? dst + 2**N : dst
03034    *   where N is the src size
03035    */
03036   {
03037     WN  *rel, *add, *select;
03038 
03039     rel = WN_LT(MTYPE_complement(src),
03040     Load_Leaf(srcNo),
03041     WN_Zerocon(MTYPE_complement(src)));
03042 
03043     add = WN_Add(dst,
03044      Load_Leaf(dstNo),
03045      WN_ConstPowerOf2( dst, MTYPE_size_reg(src)));
03046 
03047     select = WN_Select(dst, rel, add, Load_Leaf(dstNo));
03048     return select;
03049   }
03050 }
03051 
03052 
03053 
03054 
03055 /* ====================================================================
03056  *
03057  * WN *lower_float_to_unsigned(WN *block, WN *tree, LOWER_ACTIONS actions)
03058  *
03059  * Perform lowering (see WN_Lower description) on conversions <tree>,
03060  * returning lowered expression tree.
03061  *
03062  * ==================================================================== */
03063 
03064 static WN *lower_float_to_unsigned(WN *block, WN *expr, TYPE_ID src,
03065            TYPE_ID dst, LOWER_ACTIONS actions)
03066 {
03067   LEAF srcNo;
03068   WN *trunc1,*r;
03069   WN *rel, *sub, *trunc2,*add;
03070 
03071 
03072   /* Two cases, dest type = U8, and dest type = U4 */
03073   if (dst == MTYPE_U4) {
03074      r = WN_Cvt(MTYPE_I8,dst,WN_Trunc(src,MTYPE_I8,expr));
03075   } else if (src==MTYPE_FQ) {  /* Need to do this this way because there
03076         * is no quad floor */
03077      
03078      /*
03079       *  store the expr into a preg to avoid building a dag
03080       * src = expr;
03081       */
03082      srcNo = Make_Leaf(block, expr, src);
03083      
03084      /*
03085       *  build the select tree that looks like
03086       *
03087       * (2**(N-1) <= src) ? : 2**(N-1) + TRUNC(src-2**(N-1)) : TRUNC(src)
03088       *
03089       * where N is the unsigned dst size
03090       */
03091 
03092 
03093      trunc1 = WN_Trunc(src, MTYPE_complement(dst), Load_Leaf(srcNo));
03094      
03095      sub = WN_Sub(src, Load_Leaf(srcNo),
03096       WN_ConstPowerOf2(src, MTYPE_size_reg(dst)-1));
03097 
03098      trunc2 =  WN_Trunc(src, MTYPE_complement(dst),sub);
03099 
03100      add = WN_Add(dst,trunc2,WN_ConstPowerOf2(dst, MTYPE_size_reg(dst)-1));
03101      
03102      rel = WN_LE(src,
03103      WN_ConstPowerOf2(src, MTYPE_size_reg(dst)-1),
03104      Load_Leaf(srcNo));
03105      
03106      r = WN_Cselect(dst,rel,add,trunc1);
03107   } else {
03108      
03109      /*
03110       *  store the expr into a preg to avoid building a dag
03111       * src = expr;
03112       */
03113      srcNo = Make_Leaf(block, expr, src);
03114      
03115      /*
03116       *  build the select tree that looks like
03117       *
03118       * (2**(N-1) <= src) ? : FLOOR(src-2**(N)) : TRUNC(src)
03119       *
03120       * where N is the unsigned dst size
03121       */
03122 
03123 
03124      trunc1 = WN_Trunc(src, MTYPE_complement(dst), Load_Leaf(srcNo));
03125      
03126      sub = WN_Sub(src, Load_Leaf(srcNo),
03127       WN_ConstPowerOf2(src, MTYPE_size_reg(dst)));
03128 
03129      trunc2 =  WN_Floor(src, MTYPE_complement(dst),sub);
03130 
03131      rel = WN_LE(src,
03132      WN_ConstPowerOf2(src, MTYPE_size_reg(dst)-1),
03133      Load_Leaf(srcNo));
03134      
03135      r = WN_Cselect(dst,rel,trunc2,trunc1);
03136   }
03137   return (r);
03138 }
03139 
03140 
03141 
03142 
03143 /* ====================================================================
03144  *
03145  * WN *lower_cvt(WN *block, WN *tree, LOWER_ACTIONS actions)
03146  *
03147  * Perform lowering (see WN_Lower description) on conversions <tree>,
03148  * returning lowered expression tree.
03149  *
03150  * ==================================================================== */
03151 
03152 static WN *lower_cvt(WN *block, WN *tree, LOWER_ACTIONS actions)
03153 {
03154   WN  *expr, *cvt;
03155   TYPE_ID dst = WN_rtype(tree);
03156   TYPE_ID src = WN_desc(tree);
03157 
03158   expr = lower_expr(block, WN_kid0(tree), actions);
03159   WN_kid0(tree) = expr;
03160 
03161   if (   Targ_Lower_Unsigned_To_Float 
03162       && MTYPE_is_unsigned(src) && MTYPE_is_float(dst))
03163   {
03164     WN_Delete(tree);
03165 
03166     cvt = lower_unsigned_to_float(block, expr, src, dst, actions);
03167 
03168     return lower_expr(block, cvt, actions);
03169   }
03170   else if (   Targ_Lower_Float_To_Unsigned 
03171      && MTYPE_is_float(src) && MTYPE_is_unsigned(dst))
03172   {
03173     WN_Delete(tree);
03174 
03175     cvt = lower_float_to_unsigned(block, expr, src, dst, actions);
03176 
03177     return lower_expr(block, cvt, actions);
03178   }
03179   else if (   OPERATOR_is_compare(WN_operator(expr))
03180      && WN_rtype(expr) == MTYPE_B
03181      && (MTYPE_is_integral(dst) && src == MTYPE_B))
03182   {
03183 
03184     /* Optimize converts of MTYPE_B compares to integral values.
03185      */
03186     WN_Delete(tree);
03187 
03188     WN_set_rtype(expr, dst);
03189 
03190     return lower_expr(block, expr, actions);
03191   }
03192   
03193   return tree;
03194 }
03195 
03196 
03197 
03198 /* ====================================================================
03199  *
03200  * WN *lower_nary_madd(WN *block, WN *tree, LOWER_ACTIONS actions)
03201  *
03202  *  Create nary expression reassociate to produce MADDS
03203  *
03204  * ==================================================================== */
03205 
03206 static WN *lower_nary_madd(WN *block, WN *tree, LOWER_ACTIONS actions)
03207 {
03208 
03209   if (Enable_NaryExpr && Roundoff_Level >= ROUNDOFF_ASSOC)
03210   {
03211     TYPE_ID  type = WN_rtype(tree);
03212 
03213     tree = WN_ExprToNaryType(tree, type, 0);
03214 
03215     if (WN_nary_add(tree))
03216     {
03217       INT32 i;
03218       BOOL  found= TRUE;
03219 
03220      /*
03221       *  Find mpy then a non mpy under nary tree.
03222       *  The tree may change (ex. to a binary tree)
03223       */
03224       while(found)
03225       {
03226   INT32 mpyI, exprI, nmpyI, narympyI;
03227   WN  *mpy, *nmpy, *expr, *narympy;
03228         INT32 num_kids = WN_kid_count(tree);
03229 
03230   found=  FALSE;
03231   mpy  =  nmpy  = expr = narympy  = NULL;
03232   mpyI =  exprI = nmpyI = narympyI = 0;
03233 
03234   for(i = 0; i < num_kids; i++)
03235   {
03236     WN  *actual= WN_actual(tree, i);
03237 
03238     if (WN_operator_is(actual, OPR_MPY))
03239     {
03240       mpyI = i;
03241       mpy = actual;
03242     }
03243     else if (WN_operator_is(actual, OPR_NEG)  &&
03244        WN_operator_is(WN_kid0(actual), OPR_MPY))
03245     {
03246       nmpyI = i;
03247       nmpy = WN_kid0(actual);
03248     }
03249     else if (WN_nary_mpy(actual) && WN_kid_count(actual) >= 2)
03250     {
03251       narympyI = i;
03252       narympy = actual;
03253     }
03254     else 
03255     {
03256       exprI = i;
03257       expr = actual;
03258     }
03259 
03260     if (mpy && expr)
03261     {
03262       WN_actual(tree, mpyI)= WN_Madd(type, expr, WN_kid0(mpy),
03263              WN_kid1(mpy));
03264       tree = WN_NaryDelete(tree, exprI);
03265       found=  TRUE;
03266       break;
03267     }
03268     else if (nmpy && expr)
03269     {
03270       WN_actual(tree, nmpyI)= WN_Nmsub(type, expr, WN_kid0(nmpy),
03271                WN_kid1(nmpy));
03272       tree = WN_NaryDelete(tree, exprI);
03273       found=  TRUE;
03274       break;
03275     }
03276     else if (narympy && expr)
03277     {
03278       mpy=  WN_kid0(narympy);
03279       narympy=  WN_NaryDelete(narympy, 0);
03280 
03281       WN_actual(tree, narympyI)= WN_Madd(type, expr, mpy, narympy);
03282       tree = WN_NaryDelete(tree, exprI);
03283       found=  TRUE;
03284       break;
03285     }
03286   }
03287       }
03288      /*
03289       *  There may be madd opportunites at the children
03290       */
03291       for(i = 0; i < WN_kid_count(tree); i++)
03292       {
03293   WN_actual(tree, i)= lower_madd(block, WN_actual(tree,i), actions);
03294       }
03295 
03296     }
03297     
03298     if (WN_nary_intrinsic(tree))
03299     {
03300       tree = WN_NaryToExpr(tree);
03301     }
03302   }
03303 
03304   return tree;
03305 }
03306 
03307 
03308 
03309 
03310 /* ====================================================================
03311  *
03312  * WN *lower_madd(WN *block, WN *tree, LOWER_ACTIONS actions)
03313  *
03314  * Perform lowering (see WN_Lower description) on expression <tree>,
03315  * returning lowered expression tree.
03316  *
03317  * ==================================================================== */
03318 
03319 static WN *lower_madd(WN *block, WN *tree, LOWER_ACTIONS actions)
03320 {
03321   TYPE_ID  type = WN_rtype(tree);
03322 
03323  /*
03324   *  look for madd patterns
03325   */
03326   switch (WN_operator(tree))
03327   {
03328   case OPR_NEG:
03329     {
03330       WN  *child = WN_kid0(tree);
03331 
03332       switch(WN_operator(child))
03333       {
03334       case OPR_MADD:
03335   WN_Delete(tree);
03336   return WN_Nmadd(type, WN_kid0(child), WN_kid1(child), WN_kid2(child));
03337 
03338       case OPR_MSUB:
03339   WN_Delete(tree);
03340   return WN_Nmsub(type, WN_kid0(child), WN_kid1(child), WN_kid2(child));
03341 
03342       case OPR_NMADD:
03343   WN_Delete(tree);
03344   return WN_Madd(type, WN_kid0(child), WN_kid1(child), WN_kid2(child));
03345 
03346       case OPR_NMSUB:
03347   WN_Delete(tree);
03348   return WN_Msub(type, WN_kid0(child), WN_kid1(child), WN_kid2(child));
03349       }
03350     }
03351     break;
03352 
03353   case OPR_ADD:
03354     {
03355       WN  *l= WN_kid0(tree);
03356       WN  *r= WN_kid1(tree);
03357 
03358       if (WN_operator_is(l, OPR_MPY))
03359       {
03360   WN_Delete(tree);
03361   return WN_Madd(type, r, WN_kid0(l), WN_kid1(l));
03362       }
03363       else if (WN_operator_is(r, OPR_MPY))
03364       {
03365   WN_Delete(tree);
03366   return WN_Madd(type, l, WN_kid0(r), WN_kid1(r));
03367       }
03368     }
03369     break;
03370 
03371   case OPR_SUB:
03372     {
03373       WN  *l= WN_kid0(tree);
03374       WN  *r= WN_kid1(tree);
03375 
03376       if (WN_operator_is(l, OPR_MPY))
03377       {
03378   WN_Delete(tree);
03379   return WN_Msub(type, r, WN_kid0(l), WN_kid1(l));
03380       }
03381       else if (WN_operator_is(r, OPR_MPY))
03382       {
03383   WN_Delete(tree);
03384   return WN_Nmsub(type, l, WN_kid0(r), WN_kid1(r));
03385       }
03386     }
03387     break;
03388 
03389   case OPR_MADD:
03390     {
03391       WN  *neg= WN_kid0(tree);
03392 
03393       if (WN_operator_is(neg, OPR_NEG))
03394       {
03395   WN  *child= WN_kid0(neg);
03396 
03397   WN_Delete(neg);
03398   return WN_Msub(type, child, WN_kid1(tree), WN_kid2(tree));
03399       }
03400     }
03401     break;
03402 
03403   case OPR_MSUB:
03404     {
03405       WN  *neg= WN_kid0(tree);
03406 
03407       if (WN_operator_is(neg, OPR_NEG))
03408       {
03409   WN  *child= WN_kid0(neg);
03410 
03411   WN_Delete(neg);
03412   return WN_Madd(type, child, WN_kid1(tree), WN_kid2(tree));
03413       }
03414     }
03415     break;
03416 
03417   case OPR_NMADD:
03418     {
03419       WN  *neg= WN_kid0(tree);
03420 
03421       if (WN_operator_is(neg, OPR_NEG))
03422       {
03423   WN  *child= WN_kid0(neg);
03424 
03425   WN_Delete(neg);
03426   return WN_Nmsub(type, child, WN_kid1(tree), WN_kid2(tree));
03427       }
03428     }
03429     break;
03430 
03431   case OPR_NMSUB:
03432     {
03433       WN  *neg= WN_kid0(tree);
03434 
03435       if (WN_operator_is(neg, OPR_NEG))
03436       {
03437   WN  *child= WN_kid0(neg);
03438 
03439   WN_Delete(neg);
03440   return WN_Nmadd(type, child, WN_kid1(tree), WN_kid2(tree));
03441       }
03442     }
03443     break;
03444   }
03445 
03446   return tree;
03447 }
03448 
03449 
03450 
03451 
03452 /* ====================================================================
03453  *
03454  * WN *lower_tree_height(WN *block, WN *wn, LOWER_ACTIONS actions)
03455  *
03456  *  Reassociate binary commutative operator at this level 
03457  *  (ie no recursion)
03458  *
03459  * ==================================================================== */
03460 
03461 static WN *lower_tree_height(WN *block, WN *wn, LOWER_ACTIONS actions)
03462 {
03463   OPCODE  opcode = WN_opcode(wn);
03464   WN    *l, *r;
03465 
03466   if (NotAction(LOWER_TREEHEIGHT))
03467     return wn;
03468 
03469   Is_True(WN_is_commutative(wn),("expected commutative op"));
03470 
03471   l = WN_kid0(wn);
03472   r = WN_kid1(wn);
03473 
03474  /*
03475   *  do not transform an already balanced tree
03476   */
03477   if (opcode == WN_opcode(l) ^ opcode == WN_opcode(r))
03478 
03479   {
03480     WN *wn1 =  (opcode == WN_opcode(l)) ? l : r;
03481     WN *wn1X = (opcode == WN_opcode(l)) ? r : l;
03482 
03483     WN *wn1_l = WN_kid0(wn1);
03484     WN *wn1_r = WN_kid1(wn1);
03485 
03486     if (opcode == WN_opcode(wn1_l) ^ opcode == WN_opcode(wn1_r))
03487     {
03488 
03489       WN *wn2 =  (opcode == WN_opcode(wn1_l)) ? wn1_l : wn1_r;
03490       WN *wn2X = (opcode == WN_opcode(wn1_l)) ? wn1_r : wn1_l;
03491      /*
03492       *  rearrange tree
03493       */
03494       WN_kid0(wn1) =  wn2X;
03495       WN_kid1(wn1) =  wn1X;
03496 
03497       WN_kid0(wn) = wn2;
03498       WN_kid1(wn) = wn1;
03499 
03500       if (traceTreeHeight)
03501       {
03502   DevWarn("lower_tree_height: trace (%s) has been reassociated (line %d)",
03503           OPCODE_name(WN_opcode(wn)), Srcpos_To_Line(current_srcpos));
03504       }
03505     }
03506   }
03507   return wn;
03508 }
03509 
03510 
03511 #ifdef KEY
03512 /* ====================================================================
03513  *
03514  * WN *sum_madd_segments(WN **segments, INT low, INT high)
03515  *
03516  *  Sum the MADD chains.
03517  *
03518  * ==================================================================== */
03519 static WN *sum_madd_segments(WN **segments, INT low, INT high)
03520 {
03521   WN *tree;
03522 
03523   if (high == low) {
03524     tree = segments[high];
03525   } else if (high - low == 1) {
03526     WN *opnd0 = segments[low];
03527     WN *opnd1 = segments[high];
03528     tree = WN_Add(WN_rtype(opnd0), opnd0, opnd1);
03529   } else {
03530     INT mid = (high + low) / 2;
03531     WN *sum0 = sum_madd_segments(segments, low, mid);
03532     WN *sum1 = sum_madd_segments(segments, mid + 1, high);
03533     tree = WN_Add(WN_rtype(sum0), sum0, sum1);
03534   }
03535   return tree;
03536 }
03537 
03538 
03539 /* ====================================================================
03540  *
03541  * WN *lower_one_madd_tree_height(WN *block, WN *wn)
03542  *
03543  *  Reassociate MADD operator at this level 
03544  *  (ie no recursion)
03545  *
03546  * ==================================================================== */
03547 
03548 static WN *lower_one_madd_tree_height(WN *block, WN *wn)
03549 {
03550   // Tree is a MADD and potentially starts a MADD chain.
03551   Is_True(WN_operator(wn) == OPR_MADD,
03552     ("lower_one_madd_tree_height: MADD operator not found"));
03553 
03554   if (OPT_Madd_Height <= 0)
03555     return wn;
03556 
03557   // Count the MADDs in the chain.
03558   INT madd_count = 0;
03559   WN *this_wn;
03560   for (this_wn = wn;
03561        WN_operator(this_wn) == OPR_MADD;
03562        this_wn = WN_kid0(this_wn)) {
03563     madd_count++;
03564   }
03565 
03566   if (madd_count <= OPT_Madd_Height)
03567     return wn;
03568 
03569   INT segment_count = madd_count / OPT_Madd_Height + 1;
03570   WN **segments = (WN **) alloca(segment_count * sizeof(WN *));
03571   memset(segments, 0, segment_count * sizeof(WN *));
03572 
03573   // Split up the MADD chain.
03574   INT count = 0;
03575   INT idx = 0;
03576   WN *prev_wn = NULL;
03577   this_wn = wn;
03578   while (WN_operator(this_wn) == OPR_MADD) {
03579     WN *next_wn = WN_kid0(this_wn);
03580     count++;
03581     if (count > OPT_Madd_Height) {
03582       WN *mpy = WN_Mpy(WN_rtype(this_wn), WN_kid1(this_wn), WN_kid2(this_wn));
03583       WN_kid0(prev_wn) = mpy;
03584       WN_Delete(this_wn);
03585       count = 0;
03586     } else if (count == 1) {
03587       segments[idx++] = this_wn;
03588     }
03589     prev_wn = this_wn;
03590     this_wn = next_wn;
03591   }
03592 
03593   // If the last MADD in the chain was converted to a MPY, then its kid0 still
03594   // needs to be summed.
03595   if (count == 0) {
03596     segments[idx++] = this_wn;
03597   }
03598 
03599   // Add the partial sums.
03600   WN *tree = sum_madd_segments(segments, 0, idx - 1);
03601   return tree;
03602 }
03603 
03604 
03605 /* ====================================================================
03606  *
03607  * WN *lower_madd_tree_height(WN *block, WN *tree)
03608  *
03609  *  Traverse tree to find subtrees that are MADD chains.  Lower the height
03610  *  of these chains.
03611  *
03612  * ==================================================================== */
03613 
03614 static void lower_madd_tree_height(WN *block, WN *tree, LOWER_ACTIONS actions)
03615 {
03616   if (NotAction(LOWER_TREEHEIGHT))
03617     return;
03618 
03619   if (WN_operator(tree) != OPR_MADD) {
03620     INT16 i;
03621     for (i = 0; i < WN_kid_count(tree); i++) {
03622       WN *kid = WN_kid(tree, i);
03623       if (WN_operator(kid) == OPR_MADD) {
03624   // Kid potentially begins a MADD chain.  Reduce its height.
03625   WN_kid(tree, i) = lower_one_madd_tree_height(block, kid);
03626       } else {
03627   lower_madd_tree_height(block, kid, actions);
03628       }
03629     }
03630   }
03631 }
03632 #endif
03633 
03634 
03635 /* ====================================================================
03636  *
03637  * WN *lower_recip(WN *block, WN *tree, LOWER_ACTIONS actions)
03638  *
03639  * WN *lower_rsqrt(WN *block, WN *tree, LOWER_ACTIONS actions)
03640  *
03641  * lower recip/rsqrt based on ISA flags
03642  *
03643  * Quad is lowered unconditionally, as there is no runtime support
03644  * (kludge alert: turn off simplifer when creating quad divide !!)
03645  *
03646  * ==================================================================== */
03647 
03648 static WN *lower_recip(WN *block, WN *tree, LOWER_ACTIONS actions)
03649 {
03650   TYPE_ID  type = WN_rtype(tree);
03651   WN    *kid0 = WN_kid0(tree);
03652   WN    *div =  NULL;
03653 
03654   Is_True(WN_operator_is(tree, OPR_RECIP), ("expected recip"));
03655   Is_True(MTYPE_float(type), ("expected float type"));
03656 
03657 
03658 #ifndef KEY
03659   if (Recip_Allowed == FALSE)
03660 #else
03661   if (Recip_Allowed == FALSE && Div_Split_Allowed == FALSE)
03662 #endif
03663   {
03664     div = WN_Div(type, WN_Floatconst(type, 1.0), kid0);
03665   }
03666   else if (Action(LOWER_QUAD) && MTYPE_is_quad(type))
03667   {
03668     BOOL  simp= WN_Simplifier_Enable(FALSE);
03669 
03670     div = WN_Div(type, WN_Floatconst(type, 1.0), kid0);
03671 
03672     WN_Simplifier_Enable(simp);
03673   }
03674 
03675   if (div)
03676   {
03677     WN_Delete(tree);
03678     return div;
03679   }
03680 
03681   return tree;
03682 }
03683 
03684 
03685 static WN *lower_rsqrt(WN *block, WN *tree, LOWER_ACTIONS actions)
03686 {
03687   TYPE_ID  type = WN_rtype(tree);
03688 
03689   Is_True(WN_operator_is(tree, OPR_RSQRT), ("expected rsqrt"));
03690   Is_True(MTYPE_float(WN_rtype(tree)), ("expected float type"));
03691 
03692 #ifdef TARG_X8664 // bug 6123
03693   if (Rsqrt_Allowed == 0 ||
03694       // x86-64 rsqrt supports single-precision only.
03695       !(type == MTYPE_F4 || type == MTYPE_V16F4) ||
03696       !Is_Target_SSE2())
03697 #else
03698   if (Rsqrt_Allowed == FALSE || MTYPE_is_quad(type))
03699 #endif
03700   {
03701     WN  *div;
03702 
03703     div = WN_Div(type, WN_Floatconst(type, 1.0), WN_Sqrt(type, WN_kid0(tree)));
03704     WN_Delete(tree);
03705 
03706     return div;
03707   }
03708 
03709 #ifdef TARG_X8664
03710   if (Rsqrt_Allowed == 1) {
03711     /* Rsqrt followed by one iteration of Newton-Raphson to refine the result:
03712    a = rsqrt(x)      ;; get approximate rsqrt(x)
03713    b = x * a
03714    c = b * a         ;; c has error E
03715    d = c - 3.0
03716    e = d * a
03717    f = e * (-0.5)
03718        f now has 1/sqrt(x).  Bug 6123.
03719 
03720        Change the operator from RSQRT to ATOMIC_RSQRT to prevent infinite
03721        recursion.
03722      */
03723     WN_set_operator(tree, OPR_ATOMIC_RSQRT);
03724     LEAF x = Make_Leaf(block, WN_kid0(tree), type);
03725     WN_kid0(tree) = Load_Leaf(x);
03726     PREG_NUM a = AssignExpr(block, tree, type);
03727     WN *b = WN_Mpy(type, Load_Leaf(x), WN_LdidPreg(type, a));
03728     WN *c = WN_Mpy(type, b, WN_LdidPreg(type, a));
03729     WN *d = WN_Sub(type, c, WN_Floatconst(type, 3.0));
03730     WN *e = WN_Mpy(type, d, WN_LdidPreg(type, a));
03731     WN *f = WN_Mpy(type, e, WN_Floatconst(type, -0.5));
03732     return f;
03733   }
03734 #endif
03735 
03736   return tree;
03737 }
03738 
03739 
03740 /* IPA can mark variables gp-relative, even if they are not allocated
03741  * in this source file. To deal with them, we explicitly check if a 
03742  * variable is gp-relative.
03743  */
03744 static BOOL Symbol_Is_Base_Register (ST *sym)
03745 {
03746   return ((ST_class(sym) == CLASS_BLOCK && STB_is_basereg(sym)) ||
03747           (ST_class(sym) == CLASS_VAR && ST_gprel(sym)));
03748 }
03749 
03750 
03751 
03752 /* ====================================================================
03753  *
03754  * WN *lower_split_sym_addrs(WN *tree, INT64 offset, LOWER_ACTIONS actions)
03755  *
03756  * Split symbols into base/offset depending on type/class etc.
03757  *
03758  *
03759  * ==================================================================== */
03760 
03761 static WN *lower_split_sym_addrs(WN *tree, INT64 offset, LOWER_ACTIONS actions)
03762 {
03763   ST *sym  = WN_st(tree);
03764   ST *base = ST_base(sym);
03765   INT64 newoffset = 0;
03766 
03767 #ifdef TARG_NVISA
03768   // want to preserve original symbol
03769   return NULL;
03770 #endif
03771 
03772   if (traceSplitSymOff)
03773     return NULL;
03774 
03775   switch(ST_class(sym))
03776   {
03777   case CLASS_CONST:
03778    /*
03779     *  for non_shared, non-gprelative constants we want to expose the
03780     *  base for RVI
03781     */
03782     if (PIC_NONSHARED && (ST_size(sym) > Max_Sdata_Elt_Size))
03783     {
03784       Allocate_Object(sym);
03785       Base_Symbol_And_Offset_For_Addressing(sym, offset, &base, &newoffset);
03786       return lower_base_reference(tree, base, newoffset, actions);
03787     }
03788     return NULL;
03789 
03790   case CLASS_PREG:
03791     return NULL;
03792 
03793   case CLASS_FUNC:
03794     if (PIC_SHARED && ST_is_preemptible(sym))
03795     {
03796       return NULL;
03797     }
03798     break;
03799 
03800   case CLASS_BLOCK:
03801   case CLASS_VAR:
03802     Base_Symbol_And_Offset_For_Addressing(sym, offset, &base, &newoffset);
03803 
03804     if (ST_is_uplevelTemp(sym))
03805     {
03806       return NULL;
03807     }
03808     if (ST_assigned_to_dedicated_preg(sym)) 
03809     {
03810   return NULL;
03811     }
03812 
03813    /*
03814     *  We cannot keep lowering LDA's or we will forever recurse
03815     */
03816     if (WN_operator_is(tree, OPR_LDA) && base == sym) 
03817       return NULL;
03818 
03819     switch(ST_sclass(sym))
03820     {
03821     case SCLASS_REG:
03822     case SCLASS_TEXT:
03823       return NULL;
03824 
03825     case SCLASS_FORMAL_REF: 
03826      /*
03827       *  If we expand the base, we will lose the FORMAL_REF'ness of the ST
03828       *  and will not be able to dereference it later
03829       */
03830       if (base != sym)
03831       {
03832   base =  sym;
03833       }
03834       break;
03835 
03836     case SCLASS_FORMAL:
03837      /*
03838       *  Do not allocate Formal_Arg_StkSeg, as it is not correct yet !!
03839       *  (it will eventually be .sp + <offset> )
03840       */
03841       return NULL;
03842 
03843     case SCLASS_AUTO:
03844       /* 
03845        * For now, never split a stack variable.
03846        * We only see stack variables with bases when we do regions,
03847        * and for now we want to keep those cases looking like the
03848        * regular cases for correctness.  But at a later date we should
03849        * try to split these in the region case, as that may allow a
03850        * base register to be allocated for things like FP+32000,
03851        * so we could then get 1-instruction accesses to large offsets.
03852        * But that requires a cgexp change too, so wait on it.
03853        */
03854 #if 0
03855       if (Uses_Small_Offset(sym, offset))
03856         break;
03857 #endif
03858       return NULL;
03859 
03860     case SCLASS_EXTERN:
03861      /*
03862       * okay to split these. A dlopen() can never redefine these (unless
03863       * they are weak)
03864       */
03865       if (ST_is_weak_symbol(sym))
03866   return NULL;
03867       break;
03868 
03869     case SCLASS_COMMON:
03870      /*
03871       * commons may be preempted by a dlopen() (if the new definition is
03872       * initialized) see wilson/lillian for details of this rather obscure
03873       * point suneel says not to worry about this though, so please direct
03874       * bugs to him
03875       *
03876       * In the new symbol table, we need to also split common symbols
03877       * here. The reason is that now both members and the common itself
03878       * are SCLASS_COMMON, whereas before they used to be SCLASS_BASED.
03879       * We no longer have to worry about the ST_Full that was present in
03880       * the old symbol table
03881       */
03882       sym = base;
03883       break;
03884 
03885     case SCLASS_PSTATIC:
03886     case SCLASS_UGLOBAL:
03887     case SCLASS_DGLOBAL:
03888     case SCLASS_FSTATIC:
03889      /*
03890       *  okay to split these. We will never split incorrectly as
03891       *  Base_Symbol_And_Offset_For_Addressing() will not split a preemptible
03892       *  symbol
03893       */
03894       break;
03895 
03896     default:
03897       return NULL;
03898     }
03899 
03900 #ifdef TARG_SL2 
03901     if(ST_gprel(sym) || WN_is_internal_mem_ofst(tree))
03902 #else 
03903     if (ST_gprel(sym))
03904 #endif    
03905     {
03906       return NULL;
03907     }
03908     tree = lower_base_reference(tree, base, newoffset, actions);
03909     return tree;
03910 
03911   default:
03912     return NULL;
03913   }
03914 
03915   return NULL;
03916 }
03917 
03918 
03919 
03920 
03921 /* ====================================================================
03922  *
03923  * WN *lower_uplevel_reference(WN *tree, INT64 offset, LOWER_ACTIONS actions)
03924  *
03925  * Split uplevel symbols into indirect of slink
03926  *
03927  * ==================================================================== */
03928 
03929 static WN *lower_uplevel_reference(WN *tree, INT64 offset,
03930            LOWER_ACTIONS actions)
03931 {
03932   ST  *sym = WN_st(tree);
03933   ST  *base;
03934   INT64 newoffset;
03935 
03936   Is_True(ST_is_uplevelTemp(sym), ("expected uplevel %s",ST_name(sym)));
03937 
03938   Base_Symbol_And_Offset_For_Addressing(sym, offset, &base, &newoffset);
03939   base = Find_Slink_For_ST(sym);
03940 
03941   tree = lower_dereference(tree, newoffset, base, 0, actions);
03942   return tree;
03943 }
03944 
03945 
03946 
03947 
03948 /* ====================================================================
03949  *
03950  * WN *lower_formal_ref(WN *tree, INT64 offset, ST *base,
03951  *                      LOWER_ACTIONS actions)
03952  *
03953  * lower an SCLASS_FORMAL_REF into a dereference of the new base.
03954  * or
03955  * lower an SCLASS_FORMAL into a preg, already computed
03956  *
03957  * ==================================================================== */
03958 static WN *lower_formal_ref(WN *tree, INT64 offset, ST *base,
03959           LOWER_ACTIONS actions)
03960 {
03961   PREG_NUM  preg;
03962 
03963   switch(ST_sclass(base))
03964   {
03965   case SCLASS_FORMAL_REF:
03966     base = Get_ST_formal_ref_base(base);
03967     if (preg = Get_ST_formal_preg_num(base))
03968     {
03969       Is_True((ST_has_nested_ref(WN_st(tree))==FALSE),
03970         ("lower_formal_ref: cannot use preg for nested ref %s",
03971          ST_name(WN_st(tree))));
03972       base = MTYPE_To_PREG(TY_mtype(Ty_Table[ST_type(base)]));
03973     }
03974     return lower_dereference(tree, offset, base, preg, actions);
03975 
03976   case SCLASS_FORMAL:
03977     if (preg= Get_ST_formal_preg_num(base))
03978     {
03979       base = MTYPE_To_PREG(TY_mtype(Ty_Table[ST_type(base)]));
03980       tree = lower_base_register(tree, base, preg, actions);
03981       return tree;
03982     }
03983     break;
03984   }
03985   return NULL;
03986 }
03987 
03988 
03989 
03990 
03991 /* ====================================================================
03992  *
03993  * WN *lower_base_register(WN *tree, ST *base, INT64 offset,
03994  *                         LOWER_ACTIONS actions)
03995  *
03996  * common routine for lowering to a base register for LDA, LDID, STID
03997  * into using a new base/offset
03998  *
03999  * ==================================================================== */
04000 
04001 static WN *lower_base_register(WN *tree, ST *base, INT64 offset,
04002              LOWER_ACTIONS actions)
04003 {
04004   Is_True(WN_st(tree) != base, ("lower_base_register(): possible recursion"));
04005 
04006   switch (WN_operator(tree))
04007   {
04008   case OPR_LDA:
04009    /*
04010     * Convert
04011     *     LDA (offset) <sym> into
04012     *
04013     *     LDA (offset) <base>
04014     */
04015     WN_st_idx(tree) = ST_st_idx(base);
04016     WN_lda_offset(tree) = mem_offset_hi(offset);
04017     return tree;
04018 
04019   case OPR_LDID:
04020    /*
04021     * Convert
04022     *   LDID (offset> <sym>  into
04023     *     LDID (offset <base>
04024     */
04025     WN_st_idx(tree) = ST_st_idx(base);
04026     WN_load_offset(tree) = offset;
04027     break;
04028 
04029   case OPR_STID:
04030    /*
04031     * Convert
04032     *   STID (offset> <sym>  into
04033     *     STID (offset <base>
04034     */
04035     WN_st_idx(tree) = ST_st_idx(base);
04036     WN_store_offset(tree) = offset;
04037     break;
04038 
04039   default:
04040     Is_True(FALSE,("expected lda/ldid/stid"));
04041     return NULL;
04042   }
04043 
04044   return tree;
04045 }
04046 
04047 
04048 // replace the type of LDID/STID nodes with non-zero field_id to the type
04049 // of the field
04050 static void
04051 lower_field_id (WN* tree)
04052 {
04053   OPERATOR opr = WN_operator(tree);
04054 
04055   Is_True (opr == OPR_LDID || opr == OPR_STID || opr == OPR_MLOAD ||
04056      opr == OPR_MSTORE, ("expecting LDID or STID nodes"));
04057 
04058   if (WN_field_id (tree) == 0)
04059     return;
04060 
04061   BOOL is_ptr_type = (opr == OPR_MLOAD || opr == OPR_MSTORE);
04062 
04063   TY_IDX ty_idx = is_ptr_type ? TY_pointed (WN_ty (tree)) : WN_ty (tree);
04064 
04065   Is_True (TY_kind (ty_idx) == KIND_STRUCT,
04066      ("non-zero field id must have KIND_STRUCT"));
04067 
04068   UINT field_id = 0;
04069   FLD_HANDLE fld = FLD_get_to_field (ty_idx, WN_field_id (tree), field_id); 
04070   
04071   Is_True (! fld.Is_Null (), ("invalid bit-field ID for %s",
04072             OPERATOR_name(opr)));
04073 
04074   WN_set_ty (tree, (is_ptr_type ? Make_Pointer_Type (FLD_type (fld)) :
04075         FLD_type (fld)));
04076   WN_set_field_id (tree, 0);
04077   return;
04078 } // lower_field_id
04079 
04080 
04081 /* ====================================================================
04082  *
04083  * WN *lower_base_reference(WN *tree, ST *base, INT64 offset,
04084  *                          LOWER_ACTIONS actions)
04085  *
04086  * common routine for lowering to a base reference for LDA, LDID, STID
04087  *
04088  * ==================================================================== */
04089 
04090 static WN *lower_base_reference(WN *tree, ST *base, INT64 offset,
04091         LOWER_ACTIONS actions)
04092 {
04093   WN    *addr, *wn;
04094 
04095   switch (WN_operator(tree))
04096   {
04097   case OPR_LDA:
04098    /*
04099     * Convert
04100     *     LDA (offset) <sym>
04101     * 
04102     * (lo > 0)
04103     *       LDA (hi) <base>
04104     *       CONST (lo)
04105     *     ADD
04106     *
04107     * (offset >= 2GB)
04108     *       LDA (0) <base>
04109     *       CONST (offset)
04110     *     ADD
04111     */
04112 
04113     WN_st_idx(tree) = ST_st_idx(base);
04114 
04115     if (mem_offset_2GB(offset))
04116     {
04117       addr =  WN_Add(Pointer_type, tree, WN_Intconst(Pointer_type, offset));
04118       WN_lda_offset(tree)=  0;
04119       return addr;
04120     }
04121     else if (Action(LOWER_SPLIT_CONST_OFFSETS)  &&
04122        mem_offset_lo(offset))
04123     {
04124      /* turn off simplifier else ADD may be removed */
04125       BOOL  simp=        WN_Simplifier_Enable(FALSE);
04126 
04127       addr =  WN_Add(Pointer_type,
04128            tree,
04129            WN_Intconst(Pointer_type, mem_offset_lo(offset)));
04130       WN_lda_offset(tree)=  mem_offset_hi(offset);
04131 
04132       WN_Simplifier_Enable(simp);
04133       return addr;
04134     }
04135     WN_lda_offset(tree)=  offset;
04136     return tree;
04137 
04138   case OPR_LDID:
04139   case OPR_STID:
04140   case OPR_LDBITS:
04141   case OPR_STBITS:
04142    /*
04143     * Process the common address
04144     *
04145     * if (offset > 2GB)
04146     *      LDA (hi) <sym>
04147     *    CONST offset
04148     *    ADD
04149     *
04150     * if (offset > 16K)
04151     *      LDA (hi) <sym>
04152     *    ILOAD | ISTORE (lo)
04153     */
04154     addr =  WN_Lda(Pointer_type, 0, base);
04155 
04156     if (mem_offset_2GB(offset))
04157     {
04158       addr =  WN_Add(Pointer_type, addr, WN_Intconst(Pointer_type, offset));
04159       offset =  0;
04160     }
04161     if (Action(LOWER_SPLIT_CONST_OFFSETS) && mem_offset_must_be_split(offset))
04162     {
04163       WN_lda_offset(addr) = mem_offset_hi(offset);
04164       offset =      mem_offset_lo(offset);
04165     }
04166     break;
04167 
04168   default:
04169     Is_True(FALSE,("expected lda/ldid/stid"));
04170     return NULL;
04171   } 
04172 
04173   switch (WN_operator(tree))
04174   {
04175   case OPR_LDID:
04176    /*
04177     * Convert (LDID () <sym>) into
04178     *      LDA (0) <base>
04179     *    ILOAD (offset+ofst)
04180     */
04181     if (WN_field_id (tree) != 0)
04182       lower_field_id (tree);
04183     
04184     wn =  WN_RIload(WN_rtype(tree), WN_desc(tree), offset, WN_ty(tree),
04185         addr);
04186     break;
04187   case OPR_LDBITS:
04188     wn =  WN_RIload(WN_rtype(tree), WN_desc(tree), offset, WN_ty(tree),
04189         addr);
04190     WN_set_operator(wn, OPR_ILDBITS);
04191     WN_set_bit_offset_size(wn, WN_bit_offset(tree), WN_bit_size(tree));
04192     break;
04193 
04194   case OPR_STID:
04195    /*
04196     * Convert   STID (offset) <sym>
04197     *  into
04198     *       LDA (0) <base>
04199     *     ISTORE (offs+ofst)
04200     */
04201     if (WN_field_id (tree) != 0)
04202       lower_field_id (tree);
04203     
04204     wn =  WN_Istore(WN_desc(tree),
04205         offset,
04206         // The resulting TY is not an f90 pointer
04207         // type because we're converting an STID.
04208         // In the case where this STID
04209         // came about because of conversion of
04210         // ISTORE(something) in the past, and that
04211         // ISTORE was through an f90 pointer, the
04212         // destination of the STID will have the
04213         // F90_TARGET attribute, and we're OK.
04214         Make_Pointer_Type(WN_ty(tree)),
04215         addr,
04216         WN_kid0(tree));
04217     WN_Set_Linenum(wn, WN_Get_Linenum(tree));
04218     break;
04219   case OPR_STBITS:
04220     wn =  WN_Istore(WN_desc(tree),
04221         offset,
04222         Make_Pointer_Type(WN_ty(tree)),
04223         addr,
04224         WN_kid0(tree));
04225     WN_set_operator(wn, OPR_ISTBITS);
04226     WN_set_bit_offset_size(wn, WN_bit_offset(tree), WN_bit_size(tree));
04227     WN_Set_Linenum(wn, WN_Get_Linenum(tree));
04228     break;
04229   } 
04230 
04231   lower_copy_maps(tree, wn, actions);
04232   WN_Delete(tree);
04233 
04234   return wn;
04235 }
04236 
04237 
04238 
04239 /* ====================================================================
04240  *
04241  * WN *lower_dereference(WN *tree, INT64 offset, ST *base,
04242  *                       PREG_NUM *preg, LOWER_ACTIONS actions)
04243  *
04244  * Perform address dereferencing for SCLASS_FORMAL_REF and uplevel variable
04245  * Caller is responsible for any further lowering.
04246  *
04247  *  For uplevel references the idea is to replace the st with a reference
04248  *  of the slink_sym at level ST_level(st) + 1
04249  *  This will only work recursively
04250  *  (ie. that sym must be referenced via the next level's scope
04251  *
04252  * ==================================================================== */
04253 static WN
04254 *lower_dereference(WN *tree, INT64 offset, ST *base, PREG_NUM preg,
04255        LOWER_ACTIONS actions)
04256 {
04257   WN   *addr, *deref;
04258   TY_IDX  addr_ty;
04259 
04260   switch (WN_operator(tree))
04261   {
04262   case OPR_LDA:
04263    /*
04264     * Convert uplevel reference
04265     *     LDA (offset) <sym>
04266     *  into 
04267     *       LDID (0) <base>
04268     *       CONST (offset)    
04269     *     ADD
04270     */
04271     deref = WN_Ldid(Pointer_type, preg, base, WN_ty(tree));
04272     addr =  WN_Add(Pointer_type, deref, WN_Intconst(Pointer_type, offset));
04273     return addr;
04274 
04275   case OPR_LDID:
04276   case OPR_STID:
04277    /*
04278     * Process the common address
04279     *
04280     */
04281     addr_ty = Make_Pointer_Type(WN_ty(tree));
04282     addr =  WN_Ldid(Pointer_type, preg, base, addr_ty);
04283 
04284     if (mem_offset_2GB(offset))
04285     {
04286       addr =  WN_Add(Pointer_type, addr, WN_Intconst(Pointer_type, offset));
04287       offset =  0;
04288     }
04289     break;
04290 
04291   default:
04292     Is_True(FALSE,("expected lda/ldid/stid"));
04293     return NULL;
04294   } 
04295 
04296   switch (WN_operator(tree))
04297   {
04298   case OPR_LDID:
04299    /*
04300     * Convert uplevel reference  LDID () <sym>
04301     * into
04302     *      LDID (preg) <base>
04303     *    ILOAD (offset)
04304     */
04305     deref = WN_RIload(WN_rtype(tree), WN_desc(tree), offset, WN_ty(tree), addr,
04306               WN_field_id(tree));
04307     break;
04308 
04309   case OPR_STID:
04310    /*
04311     * Convert  STID () <sym>
04312     * into
04313     *       LDID (preg) <base> 
04314     *     ISTORE (offset)          
04315     */
04316     deref = WN_Istore(WN_desc(tree), offset, addr_ty, addr, WN_kid0(tree)
04317 #ifdef KEY // bug 14036
04318                       ,WN_field_id(tree)
04319 #endif
04320                      );
04321     WN_Set_Linenum(deref, WN_Get_Linenum(tree));
04322     break;
04323   } 
04324 
04325   lower_copy_maps(tree, deref, actions);
04326   WN_Delete(tree);
04327 
04328   return deref;
04329 }
04330 
04331 /* ====================================================================
04332  *
04333  * WN *lower_return_ldid(WN *block, WN *tree, LOWER_ACTIONS actions)
04334  *
04335  * Perform lowering (see WN_Lower description) on 'LDID Return_Val_Preg'
04336  * nodes returning a lowered 'LDID normal_PREG' node.
04337  *
04338  * ==================================================================== */
04339 
04340 static WN *lower_return_ldid(WN *block, WN *tree, LOWER_ACTIONS actions)
04341 {
04342   TY_IDX   ty_idx  = WN_ty(tree);
04343   TY&      ty      = Ty_Table[ty_idx];
04344   TYPE_ID  mtype   = TY_mtype (ty);
04345 #ifdef TARG_X8664
04346   BOOL sseregparm  = FALSE; // sseregparm attribute on called function?
04347 #endif
04348 
04349   Is_True((WN_operator(tree) == OPR_LDID),
04350     ("expected LDID node, not %s", OPCODE_name(WN_opcode(tree))));
04351 
04352 #ifdef TARG_X8664
04353   if (Is_Target_32bit())
04354   {
04355     // Determine if the called function has the "sseregparm" attribute
04356     WN * call = WN_last(block);
04357     if (call && WN_operator(call) == OPR_CALL)
04358     {
04359       TY_IDX pu_ty = PU_prototype(Pu_Table[ST_pu(WN_st(call))]);
04360       sseregparm = TY_has_sseregister_parm (pu_ty);
04361     }
04362   }
04363 #endif
04364 
04365   switch (mtype) {
04366 
04367     case MTYPE_I8:
04368     case MTYPE_U8:
04369 #if defined(TARG_X8664)
04370       WN_st_idx(tree) = ST_st_idx(MTYPE_To_PREG(mtype));
04371 #else
04372       WN_st_idx(tree) = ST_st_idx(Int64_Preg);
04373 #endif
04374       WN_load_offset(tree) = First_Int_Preg_Return_Offset;
04375 #ifdef TARG_NVISA
04376       // int64 are separate register class, so use unique preg num
04377       WN_load_offset(tree) = First_Int64_Preg_Return_Offset;
04378 #endif
04379       return tree;
04380 
04381     case MTYPE_I1:
04382     case MTYPE_I2:
04383     case MTYPE_I4:
04384     case MTYPE_U1:
04385     case MTYPE_U2:
04386     case MTYPE_U4:
04387 #ifdef TARG_NVISA
04388       WN_st_idx(tree) = ST_st_idx(Int32_Preg);
04389 #else
04390       WN_st_idx(tree) = ST_st_idx(Int_Preg);
04391 #endif
04392       WN_load_offset(tree) = First_Int_Preg_Return_Offset;
04393       return tree;
04394 
04395     case MTYPE_F4:
04396     case MTYPE_F8:
04397     case MTYPE_F10:
04398     case MTYPE_FQ:
04399     case MTYPE_C4:
04400     case MTYPE_C8:
04401     case MTYPE_C10:
04402     case MTYPE_CQ:
04403 #if defined(TARG_SL) && defined(EMULATE_FLOAT_POINT)
04404 #if defined(TRACE_LOWER) 
04405       fprintf(TFile, "wn_lower.cxx: lower_return_ldid %d at line %d\n", mtype, __LINE__);
04406 #endif
04407       WN_st_idx(tree) = (mtype == MTYPE_F8) ? ST_st_idx(Int64_Preg) : ST_st_idx(Int32_Preg);
04408       WN_load_offset(tree) = First_Int_Preg_Return_Offset; 
04409 #elif defined(TARG_NVISA)
04410       if (mtype == MTYPE_F8) {
04411   // doubles are separate register class, so use unique preg num
04412         WN_st_idx(tree) = ST_st_idx(Float64_Preg);
04413         WN_load_offset(tree) = First_Float64_Preg_Return_Offset;
04414       } else {
04415         WN_st_idx(tree) = ST_st_idx(Float32_Preg);
04416         WN_load_offset(tree) = First_Float_Preg_Return_Offset;
04417       }
04418 #else
04419       WN_st_idx(tree) = ST_st_idx(Float_Preg);
04420       WN_load_offset(tree) = First_Float_Preg_Return_Offset;
04421 #endif
04422 #ifdef TARG_X8664 // MTYPE_C4 is returned in one SSE register
04423       if (Is_Target_64bit() && mtype == MTYPE_C4) {
04424   WN_set_rtype(tree, MTYPE_F8);
04425   WN_set_desc(tree, MTYPE_F8);
04426   WN_set_ty(tree, MTYPE_To_TY(MTYPE_F8));
04427       }
04428 
04429       if( Is_Target_32bit() && ! sseregparm && ! MTYPE_is_complex(mtype) ||
04430             MTYPE_is_quad(mtype) ){
04431   WN_st_idx(tree) = ST_st_idx( MTYPE_To_PREG(mtype) );
04432   WN_load_offset(tree) = First_X87_Preg_Return_Offset;
04433       }
04434 #endif
04435       return tree;
04436 
04437 #if defined(TARG_X8664) || defined(VECTOR_MTYPES)
04438     case MTYPE_V16I1:
04439     case MTYPE_V16I2:
04440     case MTYPE_V16I4:
04441     case MTYPE_V16I8:
04442     case MTYPE_V16F4:
04443     case MTYPE_V16F8:
04444     case MTYPE_V8I1:
04445     case MTYPE_V8I2:
04446     case MTYPE_V8I4:
04447 #ifdef TARG_X8664
04448     case MTYPE_M8I1:
04449     case MTYPE_M8I2:
04450     case MTYPE_M8I4:
04451     case MTYPE_M8F4:
04452 #endif
04453       WN_st_idx(tree) = ST_st_idx(MTYPE_To_PREG (mtype));
04454       WN_load_offset(tree) = First_Float_Preg_Return_Offset;
04455       return tree;
04456 #endif // TARG_X8664 || VECTOR_MTYPES
04457 
04458     case MTYPE_M:
04459       Fail_FmtAssertion ("MLDID of Return_Val_Preg not allowed in middle"
04460        " of expression");
04461       /*NOTREACHED*/
04462     default:
04463       Fail_FmtAssertion ("Unexpected type in lower_return_ldid");
04464       /*NOTREACHED*/
04465   }
04466 }
04467 
04468 static TY_IDX
04469 get_field_type (TY_IDX struct_type, UINT field_id)
04470 {
04471   Is_True (TY_kind (struct_type) == KIND_STRUCT, ("expecting KIND_STRUCT"));
04472   UINT cur_field_id = 0;
04473   FLD_HANDLE fld = FLD_get_to_field (struct_type, field_id, cur_field_id);
04474   Is_True (! fld.Is_Null(), ("Invalid field id %d for type 0x%x",
04475            field_id, struct_type));
04476   return FLD_type (fld);
04477 }
04478 
04479 /* ====================================================================
04480  *
04481  * WN *lower_mldid(WN *block, WN *tree, LOWER_ACTIONS actions)
04482  *
04483  * Perform lowering (see WN_Lower description) on MLDID nodes returning
04484  * an equivalent MLOAD node.  Note that MLDID's of Return_Val_Preg are
04485  * not lowered here.  They are handled by lower_return_ldid.
04486  *
04487  * ==================================================================== */
04488 
04489 static WN *lower_mldid(WN *block, WN *tree, LOWER_ACTIONS actions)
04490 {
04491   TY_IDX ty_idx  = WN_ty(tree);
04492   TY_IDX pty_idx;
04493   UINT64 size    = WN_field_id(tree) == 0 ?
04494       TY_size(ty_idx) :
04495       TY_size(get_field_type (ty_idx, WN_field_id (tree)));
04496   WN*    wn;
04497   WN*    awn;
04498   WN*    swn;
04499 
04500   Is_True((WN_opcode(tree) == OPC_MMLDID),
04501     ("expected mldid node, not %s", OPCODE_name(WN_opcode(tree))));
04502 
04503   pty_idx = Make_Pointer_Type (ty_idx, FALSE);
04504 
04505   swn = WN_CreateIntconst(OPC_U4INTCONST, size);
04506   awn = WN_CreateLda(OPR_LDA, Pointer_Mtype, MTYPE_V, WN_load_offset(tree),
04507          pty_idx, WN_st(tree));
04508   wn  = WN_CreateMload(0, pty_idx, awn, swn);
04509   WN_set_field_id(wn, WN_field_id(tree));
04510   wn  = lower_expr(block, wn, actions);
04511 
04512   WN_Delete(tree);
04513   return wn;
04514 }
04515 
04516 /* ====================================================================
04517  *
04518  * WN *lower_miload(WN *block, WN *tree, LOWER_ACTIONS actions)
04519  *
04520  * Perform lowering (see WN_Lower description) on MILOAD nodes returning
04521  * an equivalent MLOAD node.
04522  *
04523  * ==================================================================== */
04524 
04525 static WN *lower_miload(WN *block, WN *tree, LOWER_ACTIONS actions)
04526 {
04527   TY_IDX ty_idx  = WN_field_id (tree) == 0 ?
04528     WN_ty(tree) :
04529     get_field_type (WN_ty (tree), WN_field_id (tree));
04530   TY_IDX pty_idx = WN_load_addr_ty(tree);
04531   UINT64 size    = TY_size(Ty_Table[ty_idx]);
04532   WN*    wn;
04533   WN*    swn;
04534 
04535   Is_True((WN_opcode(tree) == OPC_MMILOAD),
04536     ("expected miload node, not %s", OPCODE_name(WN_opcode(tree))));
04537 
04538   swn = WN_CreateIntconst (OPC_U4INTCONST, size);
04539   wn  = WN_CreateMload (WN_offset(tree), pty_idx, WN_kid0(tree), swn);
04540   WN_set_field_id(wn, WN_field_id(tree));
04541   set_original_wn (wn, tree);
04542   wn  = lower_expr (block, wn, actions);
04543 
04544   WN_Delete (tree);
04545   return wn;
04546 }
04547 
04548 /* ====================================================================
04549  *
04550  * lower_load_bits
04551  *
04552  * lower LDBITS and ILDBITS into shifts
04553  *
04554  * ==================================================================== */
04555 static WN*
04556 lower_load_bits (WN* block, WN* wn, LOWER_ACTIONS actions)
04557 {
04558   Is_True (WN_operator (wn) == OPR_LDBITS || WN_operator (wn) == OPR_ILDBITS,
04559      ("expected LDBITS or ILDBITS, not %s",
04560       OPERATOR_name(WN_operator(wn))));
04561 
04562   TYPE_ID rtype = WN_rtype (wn);
04563   TYPE_ID desc = WN_desc (wn);
04564   INT delta = MTYPE_bit_size(rtype) - MTYPE_bit_size(desc);
04565   if (delta < 0) {
04566     rtype = Mtype_TransferSize (desc, rtype);
04567     delta = 0;
04568   }
04569 
04570   WN* tree = wn;
04571 
04572   INT bit_size = WN_bit_size (wn);
04573   INT bit_ofst = Target_Byte_Sex == BIG_ENDIAN ?
04574     WN_bit_offset (wn) :
04575     MTYPE_bit_size(desc) - bit_size - WN_bit_offset (wn);
04576   BOOL bits_signed = MTYPE_signed(rtype);
04577   
04578   if (bit_ofst == 0)
04579     bit_size += delta;
04580   else {
04581     bit_ofst += delta;
04582     if (bits_signed)
04583       tree = WN_Shl (rtype, tree, WN_Intconst (MTYPE_I4, bit_ofst));
04584     else {
04585       INT shift_count = 64 - (MTYPE_bit_size(rtype) - bit_ofst);
04586       mUINT64 mask = (~(mUINT64)0) >> shift_count;
04587       tree = WN_Band (rtype, tree,
04588           WN_Intconst (Mtype_TransferSign (MTYPE_U4, rtype),
04589            mask));
04590       bit_size += bit_ofst;
04591     }
04592   }
04593 
04594   INT right_shift = MTYPE_bit_size(rtype) - bit_size;
04595 
04596   if (right_shift > 0) {
04597     OPERATOR opr = bits_signed ? OPR_ASHR : OPR_LSHR;
04598     tree = WN_Binary (opr, rtype, tree, WN_Intconst (MTYPE_I4, right_shift));
04599   }
04600 
04601   TYPE_ID orig_rtype = WN_rtype (wn);
04602   
04603   WN_set_rtype (wn, rtype);
04604   WN_set_bit_offset_size (wn, 0, 0);
04605   WN_set_operator (wn, WN_operator (wn) == OPR_LDBITS ? OPR_LDID : OPR_ILOAD);
04606 
04607   if (rtype != orig_rtype)
04608     tree = WN_Type_Conversion (tree, orig_rtype);
04609 
04610   return lower_expr (block, tree, actions);
04611 } // lower_load_bits
04612 
04613 
04614 /* ====================================================================
04615  *
04616  * lower_store_bits
04617  *
04618  * lower STBITS and ISTBITS
04619  *
04620  * ==================================================================== */
04621 static WN*
04622 lower_store_bits (WN* block, WN* wn, LOWER_ACTIONS actions)
04623 {
04624   Is_True (WN_operator (wn) == OPR_STBITS || WN_operator (wn) == OPR_ISTBITS,
04625      ("expected STBITS or ISTBITS, not %s",
04626       OPERATOR_name (WN_operator (wn))));
04627 
04628   INT bit_size = WN_bit_size (wn);
04629   INT bit_ofst = WN_bit_offset (wn); 
04630 
04631   WN* orig_value;
04632 
04633   if (WN_operator (wn) == OPR_ISTBITS) {
04634     WN* load_address = lower_copy_tree (WN_kid1 (wn), actions);
04635     orig_value = WN_Iload (Mtype_TransferSign (MTYPE_U4, WN_desc (wn)),
04636          WN_offset (wn), WN_ty (wn), load_address, 0);
04637   } else 
04638     orig_value = WN_Ldid (Mtype_TransferSign (MTYPE_U4, WN_desc (wn)),
04639         WN_offset (wn), WN_st_idx (wn), WN_ty (wn), 0);
04640   
04641   TYPE_ID cmp_type = WN_rtype (orig_value);
04642   
04643   INT shift = Target_Byte_Sex == BIG_ENDIAN ?
04644       MTYPE_bit_size (WN_desc (wn)) - bit_ofst - bit_size :
04645       bit_ofst;
04646   mUINT64 mask = ~((~((mUINT64)0) >> (64 - bit_size)) << shift);
04647   orig_value = WN_Band (cmp_type, orig_value, WN_Intconst (cmp_type, mask));
04648 
04649   WN* new_value = WN_kid0 (wn);
04650 
04651   // check if we need to sign-extend the value
04652   if (bit_size > MTYPE_bit_size (WN_rtype (new_value)))
04653     new_value =
04654       WN_CreateCvtl (OPR_CVTL,
04655          Mtype_TransferSign (WN_rtype (new_value), cmp_type),
04656          WN_rtype (new_value),
04657          MTYPE_bit_size (WN_rtype (new_value)),
04658          new_value);
04659   
04660   // now, truncate to the right bit size for store
04661   mask = ~((mUINT64)0) >> (64 - bit_size);
04662   new_value =
04663     WN_Band (cmp_type, new_value,
04664        WN_Intconst (Mtype_TransferSize (WN_rtype (new_value), cmp_type),
04665         mask));
04666 
04667   // move the bits to the right position
04668   if (shift > 0)
04669     new_value = WN_Shl (cmp_type, new_value, WN_Intconst (cmp_type, shift));
04670 
04671   // set the value with bitwise or
04672   new_value = WN_Bior (cmp_type, orig_value, new_value);
04673 
04674   WN_kid0 (wn) = new_value;
04675   WN_set_bit_offset_size (wn, 0, 0);
04676   WN_set_operator (wn, WN_operator(wn) == OPR_STBITS ? OPR_STID : OPR_ISTORE);
04677 
04678   return lower_store (block, wn, actions);
04679 } // lower_store_bits
04680 
04681 #if 0
04682 /* ====================================================================
04683  *
04684  * check_unaligned
04685  *
04686  * required_alignment is the natural alignment; offset is the actual offset
04687  * used in the current access; ty_align is the alignment in the TY of the
04688  * current access.  Return whether the access is unaligned.
04689  *
04690  * ==================================================================== */
04691 static bool check_unaligned(INT required_alignment, INT offset, INT ty_align)
04692 {
04693   if (required_alignment <= 1)
04694     return FALSE;
04695   INT align = ty_align;
04696   if (offset) {
04697     INT offset_align = offset % required_alignment;
04698     if (offset_align)
04699       align = MIN(align, offset_align);
04700   }
04701   return align < required_alignment;
04702 }
04703 #endif
04704 
04705 
04706 // --------------------------------------------------------------------
04707 // This function mimics FLD_get_to_field from common/com/symtab.cxx,
04708 // but it also computes the offset of <field_id> within <struct_ty_idx>
04709 // We need this because FLD_ofst only gives the offset within the first
04710 // enclosing struct.
04711 // --------------------------------------------------------------------
04712 FLD_HANDLE
04713 FLD_And_Offset_From_Field_Id (TY_IDX  struct_ty_idx, 
04714                               UINT    field_id, 
04715                               UINT&   cur_field_id,
04716                               UINT64& offset)
04717 {
04718   FLD_ITER fld_iter = Make_fld_iter(TY_fld(struct_ty_idx));
04719   do {
04720     FLD_HANDLE fld(fld_iter);
04721     cur_field_id++;
04722     if (cur_field_id == field_id) {
04723       offset += FLD_ofst(fld);
04724       return fld;
04725     }
04726     if (TY_kind(FLD_type(fld)) == KIND_STRUCT &&
04727         TY_fld(FLD_type(fld)) != FLD_HANDLE()) {
04728       UINT64 nested_offset = offset + FLD_ofst(fld);
04729       fld = FLD_And_Offset_From_Field_Id(FLD_type(fld), field_id, 
04730                                          cur_field_id, nested_offset);
04731       if (cur_field_id == field_id) {
04732         offset = nested_offset;
04733         return fld;
04734       }
04735     }
04736   } while (!FLD_last_field(fld_iter++));
04737   
04738   return FLD_HANDLE();
04739 } 
04740 
04741 /* ====================================================================
04742  *
04743  * lower_bit_field_id
04744  *
04745  * The given LDID/STID/ILOAD/ISTORE node has desc type MTYPE_BS.  Lower
04746  * the node by changing the field_id to bit_offset/bit_size combination.
04747  * The desc field is changed to reflect the unit in memory to load, and
04748  * the offset field may need to be updated.
04749  *
04750  * ==================================================================== */
04751 static void lower_bit_field_id(WN *wn)
04752 {
04753   TY_IDX struct_ty_idx;
04754   TY_IDX ty_idx;
04755   TYPE_ID rtype;
04756   OPERATOR opr = WN_operator(wn);
04757   OPERATOR new_opr;
04758   BOOL indirect;
04759   if (opr == OPR_LDID || opr == OPR_STID) {
04760     ST_IDX st_idx = WN_st_idx(wn);
04761     struct_ty_idx = WN_ty(wn);
04762     new_opr = (opr == OPR_LDID) ? OPR_LDBITS : OPR_STBITS;
04763     indirect = FALSE;
04764   }
04765   else {
04766     if (WN_operator(wn) == OPR_ILOAD) {
04767       ty_idx = WN_load_addr_ty(wn);
04768       new_opr = OPR_ILDBITS;
04769     }
04770     else {  // ISTORE
04771       ty_idx = WN_ty(wn);
04772       new_opr = OPR_ISTBITS;
04773     }
04774     Is_True(TY_kind(ty_idx) == KIND_POINTER,
04775       ("addr ty not pointer type for %s", OPERATOR_name(opr)));
04776     struct_ty_idx = TY_pointed(ty_idx);
04777     indirect = TRUE;
04778   }
04779   Is_True(TY_kind(struct_ty_idx) == KIND_STRUCT,
04780     ("struct type not associated with bit-field access for %s", OPERATOR_name(opr)));
04781   UINT cur_field_id = 0;
04782   UINT64 field_offset = 0;
04783   FLD_HANDLE fld = FLD_And_Offset_From_Field_Id(struct_ty_idx, 
04784                                                 WN_field_id(wn),
04785                                                 cur_field_id,
04786                                                 field_offset); 
04787   Is_True(! fld.Is_Null(),
04788     ("invalid bit-field ID for %s", OPERATOR_name(opr)));
04789   TY_IDX fld_ty_idx = FLD_type(fld);
04790   
04791   Is_True(FLD_is_bit_field(fld),
04792     ("non-bit-field associated with bit-field access for  %s", OPERATOR_name(opr)));
04793 
04794   // analyze bit field accessed
04795   UINT bytes_accessed = TY_size(fld_ty_idx);
04796   if (OPERATOR_is_store(new_opr))
04797     rtype = TY_mtype(fld_ty_idx);
04798   else rtype = WN_rtype(wn);
04799   INT ofst = field_offset;
04800 #if 0
04801   BOOL unaligned_field = check_unaligned(bytes_accessed * 8, ofst,
04802            TY_align(struct_ty_idx));
04803 #endif
04804   if (ofst >= 0)
04805     ofst = ofst / bytes_accessed * bytes_accessed;
04806   else ofst =  (ofst - bytes_accessed + 1) / bytes_accessed * bytes_accessed;
04807   UINT bsize = FLD_bsize(fld);
04808   UINT bofst = FLD_bofst(fld) + (field_offset-ofst) * 8;
04809   if ((bofst + bsize) > (bytes_accessed * 8)) {
04810 #ifdef TARG_X8664
04811     if (bytes_accessed == MTYPE_byte_size(MTYPE_I8)){ 
04812 #else
04813     if (bytes_accessed == MTYPE_byte_size(Max_Int_Mtype)){ 
04814 #endif // TARG_X8664
04815       // can't enlarge; reverse the adjustment
04816       ofst = field_offset;
04817       bofst = FLD_bofst(fld);
04818     }
04819     else bytes_accessed *= 2;
04820   }
04821   WN_load_offset(wn) = WN_load_offset(wn) + ofst; 
04822 
04823   TYPE_ID mtype;
04824   if ((bsize & 7) == 0 &&        // field size multiple of bytes
04825 #ifdef KEY // bug 11076
04826       bsize &&           // field size non-zero
04827 #endif
04828       (bytes_accessed * 8 % bsize) == 0 && // bytes_accessed multiple of bsize
04829 #ifdef TARG_X8664
04830       (bofst & 7) == 0
04831 #else
04832       (bofst % bsize) == 0       // bofst multiple of bsize
04833 #endif // TARG_X8664
04834       ) {
04835     // bit-field operation not needed; leave operator as previous one
04836     WN_set_field_id(wn, 0);
04837     mtype = Mtype_AlignmentClass(bsize >> 3, MTYPE_type_class(rtype));
04838     WN_set_desc(wn, mtype);
04839     WN_load_offset(wn) = WN_load_offset(wn) + (bofst >> 3);
04840   }
04841   else { // generate lowered-to bit-field operator
04842 #if defined(TARG_MIPS) || defined(TARG_IA32)
04843     if ((indirect || WN_class(wn) != CLASS_PREG) && 
04844   bofst % 8 == 0 &&   // bit offset on byte boundary
04845   compute_offset_alignment(bytes_accessed*8, bofst) >= bsize) {
04846       // adjust bytes accessed to get rid of the left-shift
04847       WN_load_offset(wn) = WN_load_offset(wn) + (bofst >> 3);
04848       bytes_accessed = compute_offset_alignment(bytes_accessed, bofst >> 3);
04849       bofst = 0;
04850     }
04851 #endif
04852     WN_set_operator(wn, new_opr);
04853 
04854 #ifdef KEY
04855     mtype = Mtype_AlignmentClass(bytes_accessed, MTYPE_type_class(rtype));
04856     Is_True( mtype != MTYPE_UNKNOWN, ("Unknown mtype encountered.") );
04857     WN_set_desc(wn, mtype);
04858 #else
04859     WN_set_desc(wn, Mtype_AlignmentClass(bytes_accessed, MTYPE_type_class(rtype)));
04860 #endif // KEY
04861 
04862     if (OPERATOR_is_load(new_opr) && 
04863   MTYPE_byte_size(WN_rtype(wn)) < bytes_accessed)
04864       WN_set_rtype(wn, WN_desc(wn));
04865     WN_set_bit_offset_size(wn, bofst, bsize);
04866   }
04867 
04868   // fix the TYs
04869   if (MTYPE_byte_size(mtype) > MTYPE_byte_size(TY_mtype(fld_ty_idx)))
04870     fld_ty_idx = MTYPE_To_TY(mtype);
04871   WN_set_ty (wn, (opr == OPR_ISTORE ?
04872       Make_Pointer_Type (fld_ty_idx, FALSE) :
04873       fld_ty_idx));
04874 #ifdef KEY // bug 12394
04875   if (new_opr == OPR_ILDBITS)
04876     WN_set_load_addr_ty(wn, Make_Pointer_Type(fld_ty_idx));
04877 #endif
04878 }
04879 
04880 static void lower_trapuv_alloca (WN *block, WN *tree, LOWER_ACTIONS actions
04881 #ifdef KEY
04882          , ST_IDX sym_idx, INT64 offset, TY_IDX pty_idx
04883          )
04884 #endif
04885 {
04886   WN *size = WN_kid0(tree);
04887   WN *con;
04888 #ifdef KEY
04889   TY_IDX ty_idx;
04890   if (TY_kind(pty_idx) == KIND_POINTER)
04891     ty_idx = TY_pointed(pty_idx);
04892   else if (TY_kind(pty_idx) == KIND_SCALAR &&
04893      TY_size(pty_idx) == Pointer_Size) {
04894     // No info on the pointed-to type.  Take a wild guess and make it U4.
04895     // Bug 8282.
04896     ty_idx = MTYPE_To_TY(MTYPE_U4);
04897   } else {
04898     ty_idx = 0;
04899     Is_True(FALSE, ("lower_trapuv_alloca: pointer type not found"));
04900   }
04901   TYPE_ID type = TY_mtype(ty_idx);
04902   if (DEBUG_Zero_Uv)      // Initialize vars to 0.
04903     con = WN_Intconst(MTYPE_byte_size(type)==4 ? MTYPE_U4 : MTYPE_U8, 0);
04904   else if (MTYPE_byte_size(type) == 4)  // Get 32/64-bit NaN from type.
04905     con = WN_UVConst(MTYPE_U4);
04906   else if (MTYPE_byte_size(type) == 8)
04907     con = WN_UVConst(MTYPE_U8);
04908   else
04909 #endif
04910   con = WN_UVConst(WN_rtype(size));
04911 
04912   WN *mstore;
04913   if (WN_operator(size) == OPR_INTCONST && WN_const_val(size) == 0)
04914     return; // nothing to do
04915 
04916 #ifdef KEY
04917   ST *sym = &St_Table[sym_idx];
04918   mstore = WN_CreateMstore(0,
04919     pty_idx,    // bug 6007
04920     con,
04921     WN_Ldid(Pointer_type, offset, sym, ST_type(sym)),
04922     WN_COPY_Tree(size) );
04923 #else
04924   mstore = WN_CreateMstore(0,
04925     Make_Pointer_Type(MTYPE_To_TY(WN_rtype(size)),TRUE),
04926     con,
04927     WN_LdidPreg(Pointer_type, Stack_Pointer_Preg_Offset),
04928     WN_COPY_Tree(size) );
04929 #endif
04930     mstore = lower_store (block, mstore, actions);
04931   WN_Set_Linenum(mstore, current_srcpos);  // Bug 1268
04932   WN_INSERT_BlockLast(block, mstore);
04933 }
04934 
04935 
04936 inline BOOL Should_Call_Divide(TYPE_ID rtype)
04937 {
04938 #ifdef TARG_X8664
04939   if( Is_Target_32bit() &&
04940       ( rtype == MTYPE_I8 || rtype == MTYPE_U8 ) ){
04941     return TRUE;
04942   }
04943 #endif // TARG_X8664
04944 
04945 #if defined(TARG_IA64)
04946   if (!OPT_Inline_Divide) {
04947     if (   rtype == MTYPE_I8 || rtype == MTYPE_U8
04948   || rtype == MTYPE_I4 || rtype == MTYPE_U4
04949   || rtype == MTYPE_F4 || rtype == MTYPE_F8) return TRUE;
04950   }
04951 #elif defined(EMULATE_LONGLONG)
04952   if (rtype == MTYPE_I8 || rtype == MTYPE_U8) return TRUE;
04953 #endif
04954 #ifdef TARG_SL //expand operator to function call
04955   return TRUE;
04956 #endif 
04957   return FALSE;
04958 }
04959 
04960 static BOOL Is_Fast_Divide(WN *wn)
04961 {
04962   OPERATOR opr = WN_operator(wn);
04963   switch (opr) {
04964   case OPR_DIV:
04965   case OPR_REM:
04966   case OPR_MOD:
04967     {
04968       if (WN_operator_is(WN_kid1(wn), OPR_INTCONST)) {
04969   TYPE_ID rtype = OPCODE_rtype(WN_opcode(wn));
04970   INT64 constval = WN_const_val(WN_kid1(wn));
04971 
04972   return   opr == OPR_DIV
04973          ? Can_Do_Fast_Divide(rtype, constval)
04974          : Can_Do_Fast_Remainder(rtype, constval);
04975       }
04976     }
04977     break;
04978   }
04979 
04980   return FALSE;
04981 }
04982 
04983 
04984 #ifdef KEY
04985 /* Convert stmt
04986       a = a / b
04987    into
04988       if( b == N1 ){
04989          a = a / N1;
04990       } else if( b == ... ){
04991          ...;
04992       } else {
04993          a = a / b;
04994       }
04995    via feedback information.
04996 */
04997 static WN* simp_remdiv( WN* block, WN* tree )
04998 {
04999   if( Cur_PU_Feedback == NULL )
05000     return NULL;
05001 
05002   if( MTYPE_is_float( OPCODE_rtype(WN_opcode(tree) ) ) )
05003     return NULL;
05004 
05005   const FB_Info_Value& info = Cur_PU_Feedback->Query_value( tree );
05006 
05007   if( info.num_values == 0 )
05008     return NULL;
05009 
05010   if( info.exe_counter < (float)Div_Exe_Counter )
05011     return NULL;
05012 
05013   /* Sum up the freq of the top <Div_Exe_Candidates> entries. And perform div
05014      conversion only if the total freq is not less than <Div_Exe_Ratio>.
05015   */
05016   int items = 0;
05017   const float cutoff_ratio = (float)Div_Exe_Ratio / 100;
05018   const int num_candidates = MIN( info.num_values, Div_Exe_Candidates );
05019   FB_FREQ freq(0.0);
05020 
05021   for( items = 1; items <= num_candidates; items++ ){
05022     freq += info.freq[items-1];
05023     if( freq / info.exe_counter >= cutoff_ratio )
05024       break;
05025   }
05026 
05027   if( freq / info.exe_counter < cutoff_ratio )
05028     return NULL;
05029 
05030   const TYPE_ID type = WN_rtype( WN_kid(tree,1) );
05031   const PREG_NUM result = Create_Preg( type, ".remdiv_value" );
05032 
05033   for( int entry = 0; entry < items; entry++ ){
05034     WN* div_tree = NULL;
05035 
05036     WN* if_then = WN_CreateBlock();
05037     {
05038       WN* value = WN_CreateIntconst( OPCODE_make_op(OPR_INTCONST, type, MTYPE_V),
05039              info.value[entry] );
05040       WN* tmp = WN_Binary( WN_operator(tree), type,
05041          WN_COPY_Tree( WN_kid(tree,0) ),
05042          value );
05043       WN* stid = WN_StidIntoPreg( type, result, MTYPE_To_PREG( type ), tmp );
05044       WN_Set_Linenum(stid, current_srcpos);
05045       WN_INSERT_BlockLast( if_then, stid );
05046     }
05047     
05048     WN* if_else = WN_CreateBlock();
05049     {
05050       div_tree = WN_Binary( WN_operator(tree), type,
05051           WN_COPY_Tree( WN_kid(tree,0) ),
05052           WN_COPY_Tree( WN_kid(tree,1) ) );
05053       if( entry+1 == items ){
05054   WN* stid = WN_StidIntoPreg( type, result, MTYPE_To_PREG( type ), div_tree );
05055   WN_Set_Linenum(stid, current_srcpos);
05056   WN_INSERT_BlockLast( if_else, stid );
05057       }
05058     }
05059       
05060     WN* value = WN_CreateIntconst( OPCODE_make_op(OPR_INTCONST, type, MTYPE_V),
05061            info.value[entry] );
05062     WN* if_tree = WN_CreateIf( WN_EQ( type, WN_COPY_Tree(WN_kid(tree,1)),
05063               value ),
05064              if_then, if_else );
05065 
05066     Cur_PU_Feedback->Annot( if_tree, FB_EDGE_BRANCH_TAKEN, info.freq[entry] );
05067     Cur_PU_Feedback->Annot( if_tree, FB_EDGE_BRANCH_NOT_TAKEN,
05068           ( info.exe_counter - info.freq[entry] ) );
05069     
05070     WN_Set_Linenum(if_tree, current_srcpos);
05071     WN_INSERT_BlockLast( block, if_tree );
05072     
05073     WN_Delete( WN_kid(tree,0) );
05074     WN_Delete( WN_kid(tree,1) );
05075     WN_Delete( tree );
05076 
05077     tree = div_tree;
05078     block = if_else;
05079   }
05080       
05081   return WN_LdidPreg( type, result );
05082 }
05083 #endif
05084 
05085 #if defined(TARG_SL) && defined(EMULATE_FLOAT_POINT)
05086 static WN *lower_float_unary(WN *block, WN *tree, LOWER_ACTIONS actions)
05087 {
05088   OPERATOR opr  = WN_operator(tree);
05089   TYPE_ID desc  = WN_desc(tree);
05090   TYPE_ID rtype = WN_rtype(tree);
05091   FmtAssert(((rtype == MTYPE_F4) || (rtype == MTYPE_F8)), ("lower_float_unary: Unexpected type"));  
05092 
05093   WN *iwn = NULL;
05094   WN *wn = NULL;
05095   WN *kids[1] = {NULL};
05096   INTRINSIC intrinsic = INTRINSIC_INVALID; 
05097   BOOL is_f4 = (rtype == MTYPE_F4);
05098   switch (opr) {
05099     case OPR_SQRT:
05100       intrinsic = (is_f4 ? INTRN_FPE_FLOAT_SQRT : INTRN_FPE_DOUBLE_SQRT);
05101       break;
05102     case OPR_ABS:
05103       intrinsic = (is_f4 ? INTRN_FPE_FLOAT_ABS : INTRN_FPE_DOUBLE_ABS);
05104       break;
05105     case OPR_NEG:
05106       intrinsic = (is_f4 ? INTRN_FPE_FLOAT_NEG : INTRN_FPE_DOUBLE_NEG);   
05107       break;
05108     default:
05109       FmtAssert(FALSE, ("lower_float_unary: Unexpect orerators"));
05110   }
05111 
05112   FmtAssert(intrinsic != INTRINSIC_INVALID, ("lower_float_unary: Invalid intrinsic"));
05113 
05114   kids[0] = WN_CreateParm(rtype, WN_kid0(tree), MTYPE_To_TY(rtype),
05115       WN_PARM_BY_VALUE | WN_PARM_READ_ONLY);
05116 
05117   iwn = WN_Create_Intrinsic(OPCODE_make_op(OPR_INTRINSIC_OP, rtype, MTYPE_V),
05118       intrinsic, 1, kids);
05119 
05120   WN_Delete(tree);  
05121   return lower_expr(block, iwn, actions); //LOWER_INTRINSIC
05122 }
05123 
05124 static WN* lower_float_ALU (WN *block, WN *tree, LOWER_ACTIONS actions)
05125 {
05126   OPERATOR opr  = WN_operator(tree);
05127   TYPE_ID desc  = WN_desc(tree);
05128   TYPE_ID rtype = WN_rtype(tree);
05129 
05130   Is_True(OPCODE_is_expression(WN_opcode(tree)),
05131       ("lower_float_ALU: expected expression node, not %s", OPCODE_name(WN_opcode(tree))));
05132   Is_True(actions & LOWER_FP_EMULATE, ("lower_float_ALU: actions does not contain LOWER_FP_EMULATE"));
05133   Is_True((MTYPE_is_float(rtype)), ("lower_float_ALU: Unexpected float type"));
05134 
05135   WN *iwn = NULL;
05136   WN *wn  = NULL;
05137   WN *kids[2] = {NULL, NULL};
05138   INTRINSIC intrinsic;
05139   BOOL is_f4 = (rtype == MTYPE_F4);
05140   switch (opr) {
05141     case OPR_ADD:
05142       intrinsic = (is_f4 ? INTRN_FPE_FLOAT_ADD : INTRN_FPE_DOUBLE_ADD);
05143       break;
05144     case OPR_SUB:
05145       intrinsic = (is_f4 ? INTRN_FPE_FLOAT_SUB : INTRN_FPE_DOUBLE_SUB);
05146       break;
05147     case OPR_MPY:
05148       intrinsic = (is_f4 ? INTRN_FPE_FLOAT_MUL : INTRN_FPE_DOUBLE_MUL);
05149       break;
05150     case OPR_REM:
05151       intrinsic = (is_f4 ? INTRN_FPE_FLOAT_REM : INTRN_FPE_DOUBLE_REM);
05152       break;
05153     case OPR_DIV:
05154       intrinsic = (is_f4 ? INTRN_FPE_FLOAT_DIV : INTRN_FPE_DOUBLE_DIV);
05155       break;
05156     default:
05157       FmtAssert(FALSE, ("unexpected ALU operator in lower_float_compare")); 
05158   }
05159 
05160   kids[0] = WN_CreateParm(rtype, WN_kid0(tree), MTYPE_To_TY(rtype),
05161       WN_PARM_BY_VALUE | WN_PARM_READ_ONLY);
05162   kids[1] = WN_CreateParm(rtype, WN_kid1(tree), MTYPE_To_TY(rtype),
05163       WN_PARM_BY_VALUE | WN_PARM_READ_ONLY);  
05164   iwn = WN_Create_Intrinsic(OPCODE_make_op(OPR_INTRINSIC_OP, rtype, MTYPE_V),
05165       intrinsic, 2, kids);
05166 
05167   WN_Delete(tree);  
05168   return lower_expr(block, iwn, actions);//LOWER_INTRINSIC
05169 }
05170 
05171 static INTRINSIC SL_CVT_Intrinsic[6][6] = 
05172 {   
05173   /*I4,    U4,     I8,     U8,      F4,     F8 */
05174   /* I4 */ {INTRINSIC_NONE, INTRINSIC_NONE, INTRINSIC_NONE, INTRINSIC_NONE, INTRN_FPE_INT32_TO_FLOAT, INTRN_FPE_INT32_TO_DOUBLE},
05175   /* U4 */ {INTRINSIC_NONE, INTRINSIC_NONE, INTRINSIC_NONE, INTRINSIC_NONE, INTRN_FPE_UINT32_TO_FLOAT, INTRN_FPE_UINT32_TO_DOUBLE},
05176   /* I8 */ {INTRINSIC_NONE, INTRINSIC_NONE, INTRINSIC_NONE, INTRINSIC_NONE, INTRN_LLE_LL_TO_FLOAT, INTRN_LLE_LL_TO_DOUBLE},
05177   /* U8 */ {INTRINSIC_NONE, INTRINSIC_NONE, INTRINSIC_NONE, INTRINSIC_NONE, INTRN_LLE_ULL_TO_FLOAT, INTRN_LLE_ULL_TO_DOUBLE},
05178   /* F4 */ {INTRN_FPE_FLOAT_TO_INT32, INTRN_FPE_FLOAT_TO_UINT32, INTRN_LLE_FLOAT_TO_LL, INTRN_LLE_FLOAT_TO_ULL, INTRINSIC_NONE, INTRN_FPE_FLOAT_TO_DOUBLE},
05179   /* F8 */ {INTRN_FPE_DOUBLE_TO_INT32, INTRN_FPE_DOUBLE_TO_UINT32, INTRN_LLE_DOUBLE_TO_LL, INTRN_LLE_DOUBLE_TO_ULL, INTRN_FPE_DOUBLE_TO_FLOAT, INTRINSIC_NONE},
05180 };
05181 
05182 static INT get_intrinsic_index(TYPE_ID type)
05183 {
05184   switch (type)
05185   {
05186     case MTYPE_I4: return 0;
05187     case MTYPE_U4: return 1;
05188     case MTYPE_I8: return 2;
05189     case MTYPE_U8: return 3;
05190     case MTYPE_F4: return 4;
05191     case MTYPE_F8: return 5;
05192     default:
05193                    FmtAssert(FALSE, ("get_intrinsic_index: Unexpected type"));
05194   }
05195 }
05196 static WN *lower_SL_cvt(WN *block, WN *tree, LOWER_ACTIONS actions)
05197 {
05198   OPERATOR opr = WN_operator(tree);
05199   TYPE_ID  src = WN_desc(tree);
05200   TYPE_ID  dst = WN_rtype(tree);
05201   INTRINSIC intrinsic;
05202 
05203   WN *kids[1] = {NULL};
05204   WN *iwn;
05205 
05206   FmtAssert((src != dst), ("lower_SL_cvt: expect diff type"));
05207 
05208   INT row = get_intrinsic_index(src);
05209   INT col = get_intrinsic_index(dst);
05210 
05211 
05212   intrinsic = SL_CVT_Intrinsic[row][col];
05213 
05214   kids[0] = WN_CreateParm(src, WN_kid0(tree), MTYPE_To_TY(src),
05215       WN_PARM_BY_VALUE | WN_PARM_READ_ONLY);
05216 
05217   iwn = WN_Create_Intrinsic(OPCODE_make_op(OPR_INTRINSIC_OP, dst, MTYPE_V),
05218       intrinsic, 1, kids);
05219 
05220   WN_Delete(tree);  
05221   return lower_expr(block, iwn, actions); //LOWER_INTRINSIC
05222 }
05223 
05224 static WN * lower_float_compare(WN *block, WN *tree, LOWER_ACTIONS actions)
05225 {
05226   OPERATOR opr  = WN_operator(tree);
05227   TYPE_ID  desc = WN_desc(tree);
05228 
05229   FmtAssert(((desc == MTYPE_F4) || (desc == MTYPE_F8)), ("lower_float_compare: Unexpected type"));
05230 
05231   WN *iwn     = NULL;
05232   WN *wn      = NULL;
05233   WN *kids[2] = {NULL, NULL};
05234   INTRINSIC intrinsic;
05235   BOOL is_f4 = (desc == MTYPE_F4);
05236 
05237   switch (opr) {
05238     case OPR_LT:
05239       intrinsic = (is_f4 ? INTRN_FPE_FLOAT_LT : INTRN_FPE_DOUBLE_LT);
05240       break;
05241     case OPR_LE:
05242       intrinsic = (is_f4 ? INTRN_FPE_FLOAT_LE : INTRN_FPE_DOUBLE_LE);
05243       break;
05244     case OPR_EQ:
05245       intrinsic = (is_f4 ? INTRN_FPE_FLOAT_EQ : INTRN_FPE_DOUBLE_EQ);
05246       break;
05247     case OPR_NE:
05248       intrinsic = (is_f4 ? INTRN_FPE_FLOAT_NE : INTRN_FPE_DOUBLE_NE);
05249       break;
05250     case OPR_GE:
05251       intrinsic = (is_f4 ? INTRN_FPE_FLOAT_GE : INTRN_FPE_DOUBLE_GE);
05252       break;
05253     case OPR_GT:
05254       intrinsic = (is_f4 ? INTRN_FPE_FLOAT_GT : INTRN_FPE_DOUBLE_GT);
05255       break;    
05256     default:
05257       FmtAssert(FALSE, ("unexpected compare condition in lower_float_compare"));
05258   }
05259 
05260   // new block for lowering intrinsic call properly
05261   WN *new_block = WN_CreateBlock();  
05262 
05263   kids[0]        = WN_CreateParm(desc, WN_kid0(tree), Be_Type_Tbl(desc),
05264       WN_PARM_BY_VALUE | WN_PARM_READ_ONLY);
05265   kids[1]        = WN_CreateParm(desc, WN_kid1(tree), Be_Type_Tbl(desc),
05266       WN_PARM_BY_VALUE | WN_PARM_READ_ONLY);   
05267   iwn            = WN_Create_Intrinsic(OPCODE_make_op(OPR_INTRINSIC_CALL,
05268         MTYPE_I4, MTYPE_V), intrinsic, 2, kids);
05269   WN_copy_linenum(tree, iwn);
05270   WN_INSERT_BlockLast(new_block, iwn); // insert into new block
05271 
05272 
05273   ST       *preg_st     = MTYPE_To_PREG(MTYPE_I4);
05274   TY_IDX    preg_ty_idx = Be_Type_Tbl(MTYPE_I4);
05275   PREG_NUM  preg         = Create_Preg(MTYPE_I4, NULL);
05276 
05277   wn = WN_Ldid(MTYPE_I4, -1, Return_Val_Preg, preg_ty_idx);
05278   wn = WN_Stid(MTYPE_I4, preg, preg_st, preg_ty_idx, wn),
05279      WN_copy_linenum(tree, wn);
05280   WN_INSERT_BlockLast(new_block, wn);  // insert into new block, force use return value of intrinsic call
05281 
05282 
05283   WN *low_iwn = lower_intrinsic_call(block, iwn, actions | LOWER_INTRINSIC);
05284 
05285   WN_copy_linenum(tree, low_iwn);
05286   WN_INSERT_BlockLast(block, low_iwn);  // insert into block
05287 
05288   RETURN_INFO return_info = Get_Return_Info(MTYPE_To_TY(MTYPE_I4), Complex_Not_Simulated);
05289   PREG_NUM    reg_ret     = RETURN_INFO_preg(return_info, 0);
05290 
05291   wn = WN_Ldid(MTYPE_I4, reg_ret, Return_Val_Preg, preg_ty_idx);
05292   wn = WN_CreateExp2(OPR_NE, Boolean_type, MTYPE_I4, wn, 
05293       WN_Intconst(MTYPE_I4, 0));  
05294 
05295   WN_Delete(tree);
05296   WN_Delete(new_block);
05297 
05298   return lower_expr(block, wn, actions); 
05299 }
05300 #endif //  TARG_SL && EMULATE_FLOAT_POINT
05301 
05302 /* ====================================================================
05303  *
05304  * WN *lower_expr(WN *block, WN *tree, LOWER_ACTIONS actions)
05305  *
05306  * Perform lowering (see WN_Lower description) on expression <tree>,
05307  * returning lowered expression tree.
05308  *
05309  * ==================================================================== */
05310 
05311 static WN *lower_expr(WN *block, WN *tree, LOWER_ACTIONS actions)
05312 {
05313   BOOL kids_lowered = FALSE;  /* becomes TRUE when kids are lowered */
05314   BOOL intrinsic_lowered;
05315 
05316   TYPE_ID type = WN_rtype(tree);
05317 
05318   Is_True(OPCODE_is_expression(WN_opcode(tree)),
05319     ("expected expression node, not %s", OPCODE_name(WN_opcode(tree))));
05320 
05321   if (OPCODE_is_load(WN_opcode(tree)))
05322     lower_map(tree, actions);
05323 
05324  /*
05325   *  before children are processed reassociate for madd oportunities
05326   */
05327   if (Action(LOWER_MADD)  &&
05328       Madd_Allowed    &&
05329      ((MTYPE_id(type) == MTYPE_F4 || MTYPE_id(type) == MTYPE_F8)
05330 #ifdef TARG_NVISA
05331       // NVISA supports integer madds
05332       || (Integer_Madd_Allowed &&
05333        (MTYPE_id(type) == MTYPE_I4 || MTYPE_id(type) == MTYPE_U4
05334         || MTYPE_id(type) == MTYPE_I8 || MTYPE_id(type) == MTYPE_U8))
05335 #endif
05336       ))
05337   {
05338     tree = lower_nary_madd(block, tree, actions);
05339     tree = lower_madd(block, tree, actions);
05340   }
05341   if (Action(LOWER_TREEHEIGHT)  &&
05342       WN_is_commutative(tree))
05343   {
05344     if (MTYPE_is_integral(type) || Roundoff_Level >= ROUNDOFF_ASSOC)
05345       tree = lower_tree_height(block, tree, actions);
05346   }
05347 
05348  /* Note: We must split constant offsets after lowering complex exprs
05349   * and splitting symbol addresses since these may create new offsets
05350   * that need to be split.
05351   */
05352   switch (WN_operator(tree))
05353   {
05354 #if defined(TARG_SL) && defined(EMULATE_LONGLONG)
05355   case OPR_LSHR: // no break
05356   case OPR_ASHR:
05357   case OPR_SHL:  
05358     if ((Action(LOWER_TO_CG)) && (type == MTYPE_I8 || type == MTYPE_U8))
05359     {
05360       OPERATOR opr = WN_operator(WN_kid1(tree));
05361       if (opr != OPR_INTCONST) // INTCONST is expanded in CG expand
05362       {  
05363         INTRINSIC intrinsic = WN_operator(tree) == OPR_LSHR ? INTRN_LLE_LSHR_LL :
05364           (WN_operator(tree) == OPR_ASHR ? INTRN_LLE_ASHR_LL : INTRN_LLE_ASHL_LL);
05365         
05366         WN * kids[2] = {0};
05367         WN * tmp     = lower_expr(block, WN_kid0(tree), actions);
05368         TYPE_ID tid  = WN_rtype(tmp);
05369       
05370         kids[0]      = WN_CreateParm(tid, tmp, Be_Type_Tbl(tid),
05371                 WN_PARM_BY_VALUE | WN_PARM_READ_ONLY);
05372 
05373         WN * tmp1    = lower_expr(block, WN_kid1(tree), actions);
05374         TYPE_ID tid1 = WN_rtype(tmp1);
05375         
05376         if (tid1 == MTYPE_I8 || tid == MTYPE_U8) 
05377         {
05378           tmp1       = WN_Cvt(tid, MTYPE_I4, tmp1);
05379           tid1       = MTYPE_I4;
05380         } 
05381         TY_IDX tyi1  = Be_Type_Tbl(tid1);      
05382         kids[1]      = WN_CreateParm(tid1, tmp1, tyi1, WN_PARM_BY_VALUE | WN_PARM_READ_ONLY);
05383       
05384         WN * iwn     = WN_Create_Intrinsic(
05385                          OPCODE_make_op(OPR_INTRINSIC_OP, type, MTYPE_V), 
05386                          intrinsic, 2, kids);
05387   
05388         WN_Delete(tree);
05389         return lower_expr(block, iwn, actions);    
05390       }
05391     }
05392     break;
05393 #endif
05394   case OPR_INTRINSIC_OP:
05395     if (INTRN_is_nary(WN_intrinsic(tree)))
05396       break;
05397 
05398     if (INTRN_cg_intrinsic(WN_intrinsic(tree)))
05399       break;
05400 
05401 #ifdef TARG_X8664
05402     if( ( (INTRINSIC)WN_intrinsic(tree) == INTRN_F8ANINT ) &&
05403   Is_Target_SSE2() ){
05404       /* The code implemented in em_nearest_aint will introduce conversions
05405    between long long and float, which will slow down the performance
05406    under -m32.
05407       */
05408       if( Is_Target_32bit() )
05409   break;
05410 
05411       /* cg can generate a more accurate and faster version when
05412    -OPT:fast_dnint is ON.
05413    Expand the fast version as late as possible to avoid being
05414    screwed up by cfold reassociation.
05415       */
05416       if( Fast_ANINT_Allowed )
05417         break;
05418     }
05419 #endif
05420 
05421 #ifdef KEY
05422     if ( (INTRINSIC) WN_intrinsic (tree) == INTRN_CONSTANT_P
05423          /* && Action (LOWER_TO_CG) */ ) {
05424       WN * old = tree;
05425       WN * parm = WN_kid0 (WN_kid0 (old)); // child of OPR_PARM
05426 
05427       // Check if the argument is a compile-time constant, replace the
05428       // intrn op by true/false
05429       if (WN_operator (parm) == OPR_INTCONST ||
05430           (OPCODE_has_sym (WN_opcode (parm)) &&
05431            ST_class (WN_st (parm)) == CLASS_CONST)) {
05432         tree = WN_Intconst (MTYPE_I4, 1);
05433         WN_copy_linenum (old, tree);
05434         WN_Delete (old);
05435         kids_lowered = TRUE;
05436         break;
05437       }
05438       else if ( Action (LOWER_TO_CG) ) {
05439   // Still not constant, replace it by false
05440   tree = WN_Intconst (MTYPE_I4, 0);
05441         WN_copy_linenum (old, tree);
05442   WN_Delete (old);
05443   kids_lowered = TRUE;
05444         break;
05445       }
05446     }
05447 #endif
05448 
05449     if (INTRN_is_actual(WN_intrinsic(tree)))
05450     {
05451       if (Action(LOWER_INTRINSIC))
05452       {
05453   tree = lower_intrinsic(block, tree, actions);
05454         kids_lowered = TRUE;
05455       }
05456       break;
05457     }
05458     if (Action(LOWER_INTRINSIC) ||
05459   Action(LOWER_INLINE_INTRINSIC) ||
05460 #ifdef KEY // bug 6938
05461   Action(LOWER_FAST_EXP) ||
05462 #endif
05463   Action(LOWER_INL_STACK_INTRINSIC))
05464     {
05465       tree = lower_emulation(block, tree, actions, intrinsic_lowered);
05466       kids_lowered = TRUE;
05467     }
05468     break;
05469 
05470   case OPR_ARRAY:
05471     if (Action(LOWER_ARRAY))
05472     {
05473       tree = lower_linearize_array_addr(block, tree, actions);
05474       kids_lowered = TRUE;
05475     }
05476     break;
05477 
05478   case OPR_ADD:
05479     if (Action(LOWER_SPLIT_CONST_OFFSETS))
05480     {
05481      /*
05482       * Split
05483       *       LDA   (c1) <sym>
05484       *       CONST (c2)
05485       *     ADD
05486       * Into
05487       *       LDA   (hi) <sym>
05488       *       CONST (low)
05489       *     ADD
05490       */
05491       WN *lda = WN_kid0(tree);
05492       WN *con = WN_kid1(tree);
05493 
05494       if (WN_operator_is(con, OPR_INTCONST) &&
05495     foldLdaOffset(lda, WN_const_val(con)))
05496       {
05497         WN_OFFSET  offset = WN_lda_offset(lda) + WN_const_val(con);
05498 
05499   if (mem_offset_must_be_split(offset))
05500   {
05501     WN_lda_offset(lda) = mem_offset_hi(offset);
05502     WN_const_val(con) =  mem_offset_lo(offset);
05503   }
05504       }
05505     }
05506     else
05507     {
05508      /*
05509       * Fold
05510       *       LDA   (c1) <sym>
05511       *       CONST (c2)
05512       *     ADD
05513       * Into
05514       *     LDA (c1+c2) <sym>
05515       */
05516       WN *lda = WN_kid0(tree);
05517       WN *con = WN_kid1(tree);
05518 
05519       if (WN_operator_is(con, OPR_INTCONST) &&
05520     foldLdaOffset(lda, WN_const_val(con)))
05521       {
05522   WN_lda_offset(lda) += WN_const_val(con);
05523   WN_Delete(tree);
05524   WN_Delete(con);
05525   tree = lower_expr(block, lda, actions);;
05526       }
05527     }
05528     break;
05529 
05530   case OPR_MLOAD:
05531     if (Align_Object)
05532     {
05533       WN_kid0(tree)=  lower_expr(block, WN_kid0(tree), actions);
05534       kids_lowered =  TRUE;
05535 
05536       tree = improve_Malignment(tree, WN_kid0(tree), WN_kid1(tree),
05537         WN_load_offset(tree));
05538       break;
05539     }  /* fall thru */
05540 
05541   case OPR_ILOAD:
05542     if (Action(LOWER_MLDID_MSTID) && WN_opcode(tree) == OPC_MMILOAD)
05543       return lower_miload(block, tree, actions);
05544 
05545     if (Action(LOWER_BIT_FIELD_ID) && WN_desc(tree) == MTYPE_BS) {
05546       lower_bit_field_id(tree);
05547       if (Action(LOWER_BITS_OP) && WN_operator(tree) == OPR_ILDBITS)
05548   return lower_load_bits (block, tree, actions);
05549     }
05550 
05551     if (Action(LOWER_SPLIT_CONST_OFFSETS))
05552     {
05553      /*
05554       * Convert
05555       *      EXPR
05556       *    ILOAD (offset>16bits)
05557       * Into
05558       *        CONST (hi)
05559       *        EXPR
05560       *      ADD
05561       *    ILOAD (lo)
05562       */
05563       WN_OFFSET  offset = WN_load_offset(tree);
05564       if (mem_offset_must_be_split(offset))
05565       {
05566   WN_kid0(tree) =  WN_Add(Pointer_type,
05567         WN_kid0(tree),
05568         WN_Intconst(Pointer_type,
05569               mem_offset_hi(offset)));
05570   WN_load_offset(tree) = mem_offset_lo(offset);
05571       }
05572     }
05573     else
05574     {
05575      /*
05576       * Fold
05577       *       LDA (c1) <sym>
05578       *     ILOAD (c2)
05579       * Into
05580       *       LDA (0)  <sym>
05581       *     ILOAD (c1+c2)
05582       */
05583       WN *kid = WN_kid0(tree);
05584 
05585 #ifdef TARG_MIPS
05586       /* We don't want this for MIPS since (c1+c2) could likely be
05587          out-of-range for the ILOAD, and we have the global
05588          canonicalization optimization to assign c1 and c2
05589          appropriately. */
05590       if (FALSE)
05591 #else
05592       if (foldLdaOffset(kid, WN_load_offset(tree)))
05593 #endif
05594       {
05595   WN_load_offset(tree) += WN_lda_offset(kid);
05596   WN_lda_offset(kid) = 0;
05597       }
05598 #ifndef TARG_MIPS
05599      /*
05600       * Fold
05601       *           EXPR 
05602       *           CONST (c1)
05603       *       ADD expr
05604       *     ILOAD (c1)
05605       * Into
05606       *       EXPR
05607       *     ILOAD (c1+c2)
05608       */
05609       else if (WN_operator_is(kid, OPR_ADD) &&
05610          foldConstOffset(WN_kid1(kid), WN_load_offset(tree)))
05611       {
05612   WN_load_offset(tree) += WN_const_val(WN_kid1(kid));
05613   WN_kid0(tree) = WN_kid0(kid);
05614   WN_Delete(WN_kid1(kid));
05615   WN_Delete(kid);
05616       }
05617 #endif
05618     }
05619     break;
05620 
05621   case OPR_LDID:
05622     if (Action(LOWER_RETURN_VAL) && WN_st(tree) == Return_Val_Preg)
05623       return lower_return_ldid(block, tree, actions);
05624 
05625     if (Action(LOWER_MLDID_MSTID) && WN_opcode(tree) == OPC_MMLDID)
05626       return lower_mldid(block, tree, actions);
05627 
05628     if (Action(LOWER_BIT_FIELD_ID) && WN_desc(tree) == MTYPE_BS) {
05629       lower_bit_field_id(tree);
05630       if (Action(LOWER_BITS_OP) && WN_operator(tree) == OPR_LDBITS)
05631   return lower_load_bits (block, tree, actions);
05632     }
05633 
05634     if ((WN_class(tree) == CLASS_CONST) && (WN_load_offset(tree) == 0))
05635     {
05636       TCON  val = WN_val(tree);
05637       TYPE_ID valType = WN_val_type(tree);
05638       WN  *con;
05639 
05640       if (MTYPE_is_integral(type) && MTYPE_is_integral(valType))
05641       {
05642   con = WN_Intconst(type, Targ_To_Host( val));
05643         WN_Delete(tree);
05644         return con;
05645       }
05646      /*
05647       *  check for real (complex constant) conversion not handled by Targ_Conv
05648       */
05649       else if ((MTYPE_is_float(type) && MTYPE_is_float(valType))  &&
05650         !(!MTYPE_is_complex(type) && MTYPE_is_complex(valType)))
05651       {
05652   if (type != valType)
05653   {
05654     val = Targ_Conv(type, val);
05655   }
05656   con = Make_Const(val);
05657   WN_Delete(tree);
05658   return con;
05659       }
05660     }
05661     {
05662       PREG_NUM last_preg = Get_Preg_Num(PREG_Table_Size(CURRENT_SYMTAB));
05663       if ((WN_class(tree) == CLASS_PREG) &&
05664     (WN_load_offset(tree) > last_preg))
05665       {
05666     DevWarn("lower_expr() pregno %d > SYMTAB_last_preg(%d)",
05667       WN_load_offset(tree), last_preg);
05668       }
05669     }
05670    /*
05671     * Exposes the LDA for RVI usage
05672     */
05673     if (Action(LOWER_SPLIT_SYM_ADDRS))
05674     {
05675       WN  *iload;
05676       iload = lower_split_sym_addrs(tree, WN_load_offset(tree), actions);
05677       if (iload)
05678       {
05679   return lower_expr(block, iload, actions);
05680       }
05681     }
05682     if ( Action(LOWER_FORMAL_REF) && WN_class(tree) == CLASS_VAR)
05683     {
05684       WN     *iload;
05685 
05686       iload = lower_formal_ref(tree, WN_load_offset(tree),
05687              WN_st(tree), actions);
05688       if (iload)
05689       {
05690         return lower_expr(block, iload, actions);
05691       }
05692     }
05693     if ( Action(LOWER_UPLEVEL))
05694     {
05695       ST *sym = WN_st(tree);
05696 
05697       if (ST_is_uplevelTemp(sym))
05698       {
05699         WN     *iload;
05700 
05701         iload = lower_uplevel_reference(tree, WN_load_offset(tree), actions);
05702   tree = lower_expr(block, iload, actions);
05703   return tree;
05704       }
05705     }
05706     if ( Action(LOWER_TO_CG) && promote_tls_ldst &&
05707          ST_is_tls( WN_st(tree) ) ) {
05708       // There is a ldid to TLS data needs to be promoted to up level
05709       // In order to avoid conflicts in output registers
05710       // We create a preg to be the local copy of the TLS variable.
05711       //       LDID tls_st <ST_IS_THREAD_PRIVATE>
05712       //     ......
05713       //   OPR_PARAM
05714       // OPR_CALL
05715       // --->
05716       //   LDID tls_st <ST_IS_THREAD_PRIVATE>
05717       // STID local_num <PREG>
05718       //       LDID local_num <PREG>
05719       //     ......
05720       //   OPR_PARAM
05721       // OPR_CALL
05722       char local_name[64];
05723       ST* tls_st = WN_st(tree);
05724       TYPE_ID tls_mtype = ST_mtype(tls_st);
05725       snprintf(local_name, 64, "%s.local", ST_name(tls_st));
05726       ST* local_st = MTYPE_To_PREG(tls_mtype);
05727       PREG_NUM local_num = Create_Preg(tls_mtype, local_name);
05728       WN* tls_ldid = WN_COPY_Tree(tree);
05729       WN* local_stid = WN_StidIntoPreg(tls_mtype, local_num,
05730                                        local_st, tls_ldid);
05731       WN_INSERT_BlockLast(block, local_stid);
05732       WN* local_ldid = WN_LdidPreg(tls_mtype, local_num );
05733       WN_Delete(tree);
05734       return local_ldid;
05735     }
05736     break;
05737 
05738   case OPR_ILDBITS:
05739   case OPR_LDBITS:
05740     if (Action(LOWER_BITS_OP))
05741       return lower_load_bits (block, tree, actions);
05742     break;
05743     
05744   case OPR_LDA:
05745    /*
05746     *  use of LDA should mark STFL_ADDR_USED_LOCALLY
05747     */
05748     {
05749       ST *sym = WN_st(tree);
05750 
05751       // if ((ST_class(sym) == CLASS_VAR) ||
05752       //     (ST_class(sym) == CLASS_FUNC)) {
05753       //   Do nothing here. ADDR flags should only grow more
05754       //   optimistic; they should never become more conservative,
05755       //   because the program's semantics cannot grow worse as we
05756       //   compile it.
05757       // }
05758 
05759       if (ST_class(sym) == CLASS_BLOCK && STB_merge(sym))
05760       {
05761   DevWarn("LDA (%s) potential bad exposed use of a mergeable symbol",
05762     ST_name(sym));
05763       }
05764     }
05765     if (Action(LOWER_SPLIT_SYM_ADDRS))
05766     {
05767       WN  *lda;
05768       lda = lower_split_sym_addrs(tree, WN_lda_offset(tree), actions);
05769       if (lda)
05770       {
05771   return lower_expr(block, lda, actions);
05772       }
05773     }
05774     if ( Action(LOWER_FORMAL_REF) && WN_class(tree) == CLASS_VAR)
05775     {
05776       WN     *ldid;
05777 
05778       ldid =  lower_formal_ref(tree, WN_lda_offset(tree), WN_st(tree),
05779          actions);
05780       if (ldid)
05781       {
05782   return lower_expr(block, ldid, actions);
05783       }
05784     }
05785     if ( Action(LOWER_UPLEVEL))
05786     {
05787       ST *sym = WN_st(tree);
05788 
05789       if (ST_is_uplevelTemp(sym))
05790       {
05791         WN     *ldid;
05792 
05793         ldid = lower_uplevel_reference(tree, WN_lda_offset(tree), actions);
05794   tree = lower_expr(block, ldid, actions);
05795   return tree;
05796       }
05797     }
05798     if (Action(LOWER_TO_CG) && promote_tls_ldst &&
05799         ST_is_tls( WN_st(tree) ) ) 
05800     {
05801       // promote OPR_LDA to TLS variable in the OPR_PARAM of OPR_CALL to upper level
05802       // In order to avoid conflicts in output registers
05803       //       OPR_LDA tls_st <ST_IS_THREAD_PRIVATE>
05804       //     ......
05805       //   OPR_PARAM
05806       // OPR_CALL
05807       // --->
05808       //   OPR_LDA tls_st <ST_IS_THREAD_PRIVATE>
05809       // OPR_STID local_num <PREG>
05810       //       OPR_LDID local_num <PREG>
05811       //     ......
05812       //   OPR_PARAM
05813       // OPR_CALL
05814       char local_name[64];
05815       ST* tls_st = WN_st(tree);
05816       snprintf(local_name, 64, "local.%s", ST_name(tls_st));
05817       ST* local_st = MTYPE_To_PREG(Pointer_type);
05818       PREG_NUM local_num = Create_Preg ( Pointer_type, local_name);
05819       WN* tls_lda = WN_COPY_Tree(tree);
05820       WN* local_stid = WN_StidIntoPreg( Pointer_type, local_num, 
05821                                         local_st, tls_lda);
05822       WN_INSERT_BlockLast(block, local_stid);
05823       WN * local_ldid = WN_LdidPreg(Pointer_type, local_num);
05824       WN_Delete(tree);
05825       return local_ldid;
05826     }
05827 #ifdef KEY  // if taking address of a nested function, replace it by the address
05828     // of the corresopnding trampoline
05829     if (Action(LOWER_UPLEVEL) && WN_class(tree) == CLASS_FUNC) {
05830       ST *sym = WN_st(tree);
05831       PU &pu = Pu_Table[ST_pu(sym)];
05832       if (PU_need_trampoline(pu)) {
05833   Allocate_Object(sym); // because it may not appear again
05834   ST_IDX tramp_st_idx = find_trampoline(ST_st_idx(sym));
05835         WN_st_idx(tree) = tramp_st_idx;
05836   return lower_expr(block, tree, actions | LOWER_UPLEVEL);
05837       }
05838     }
05839 #endif
05840 
05841     break;
05842 
05843   case OPR_CVT:
05844   case OPR_TRUNC:
05845   case OPR_RND:
05846     if (Action(LOWER_CVT))
05847     {
05848       tree = lower_cvt(block, tree, actions);
05849       kids_lowered = TRUE;
05850     }
05851     break;
05852 
05853   case OPR_TAS:
05854 
05855     /* If the operand of the TAS is a load from memory, try to
05856      * replace with a load matching the result type of the TAS.
05857      * Doing so may avoid a move from one register set to another.
05858      */
05859     if (Action(LOWER_TO_CG))
05860     {
05861       WN *load = WN_kid0(tree);
05862       if (   OPERATOR_is_load(WN_operator(load))
05863     && (!WN_has_sym(load) || WN_class(load) != CLASS_PREG))
05864       {
05865   TYPE_ID tas_rtype = WN_rtype(tree);
05866   if (MTYPE_byte_size(tas_rtype) == MTYPE_byte_size(WN_desc(load))) {
05867     WN_set_rtype(load, tas_rtype);
05868     WN_set_desc(load, tas_rtype);
05869     WN_Delete(tree);
05870     return lower_expr(block, load, actions);
05871   }
05872       }
05873     }
05874     break;
05875 
05876   case OPR_IMAGPART:
05877     if (Action(LOWER_COMPLEX))
05878     {
05879       WN  *realexp, *imagexp;
05880       lower_complex_expr(block, WN_kid0(tree), actions, &realexp, &imagexp);
05881       WN_Delete(tree);
05882       tree = lower_expr(block, imagexp, actions);
05883     }
05884     break;
05885 
05886   case OPR_REALPART:
05887     if (Action(LOWER_COMPLEX))
05888     {
05889       WN  *realexp, *imagexp;
05890 
05891       lower_complex_expr(block, WN_kid0(tree), actions, &realexp, &imagexp);
05892       WN_Delete(tree);
05893       tree = lower_expr(block, realexp, actions);
05894     }
05895     break;
05896     
05897   case OPR_EQ:
05898     if (Action(LOWER_COMPLEX) && MTYPE_is_complex(WN_desc(tree)))
05899     {
05900       /*
05901        *  x == y
05902        *    R(x)==R(y) && I(x)==I(y)
05903        */
05904       WN  *rx, *ry, *ix, *iy;
05905       TYPE_ID realTY = Mtype_complex_to_real( WN_desc(tree));
05906 
05907       lower_complex_expr(block, WN_kid0(tree), actions, &rx, &ix);
05908       lower_complex_expr(block, WN_kid1(tree), actions, &ry, &iy);
05909  
05910       tree = WN_LAND(WN_EQ(realTY, rx, ry),
05911          WN_EQ(realTY, ix, iy));
05912 
05913       return lower_expr(block, tree, actions);
05914     }
05915     break;
05916 
05917   case OPR_NE:
05918     if (Action(LOWER_COMPLEX) && MTYPE_is_complex(WN_desc(tree)))
05919     {
05920       /*
05921        *  x != y
05922        *    ! ( R(x)==R(y)  &&  I(x)==I(y) )
05923        */
05924       WN  *rx, *ry, *ix, *iy;
05925       TYPE_ID realTY = Mtype_complex_to_real( WN_desc(tree));
05926 
05927       lower_complex_expr(block, WN_kid0(tree), actions, &rx, &ix);
05928       lower_complex_expr(block, WN_kid1(tree), actions, &ry, &iy);
05929  
05930       tree = WN_LNOT(WN_LAND(WN_EQ(realTY, rx, ry),
05931            WN_EQ(realTY, ix, iy)));
05932 
05933       return lower_expr(block, tree, actions);
05934     }
05935     break;
05936 
05937   case OPR_MADD:
05938     if (Action(LOWER_QUAD) && MTYPE_is_quad(type))
05939     {
05940      /*
05941       *   kid1 * kid2 + kid0
05942       */
05943       WN  *wn;
05944 
05945       wn = WN_Add(type,
05946       WN_Mpy(type, WN_kid1(tree), WN_kid2(tree)),
05947       WN_kid0(tree));
05948       WN_Delete(tree);
05949 
05950       tree = wn;
05951     }
05952     break;
05953 
05954   case OPR_MSUB:
05955     if (Action(LOWER_QUAD) && MTYPE_is_quad(type))
05956     {
05957      /*
05958       *   kid1 * kid2 - kid0
05959       */
05960       WN  *wn;
05961 
05962       wn = WN_Sub(type,
05963       WN_Mpy(type, WN_kid1(tree), WN_kid2(tree)),
05964       WN_kid0(tree));
05965       WN_Delete(tree);
05966 
05967       tree = wn;
05968     }
05969     break;
05970 
05971   case OPR_NMADD:
05972     if (Action(LOWER_QUAD) && MTYPE_is_quad(type))
05973     {
05974      /*
05975       *   - (kid1 * kid2 + kid0)
05976       */
05977       WN  *wn, *madd;
05978 
05979       madd = WN_Add(type,
05980         WN_Mpy(type, WN_kid1(tree), WN_kid2(tree)),
05981         WN_kid0(tree));
05982 
05983       wn = WN_Neg(type, madd);
05984       WN_Delete(tree);
05985 
05986       tree = wn;
05987     }
05988     break;
05989 
05990   case OPR_NMSUB:
05991     if (Action(LOWER_QUAD) && MTYPE_is_quad(type))
05992     {
05993      /*
05994       *   - (kid1 * kid2 - kid0)  -->   (kid0 - kid1 * kid2)
05995       */
05996       WN  *wn;
05997 
05998       wn = WN_Sub(type,
05999       WN_kid0(tree),
06000       WN_Mpy(type, WN_kid1(tree), WN_kid2(tree)));
06001       WN_Delete(tree);
06002 
06003       tree = wn;
06004     }
06005     break;
06006 
06007   case OPR_RSQRT:
06008     tree = lower_rsqrt(block, tree, actions);
06009     break;
06010 
06011   case OPR_RECIP:
06012     tree = lower_recip(block, tree, actions);
06013     break;
06014 
06015   case OPR_SELECT:
06016     {
06017 #ifdef KEY // f90 front-end sometimes generate inconsistent types; fix them
06018       if (MTYPE_size_min(type) != MTYPE_size_min(WN_rtype(WN_kid1(tree))))
06019   WN_kid1(tree) = WN_Cvt(WN_rtype(WN_kid1(tree)), type, WN_kid1(tree));
06020       if (MTYPE_size_min(type) != MTYPE_size_min(WN_rtype(WN_kid2(tree))))
06021   WN_kid2(tree) = WN_Cvt(WN_rtype(WN_kid2(tree)), type, WN_kid2(tree));
06022 #endif
06023       WN * const kid0 = WN_kid0(tree);  // the condition expression
06024       if (WN_operator_is(kid0, OPR_INTCONST))
06025       {
06026   INT64 flag = WN_const_val(kid0);
06027   WN * const kid = flag ? WN_kid1(tree) : WN_kid2(tree);
06028   return lower_expr(block, kid, actions);
06029       } else if (WN_operator(kid0) == OPR_LNOT) {
06030   // swap the select inputs and replace the condition with
06031   // operand of the LNOT. Then lower the whole tree again
06032   // as there may be further lowerings that may occur with the
06033   // new operands.
06034   WN * const new_kid1 = WN_kid2(tree);
06035   WN * const new_kid2 = WN_kid1(tree);
06036   WN * const new_kid0 = WN_kid0(kid0);
06037   TYPE_ID new_desc = (WN_rtype(new_kid0) == MTYPE_B) ? MTYPE_B : MTYPE_V;
06038   WN_kid0(tree) = new_kid0;
06039   WN_kid1(tree) = new_kid1;
06040   WN_kid2(tree) = new_kid2;
06041   WN_set_desc(tree, new_desc);
06042   WN_Delete(kid0);
06043   return lower_expr(block, tree, actions);
06044       }
06045     }
06046     break;
06047 
06048   case OPR_PAREN:
06049     if (Roundoff_Level > ROUNDOFF_ASSOC
06050 #ifdef TARG_X8664 // Such useless PARENs are used by LNO's Simd phase as markers
06051         || WN_kid_count(tree) < 2
06052 #endif
06053        )
06054     {
06055      /*
06056       *  At suitable roundoff we may remove these parens
06057       *  This will allow better MADD generation latter (pv 316380)
06058       */
06059       WN *kid0 = WN_kid0(tree);
06060 
06061       WN_Delete(tree);
06062       return lower_expr(block, kid0, actions);
06063     }
06064     break;
06065 
06066   case OPR_DIV:
06067   case OPR_REM:
06068   case OPR_MOD:
06069 
06070     {
06071 #ifdef KEY
06072       WN* simp = simp_remdiv( block, tree );
06073       if( simp != NULL ){
06074   return simp;
06075       }
06076 #endif      
06077 
06078       /* If not inlining divides, then generate an INTRINSIC_OP that is
06079        * later lowered to a call
06080        */
06081       TYPE_ID rtype = OPCODE_rtype(WN_opcode(tree));
06082       if (Should_Call_Divide(rtype) && !Is_Fast_Divide(tree)) {
06083 
06084 #ifdef EMULATE_LONGLONG
06085         if (rtype == MTYPE_I8 || rtype == MTYPE_U8) {
06086     FmtAssert (OPCODE_rtype(WN_opcode(WN_kid0(tree))) == rtype,
06087          ("DIV/REM/MOD: kid0 should be %d, is %d",
06088          rtype, OPCODE_rtype(WN_opcode(WN_kid0(tree)))));
06089     FmtAssert (OPCODE_rtype(WN_opcode(WN_kid1(tree))) == rtype,
06090          ("DIV/REM/MOD: kid1 should be %d, is %d",
06091          rtype, OPCODE_rtype(WN_opcode(WN_kid1(tree)))));
06092   }
06093 #endif
06094 
06095   WN *kids[2];
06096   WN *iwn;
06097   LEAF tmpY;
06098   INTRINSIC intrinsic;
06099   BOOL is_unsigned = MTYPE_is_unsigned(rtype);
06100   BOOL is_float = MTYPE_is_float(rtype);
06101   BOOL is_double = MTYPE_is_size_double(rtype);
06102   switch (WN_operator(tree)) {
06103   case OPR_DIV:
06104     if (is_float) {
06105 #ifdef TARG_SL
06106       intrinsic = (is_double ? INTRN_FPE_DOUBLE_DIV : INTRN_FPE_FLOAT_DIV);
06107 #else
06108       intrinsic = (is_double ? INTRN_DIVDF3 : INTRN_DIVSF3);
06109 #endif
06110     } else if (is_double) {
06111       intrinsic = (is_unsigned ? INTRN_UDIVDI3 : INTRN_DIVDI3);
06112     } else {
06113       intrinsic = (is_unsigned ? INTRN_UDIVSI3 : INTRN_DIVSI3);
06114     }
06115     break;
06116   case OPR_MOD:
06117     FmtAssert(!is_float, ("Unexpected MOD operator on float"));
06118     // Unsigned MOD is the same as REM.
06119     // Signed MOD is a REM followed by an adjustment which
06120     // uses the divisor, so save it to a temp and replace the
06121     // divisor operand of the tree with a load from the temp.
06122     if (!is_unsigned) {
06123       tmpY = Make_Leaf(block, WN_kid1(tree), type);
06124       WN_kid1(tree) = Load_Leaf(tmpY);
06125     }
06126     /*FALLTHROUGH*/
06127   case OPR_REM:
06128     FmtAssert(!is_float, ("Unexpected REM operator on float"));
06129     if (is_double) {
06130       intrinsic = (is_unsigned ? INTRN_UMODDI3 : INTRN_MODDI3);
06131     } else {
06132       intrinsic = (is_unsigned ? INTRN_UMODSI3 : INTRN_MODSI3);
06133     }
06134     break;
06135   default:
06136     #pragma mips_frequency_hint NEVER
06137     FmtAssert (FALSE, ("Unexpected division operator"));
06138     /*NOTREACHED*/
06139   }
06140   kids[0] = WN_CreateParm (rtype,
06141          lower_expr(block, WN_kid0(tree), actions),
06142          Be_Type_Tbl(rtype),
06143          WN_PARM_BY_VALUE | WN_PARM_READ_ONLY);
06144   kids[1] = WN_CreateParm (rtype, 
06145          lower_expr(block, WN_kid1(tree), actions),
06146          Be_Type_Tbl(rtype),
06147          WN_PARM_BY_VALUE | WN_PARM_READ_ONLY);
06148   iwn = WN_Create_Intrinsic(OPCODE_make_op(OPR_INTRINSIC_OP,
06149              rtype, MTYPE_V),
06150           intrinsic, 2, kids);
06151 
06152   if (WN_operator(tree) == OPR_MOD && !is_unsigned) {
06153     // For signed MOD, we need to add the divisor to the result
06154     // of the REM if both of the operands are negative.
06155     WN *t2, *t3, *t4;
06156     PREG_NUM t1;
06157     t1 = AssignExpr(block, iwn, type);
06158     t2 = WN_Bxor(type, WN_LdidPreg(type, t1), Load_Leaf(tmpY));
06159     t3 = WN_Ashr(type, t2, WN_Intconst(type, MTYPE_size_reg(type) - 1));
06160     t4 = WN_Band(type, Load_Leaf(tmpY), t3);
06161     iwn = WN_Add(type, WN_LdidPreg(type, t1), t4);
06162     iwn = lower_expr(block, iwn, actions);
06163   }
06164 
06165 #ifdef TARG_X8664
06166   if( Action( LOWER_TO_CG ) &&
06167       Action( LOWER_INTRINSIC) ){
06168     BOOL intrinsic_lowered = FALSE;
06169     iwn = lower_emulation( block, iwn, actions, intrinsic_lowered );
06170   }
06171 #endif
06172 
06173   WN_Delete(tree);
06174   return iwn;
06175       }
06176     }
06177 
06178     if (Action(LOWER_COMPLEX) && MTYPE_is_complex(WN_rtype(tree))) {
06179   // complex div creates if-then-else structure,
06180   // so want to expand this early, then just return C*LDID preg here
06181   // (e.g. in case is under a PARM node, and is not first parm).
06182   // Note that fortran fe moves this out from under call, 
06183   // but C doesn't.  Apparently only get here for C PARM case.
06184   TYPE_ID cdiv_mtype = WN_rtype(tree);
06185   // using a preg causes wopt to get confused and not
06186   // connect the F* preg numbers with the C* preg number.
06187   // so use temp symbol instead.
06188   TY_IDX cdiv_ty = MTYPE_To_TY(cdiv_mtype);
06189   ST *cdiv_st = Gen_Temp_Symbol (cdiv_ty, ".complex_div");
06190   WN *stid = WN_Stid(cdiv_mtype, 0, cdiv_st, cdiv_ty, tree);
06191         WN_Set_Linenum (stid, current_srcpos);
06192   stid = lower_store(block, stid, actions);
06193   WN_INSERT_BlockLast(block, stid);
06194   WN *ldid = WN_Ldid(cdiv_mtype, 0, cdiv_st, cdiv_ty);
06195   return ldid;
06196     }
06197     break;
06198 
06199   case OPR_COMMA:
06200     {
06201       WN *commaBlock;
06202       commaBlock = lower_block(WN_kid0(tree), actions);
06203 
06204       DevWarn("lower_expr(): comma operator seen, line %d",
06205         Srcpos_To_Line(current_srcpos));
06206 
06207 #ifdef KEY
06208       // Bug 1268 - copy linenumber when creating WNs.
06209       WN_copy_linenum(tree, commaBlock);
06210 #endif
06211       WN_INSERT_BlockLast(block, commaBlock);
06212     }
06213     return lower_expr(block, WN_kid1(tree), actions);
06214 
06215   case OPR_CSELECT:
06216    /*
06217     *  
06218     */
06219     if (Action(LOWER_SHORTCIRCUIT))
06220     {
06221       /*******************************************************************
06222 
06223       DevWarn("lower_expr(): cselect operator seen, line %d",
06224               Srcpos_To_Line(current_srcpos));
06225       *******************************************************************/
06226 
06227       if (expr_is_speculative(tree))
06228       {
06229   WN *select = WN_Select(type, WN_kid0(tree), WN_kid1(tree),
06230              WN_kid2(tree));
06231   
06232   WN_Delete(tree);
06233   return select;
06234       }
06235       else
06236       {
06237   PREG_NUM  tmpN;
06238   WN *if_tree, *if_then, *if_else, *stid;
06239   WN *body = WN_CreateBlock();
06240 
06241   if_then = WN_CreateBlock();
06242   tmpN = AssignExpr(if_then, WN_kid1(tree), type);
06243 
06244   if_else = WN_CreateBlock();
06245   stid = WN_StidIntoPreg(type, tmpN, MTYPE_To_PREG(type), WN_kid2(tree));
06246   WN_Set_Linenum(stid, current_srcpos);  // Bug 1268
06247   WN_INSERT_BlockLast(if_else, stid);
06248 
06249   if_tree = WN_CreateIf( WN_kid0(tree), if_then, if_else );
06250   if ( Cur_PU_Feedback )
06251     Cur_PU_Feedback->FB_lower_branch( tree, if_tree );
06252   WN_INSERT_BlockLast( block, lower_if( body, if_tree, actions ) );
06253 
06254   return WN_LdidPreg(type, tmpN);
06255       }
06256     }
06257     break;
06258 
06259   case OPR_CAND:
06260   case OPR_CIOR:
06261    /*
06262     *  return boolean 0/1 (build CSELECT)
06263     */
06264     if (Action(LOWER_SHORTCIRCUIT))
06265     {
06266       if (expr_is_speculative(tree))
06267       {
06268   WN *cond;
06269 
06270   if (WN_operator_is(tree, OPR_CAND))
06271     cond = WN_LAND( WN_kid0(tree), WN_kid1(tree));
06272   else
06273     cond = WN_LIOR( WN_kid0(tree), WN_kid1(tree));
06274 
06275   WN_Delete(tree);
06276   return lower_expr(block, cond, actions);
06277       }
06278       else
06279       {
06280   WN *select = WN_Cselect(type,
06281         tree, 
06282         WN_Intconst(Boolean_type, 1),
06283         WN_Intconst(Boolean_type, 0));
06284   return lower_expr(block, select, actions);
06285       }
06286     }
06287     break;
06288 
06289 #ifdef KEY
06290   case OPR_PURE_CALL_OP:
06291     if (Action(LOWER_TO_CG))
06292     {
06293       // create and insert call
06294       WN * call = WN_Create (OPR_CALL,
06295                              WN_rtype (tree),
06296            WN_desc (tree),
06297            WN_kid_count (tree));
06298       WN_st_idx (call) = WN_st_idx (tree);
06299       for (int i=0; i<WN_kid_count (call); i++)
06300         WN_kid (call, i) = WN_kid (tree, i);
06301       WN_Set_Linenum(call, current_srcpos);
06302 
06303       call = lower_call (block, call, actions);
06304       WN_INSERT_BlockLast (block, call);
06305 
06306       // ldid return val
06307       WN * ldid = WN_Ldid (WN_rtype (call), -1, Return_Val_Preg, MTYPE_TO_TY_array[WN_rtype (call)]);
06308       ldid = lower_return_ldid (block, ldid, actions);
06309 
06310       // stid return val into temporary
06311       ST * sym = Gen_Temp_Symbol (WN_ty (ldid), "pure_call_ret");
06312       WN * stid = WN_Stid (WN_rtype (ldid), 0, sym, WN_ty (ldid), ldid);
06313       WN_Set_Linenum(stid, current_srcpos);
06314       stid = lower_store (block, stid, actions);
06315       WN_INSERT_BlockLast (block, stid);
06316 
06317       // ldid val from temporary
06318       ldid = WN_Ldid (WN_desc (stid), 0, sym, WN_ty (ldid));
06319       WN_Delete (tree);
06320 
06321       tree = lower_expr (block, ldid, actions);
06322 
06323     }
06324     break;
06325 #endif
06326   }
06327 
06328 #if defined(TARG_SL) && defined(EMULATE_FLOAT_POINT)
06329   if (Action(LOWER_FP_EMULATE)) {
06330 
06331     TYPE_ID desc = WN_desc(tree);
06332 
06333     switch (WN_operator(tree)) {
06334       case OPR_ADD:
06335       case OPR_SUB:
06336       case OPR_MPY:
06337       case OPR_REM:
06338       case OPR_DIV: 
06339         if (MTYPE_is_float(type)) {
06340           return lower_float_ALU(block, tree, actions);
06341         }
06342         break;
06343 
06344       case OPR_NE:
06345       case OPR_EQ:
06346       case OPR_GE:
06347       case OPR_GT:
06348       case OPR_LE:
06349       case OPR_LT:  
06350         if (MTYPE_is_float(desc)) {
06351           return lower_float_compare(block, tree, actions);
06352         }
06353         break;
06354 
06355      case OPR_NEG:
06356       case OPR_ABS:
06357         /* Expanded in lowering to CG phase */
06358         break;
06359       
06360       case OPR_SQRT:
06361         if (MTYPE_is_float(type)) {
06362           return lower_float_unary(block, tree, actions);
06363         }
06364         break;  
06365 
06366       case OPR_FLOOR:
06367       case OPR_CEIL:
06368       case OPR_TRUNC:
06369       case OPR_RND:
06370       case OPR_CVT:
06371         if ((MTYPE_is_float(type) || MTYPE_is_float(desc))
06372             && (desc != type)) {
06373           return lower_SL_cvt(block, tree, actions);
06374         }
06375     }
06376   }
06377 #endif
06378 
06379   if (Action(LOWER_QUAD))
06380   {
06381     if (WN_desc(tree) == MTYPE_FQ)
06382     {
06383       switch (WN_operator(tree))
06384       {
06385       case OPR_CONST:
06386       case OPR_LDID:
06387       case OPR_ILOAD:
06388   break;
06389       case OPR_EQ:
06390       case OPR_NE:
06391       case OPR_LE:
06392       case OPR_LT:
06393       case OPR_GT:
06394       case OPR_GE:
06395       case OPR_CVT:
06396       case OPR_TRUNC:
06397       case OPR_RND:
06398       case OPR_CEIL:
06399       case OPR_FLOOR:
06400   tree = lower_emulation(block, tree, actions,intrinsic_lowered);
06401   break;
06402       default:
06403   break;
06404       }
06405     }
06406     if (WN_rtype(tree) == MTYPE_FQ)
06407     {
06408       switch (WN_operator(tree))
06409       {
06410       case OPR_CONST:
06411       case OPR_LDID:
06412       case OPR_ILOAD:
06413   break;
06414 
06415       case OPR_SELECT:
06416       case OPR_NEG:
06417       case OPR_ABS:
06418       case OPR_SQRT:
06419       case OPR_ADD:
06420       case OPR_SUB:
06421       case OPR_MPY:
06422       case OPR_DIV:
06423       case OPR_MOD:
06424       case OPR_REM:
06425       case OPR_MAX:
06426       case OPR_MIN:
06427       case OPR_CVT:
06428       case OPR_TRUNC:
06429       case OPR_RND:
06430   tree = lower_emulation(block, tree, actions, intrinsic_lowered);
06431   break;
06432       default:
06433   break;
06434       }
06435     }
06436   }
06437 
06438   if (WN_nary_intrinsic(tree))
06439   {
06440     tree = WN_NaryToExpr(tree);
06441   }
06442 
06443   /* Lower kids if not done already. */
06444   if (! kids_lowered)
06445   {
06446      INT16 i;
06447      for (i = 0; i < WN_kid_count(tree); i++)
06448        WN_kid(tree,i) = lower_expr(block, WN_kid(tree,i), actions);
06449      tree = WN_Simplify_Rebuild_Expr_Tree(tree,alias_manager);
06450   }
06451 
06452   return tree;
06453 }
06454 
06455 
06456 /* ====================================================================
06457  *
06458  *  static TY_IDX coerceTY(TY_IDX type, TYPE_ID btype)
06459  *
06460  * return TY corresponding to the btype
06461  * (type might be pointer -> btype)
06462  *
06463  * ==================================================================== */
06464 
06465 static TY_IDX coerceTY(TY_IDX type, TYPE_ID btype)
06466 {
06467   TY &ty = Ty_Table[type];
06468 
06469   if (TY_is_pointer(ty))
06470     return Make_Pointer_Type(coerceTY(TY_pointed(ty), btype));
06471 
06472   return MTYPE_To_TY(btype);
06473 }
06474 
06475 
06476 
06477 
06478 /* ====================================================================
06479  *
06480  *  static ST * coerceST(const ST *st, TYPE_ID type)
06481  *
06482  * return ST corresponding to the type
06483  *
06484  * ==================================================================== */
06485 
06486 static ST *coerceST(const ST *st, TYPE_ID type)
06487 {
06488   if (ST_class(st) == CLASS_PREG)
06489   {
06490    /*
06491     *  for now, only pregs must correspond to the type
06492     */
06493     return MTYPE_To_PREG(type);
06494   }
06495 
06496   return (ST *) st;
06497 }
06498 
06499 static ST *coerceST(const ST &st, TYPE_ID type)
06500 {
06501   if (ST_class(&st) == CLASS_PREG)
06502   {
06503    /*
06504     *  for now, only pregs must correspond to the type
06505     */
06506     return MTYPE_To_PREG(type);
06507   }
06508 
06509   return (ST *) &st;
06510 }
06511 
06512 
06513 /* ====================================================================
06514  *
06515  * static BOOL WN_StoreIsUnused(WN *tree)
06516  *
06517  * Find if store has been marked by IPA as unused
06518  * This may require traversal of the address expression to find
06519  * an LDA or ARRAY
06520  * ==================================================================== */
06521 static BOOL WN_StoreIsUnused(WN *tree)
06522 {
06523   ST  *sym;
06524 
06525   switch(WN_operator(tree))
06526   {
06527   case OPR_LDA:
06528   case OPR_STID:
06529     sym = WN_st(tree);
06530 
06531     if (ST_class(sym) != CLASS_PREG  &&
06532         ST_class(sym) != CLASS_BLOCK &&
06533   ST_is_not_used(sym))
06534       return TRUE;
06535     break;
06536 
06537   case OPR_ARRAY:
06538     return WN_StoreIsUnused(WN_array_base(tree));
06539   }
06540 
06541   return FALSE;
06542 }
06543 
06544 /* ====================================================================
06545  *
06546  * WN *add_fake_parm(WN *o_call, WN *fake_actual)
06547  *
06548  * Add the fake actual parameter as the first parameter to the original call.
06549  * All original parameters are shifted down by 1.
06550  *
06551  * ==================================================================== */
06552 static WN *add_fake_parm(WN *o_call, WN *fake_actual, TY_IDX ty_idx)
06553 {
06554   WN *n_call;
06555   if (WN_operator(o_call) == OPR_ICALL)
06556     n_call = WN_Icall(MTYPE_V, MTYPE_V, WN_kid_count(o_call)+1, WN_ty(o_call));
06557   else
06558     n_call = WN_generic_call(WN_operator(o_call), MTYPE_V, MTYPE_V, 
06559            WN_kid_count(o_call)+1, WN_st_idx(o_call));
06560   WN_call_flag(n_call) = WN_call_flag(o_call);
06561   WN_Set_Linenum(n_call, WN_Get_Linenum(o_call));
06562   if ( Cur_PU_Feedback ) {
06563     Cur_PU_Feedback->FB_lower_call( o_call, n_call );
06564   }
06565   WN_kid0(n_call) = WN_CreateParm(Pointer_Mtype, fake_actual, ty_idx,
06566             WN_PARM_BY_REFERENCE | WN_PARM_PASSED_NOT_SAVED);
06567   for (INT32 i = 0; i < WN_kid_count(o_call); i++)
06568     WN_kid(n_call, i+1) = WN_COPY_Tree(WN_kid(o_call, i));
06569   return n_call;
06570 }
06571 
06572 /* ====================================================================
06573  *
06574  * WN *lower_return_mstid(WN *block, WN *tree, LOWER_ACTIONS actions)
06575  *
06576  * "tree" must be an MSTID whose kid is MLDID of Return_Val_Preg (-1).
06577  * Perform lowering of MSTID whose rhs is Return_Val_Preg; translate to
06578  * either MSTORE or a sequence of STIDs.
06579  *
06580  * ==================================================================== */
06581 static WN *lower_return_mstid(WN *block, WN *tree, LOWER_ACTIONS actions)
06582 {
06583   ST *preg_st;
06584   WN *n_rhs;
06585   WN *wn = NULL;  // init to prevent upward-exposed use
06586   RETURN_INFO return_info = Get_Return_Info(WN_ty(tree), Complex_Not_Simulated
06587 #ifdef TARG_X8664
06588               , last_call_ff2c_abi
06589 #endif
06590                );
06591   if (RETURN_INFO_return_via_first_arg(return_info)) { // fake first parm
06592     // get the previous MCALL statement
06593     WN *call = WN_last(block);
06594     Is_True(WN_operator(call) == OPR_CALL || WN_operator(call) == OPR_ICALL ||
06595       WN_operator(call) == OPR_PICCALL,
06596       ("statement preceding MMLDID of Return_Val_Preg must be a call"));
06597 #ifndef TARG_X8664
06598     Is_True(WN_rtype(call) == MTYPE_M,
06599       ("call preceding MMLDID of Return_Val_Preg not type M"));
06600 #else
06601     Is_True(WN_rtype(call) == MTYPE_M || MTYPE_is_complex(WN_rtype(call)) ||
06602           MTYPE_is_mmx_vector(WN_rtype(call)),
06603       ("call preceding MMLDID of Return_Val_Preg not type M or complex"));
06604 #endif
06605     WN *awn = WN_CreateLda(OPR_LDA, Pointer_Mtype, MTYPE_V, 
06606          WN_store_offset(tree), 
06607          Make_Pointer_Type(WN_ty(tree)), WN_st_idx(tree));
06608     awn = lower_expr(block, awn, actions);
06609     WN *n_call = add_fake_parm(call, awn, WN_ty(awn));
06610     WN_DELETE_FromBlock(block, call);
06611     WN_INSERT_BlockLast(block, n_call); 
06612 
06613     WN_DELETE_Tree(tree);
06614     return NULL; // original MSTID disappears
06615   }
06616   else { // return via 1 or more return registers
06617     TYPE_ID mtype, desc;
06618     for (INT32 i = 0; i < RETURN_INFO_count(return_info); i++) {
06619       if (i != 0)
06620         WN_INSERT_BlockLast (block, wn); // insert the last STID created 
06621       mtype = RETURN_INFO_mtype(return_info, i);
06622       desc = mtype;
06623 #ifdef KEY
06624       if (MTYPE_byte_size(mtype) > TY_size(WN_ty(tree)) && !MTYPE_float(mtype)){
06625   desc = Mtype_AlignmentClass(1, MTYPE_type_class(mtype));
06626   while (MTYPE_byte_size(desc) < TY_size(WN_ty(tree)))
06627     desc = Mtype_next_alignment(desc);
06628       }
06629 #endif
06630       preg_st = Standard_Preg_For_Mtype(mtype);
06631       n_rhs = WN_CreateLdid(OPR_LDID, mtype, mtype, 
06632           RETURN_INFO_preg(return_info, i), preg_st,
06633           Be_Type_Tbl(mtype));
06634 #ifndef KEY
06635       if (TY_align(ST_type(WN_st(tree))) < MTYPE_alignment(mtype)) {
06636   DevWarn("return_info struct alignment is smaller than register size, may produce wrong results");
06637       }
06638 #endif
06639       wn = WN_CreateStid(OPR_STID, MTYPE_V, desc, 
06640              WN_store_offset(tree)+i*MTYPE_byte_size(mtype),
06641        WN_st_idx(tree), Be_Type_Tbl(desc), n_rhs);
06642       wn  = lower_store (block, wn, actions);
06643       WN_Set_Linenum(wn, current_srcpos);
06644     }
06645     WN_DELETE_Tree(tree);
06646     return wn;
06647   }
06648 }
06649 
06650 /* ====================================================================
06651  *
06652  * WN *lower_return_mistore(WN *block, WN *tree, LOWER_ACTIONS actions)
06653  *
06654  * "tree" must be an MISTORE whose rhs is MLDID of Return_Val_Preg (-1).
06655  * Perform lowering of MISTORE whose rhs is Return_Val_Preg; translate to
06656  * either MSTORE or a sequence of ISTOREs.
06657  *
06658  * ==================================================================== */
06659 static WN *lower_return_mistore(WN *block, WN *tree, LOWER_ACTIONS actions)
06660 {
06661   TYPE_ID mtype;
06662   ST *preg_st;
06663   WN *n_rhs;
06664   WN *wn = NULL;  // init to prevent upward-exposed use
06665   RETURN_INFO return_info = Get_Return_Info(WN_ty(tree), Complex_Not_Simulated
06666 #ifdef TARG_X8664
06667               , last_call_ff2c_abi
06668 #endif
06669              );
06670   if (RETURN_INFO_return_via_first_arg(return_info)) { // fake first parm
06671     // get the previous MCALL statement
06672     WN *call = WN_last(block);
06673     Is_True(WN_operator(call) == OPR_CALL || WN_operator(call) == OPR_ICALL ||
06674       WN_operator(call) == OPR_PICCALL,
06675       ("statement preceding MMLDID of Return_Val_Preg must be a call"));
06676 #ifndef TARG_X8664
06677     Is_True(WN_rtype(call) == MTYPE_M,
06678       ("call preceding MMLDID of Return_Val_Preg not type M"));
06679 #else
06680     Is_True(WN_rtype(call) == MTYPE_M || MTYPE_is_mmx_vector(WN_rtype(call)),
06681       ("call preceding MMLDID of Return_Val_Preg not type M"));
06682 #endif
06683     WN *awn = WN_COPY_Tree(WN_kid1(tree));
06684     if (WN_store_offset(tree) != 0) { // generate an ADD node for the offset
06685       WN *iwn = WN_CreateIntconst(OPR_INTCONST, Pointer_Mtype, MTYPE_V, 
06686           WN_store_offset(tree));
06687       awn = WN_CreateExp2(OPR_ADD, Pointer_Mtype, Pointer_Mtype, awn, iwn);
06688     }
06689     awn = lower_expr(block, awn, actions);
06690     WN *n_call = add_fake_parm(call, awn, WN_ty(tree));
06691     WN_DELETE_FromBlock(block, call);
06692     WN_INSERT_BlockLast(block, n_call); 
06693 
06694     WN_DELETE_Tree(tree);
06695     return NULL; // original MSTID disappears
06696   }
06697   else { // return via 1 or more return registers
06698     WN *base_expr;
06699     for (INT32 i = 0; i < RETURN_INFO_count(return_info); i++) {
06700       if (i != 0)
06701         WN_INSERT_BlockLast (block, wn); // insert the last STID created 
06702       mtype = RETURN_INFO_mtype(return_info, i);
06703       preg_st = Standard_Preg_For_Mtype(mtype);
06704       n_rhs = WN_CreateLdid(OPR_LDID, mtype, mtype, 
06705           RETURN_INFO_preg(return_info, i), preg_st,
06706           Be_Type_Tbl(mtype));
06707       base_expr = WN_COPY_Tree(WN_kid1(tree));
06708 // OSP-438: The type of Istore node should be a pointer to mtype.
06709 // (Previously, we just use Be_Type_Tbl(mtype) as the type of Istore).
06710       wn = WN_CreateIstore(OPR_ISTORE, MTYPE_V, mtype, 
06711                WN_store_offset(tree)+i*MTYPE_byte_size(mtype),
06712          Make_Pointer_Type(Be_Type_Tbl(mtype), FALSE), n_rhs, base_expr);
06713       WN_Set_Linenum(wn, WN_Get_Linenum(tree));
06714       wn  = lower_store (block, wn, actions);
06715       WN_Set_Linenum (wn, WN_Get_Linenum(tree));
06716     }
06717     WN_DELETE_Tree(tree);
06718     return wn;
06719   }
06720 }
06721 
06722 #ifdef TARG_NVISA
06723 // lower struct copy of asm output, which goes downward from negative preg,
06724 // into sequence of ldid/stid. 
06725 static WN *lower_asm_mstid(WN *block, WN *tree, LOWER_ACTIONS actions)
06726 {
06727   WN *wn;
06728   WN *ldid;
06729   INT field_id = 0;
06730   TY_IDX vty = WN_ty(tree);
06731   FmtAssert(TY_can_be_vector(vty), ("not a vector type"));
06732   TY_IDX ety = TY_vector_elem_ty(vty);
06733   PREG_NUM pnum = WN_load_offset(WN_kid0(tree)); // asm out preg
06734   for (INT i = 0; i < TY_vector_count(vty); ++i) {
06735       ldid = WN_CreateLdid(OPR_LDID, TY_mtype(ety), TY_mtype(ety), 
06736     /* asm out pregs count downward */
06737     pnum - i, 
06738     MTYPE_To_PREG(TY_mtype(ety)), ety);
06739       ++field_id;
06740       wn = WN_CreateStid( OPR_STID, MTYPE_V, TY_mtype(ety),
06741     /* increment by size of element */
06742     i * MTYPE_byte_size(TY_mtype(ety)), 
06743     WN_st(tree), vty, ldid, field_id);
06744       wn  = lower_store (block, wn, actions);
06745       WN_Set_Linenum (wn, WN_Get_Linenum(tree));
06746       WN_INSERT_BlockLast (block, wn); // insert the last STID created 
06747   }
06748   WN_DELETE_Tree(tree);
06749   return NULL; // original MSTID disappears
06750 }
06751 #endif // TARG_NVISA
06752 
06753 /* ====================================================================
06754  *
06755  * WN *lower_mstid(WN *block, WN *tree, LOWER_ACTIONS actions)
06756  *
06757  * Perform lowering (see WN_Lower description) on MSTID nodes returning
06758  * an equivalent MSTORE node.
06759  *
06760  * ==================================================================== */
06761 
06762 static WN *lower_mstid(WN *block, WN *tree, LOWER_ACTIONS actions)
06763 {
06764   TY_IDX ty_idx  = WN_ty(tree);
06765   TY_IDX pty_idx;
06766   UINT64 size    = WN_field_id(tree) == 0 ?
06767       TY_size(ty_idx):
06768       TY_size(get_field_type (ty_idx, WN_field_id(tree)));
06769   WN*    wn;
06770   WN*    awn;
06771   WN*    swn;
06772 
06773   Is_True((WN_operator(tree) == OPR_STID && WN_desc(tree) == MTYPE_M),
06774     ("expected mstid node, not %s", OPCODE_name(WN_opcode(tree))));
06775 
06776   pty_idx = Make_Pointer_Type (ty_idx, FALSE);
06777 
06778   WN *rhs = WN_kid0(tree);
06779   if (WN_opcode(rhs) == OPC_MMLDID && WN_st(rhs) == Return_Val_Preg) {
06780     // handle lowering of MLDID of Return_Val_Preg followed by MSTID
06781     Is_True(Action(LOWER_RETURN_VAL),
06782       ("LOWER_RETURN_VAL action must be specified"));
06783     return lower_return_mstid(block, tree, actions);
06784   }
06785 
06786 #ifdef KEY
06787   // Don't do struct copy if src and dest are the same.
06788   if (WN_opcode(rhs) == OPC_MMLDID &&
06789       WN_st(rhs) == WN_st(tree) &&
06790       WN_load_offset(rhs) == WN_store_offset(tree)) {
06791     WN_Delete(tree);
06792     return NULL;
06793   }
06794 #endif
06795 
06796   awn = WN_CreateLda (OPR_LDA, Pointer_Mtype, MTYPE_V, WN_store_offset(tree),
06797           pty_idx, WN_st(tree));
06798   swn = WN_CreateIntconst (OPC_U4INTCONST, size);
06799   wn  = WN_CreateMstore (0, pty_idx, WN_kid0(tree), awn, swn);
06800   WN_Set_Linenum(wn, current_srcpos);
06801   WN_set_field_id(wn, WN_field_id(tree));
06802   wn  = lower_store (block, wn, actions);
06803 
06804   WN_Delete(tree);
06805   return wn;
06806 }
06807 
06808 
06809 /* ====================================================================
06810  *
06811  * WN *lower_mistore(WN *block, WN *tree, LOWER_ACTIONS actions)
06812  *
06813  * Perform lowering (see WN_Lower description) on MISTORE nodes returning
06814  * an equivalent MSTORE node.
06815  *
06816  * ==================================================================== */
06817 
06818 static WN *lower_mistore(WN *block, WN *tree, LOWER_ACTIONS actions)
06819 {
06820   TY_IDX pty_idx  = WN_ty(tree);
06821   TY_IDX ty_idx  = TY_pointed(pty_idx);
06822 
06823   if (WN_field_id (tree) != 0)
06824     ty_idx = get_field_type (ty_idx, WN_field_id (tree));
06825   
06826   UINT64 size    = TY_size(Ty_Table[ty_idx]);
06827   WN*    wn;
06828   WN*    swn;
06829 
06830   Is_True((WN_operator(tree) == OPR_ISTORE && WN_desc(tree) == MTYPE_M),
06831     ("expected mistore node, not %s", OPCODE_name(WN_opcode(tree))));
06832   Is_True(TY_kind(pty_idx) == KIND_POINTER,
06833     ("type specified in MISTORE not pointer"));
06834 //Is_True(size > 0, ("type in MISTORE cannot be zero size"));
06835   if (size == 0)
06836     DevWarn ("type in MISTORE cannot be zero size");
06837   WN *rhs = WN_kid0(tree);
06838   if (WN_opcode(rhs) == OPC_MMLDID && WN_st(rhs) == Return_Val_Preg) {
06839     // handle lowering of MLDID of Return_Val_Preg followed by MISTORE
06840     Is_True(Action(LOWER_RETURN_VAL),
06841       ("LOWER_RETURN_VAL action must be specified"));
06842     return lower_return_mistore(block, tree, actions);
06843   }
06844 
06845   swn = WN_CreateIntconst(OPC_U4INTCONST, size);
06846   WN* kid0 = WN_COPY_Tree(WN_kid0(tree));
06847   WN* kid1 = WN_COPY_Tree(WN_kid1(tree));
06848   wn  = WN_CreateMstore(WN_offset(tree), pty_idx, kid0, kid1, swn);
06849 
06850   WN_Set_Linenum(wn, current_srcpos);
06851   WN_set_field_id(wn, WN_field_id(tree));
06852   set_original_wn (wn, tree);
06853   set_original_wn (kid0, WN_kid0(tree));
06854   wn  = lower_store(block, wn, actions);
06855 
06856   set_original_wn (wn, NULL); // avoid dangling pointer
06857   set_original_wn (WN_kid0(wn), NULL);
06858   WN_DELETE_Tree (tree);
06859   return wn;
06860 }
06861 
06862 
06863 #ifdef KEY
06864 static BOOL Equiv (WN* wn1, WN* wn2) {
06865   if (!WN_Equiv(wn1,wn2)) return(FALSE);
06866   for (INT kidno=0; kidno<WN_kid_count(wn1); kidno++) {
06867     if (!Equiv(WN_kid(wn1,kidno),WN_kid(wn2,kidno))) {
06868       return(FALSE);
06869     }
06870   }
06871   return(TRUE);
06872 }
06873 #endif
06874 
06875 #ifdef KEY // bug 12787
06876 /* ====================================================================
06877  * walk expr looking for an INTRINSIC_OP that will become a function call;
06878  * return TRUE if found.
06879    ==================================================================== */
06880 static BOOL has_call(WN *expr)
06881 {
06882   if (WN_operator(expr) == OPR_INTRINSIC_OP &&
06883       ! INTRN_cg_intrinsic(WN_intrinsic(expr)))
06884     return TRUE;
06885   for (INT i = 0; i < WN_kid_count(expr); i++) {
06886     if (has_call(WN_kid(expr, i)))
06887       return TRUE;
06888   }
06889   return FALSE;
06890 }
06891 #endif
06892 
06893 static BOOL Is_small_struct(WN* wn)
06894 {
06895   Is_True((WN_opcode(WN_kid0(wn)) == OPC_MMILOAD || 
06896      WN_opcode(WN_kid0(wn)) == OPC_MMLDID), ("Expected M type loads"));
06897 
06898   if (TY_kind(WN_ty(WN_kid0(wn))) != KIND_STRUCT)
06899     return FALSE;
06900 
06901   if (TY_size(Ty_Table[WN_ty(WN_kid0(wn))]) < (Copy_Quantum_Ratio() * Pointer_Size +1)) {
06902       return TRUE;
06903   }
06904   return FALSE;
06905 }
06906 
06907 
06908 /* ====================================================================
06909  *
06910  * WN *lower_store(block, WN *tree, LOWER_ACTIONS actions)
06911  *
06912  * Perform lowering (see WN_Lower description) on store statement <tree>,
06913  * returning lowered tree.
06914  *
06915  * ==================================================================== */
06916 
06917 static WN *lower_store(WN *block, WN *tree, LOWER_ACTIONS actions)
06918 {
06919   BOOL kids_lowered = FALSE;  /* becomes TRUE when kids are lowered */
06920 
06921   Is_True(OPCODE_is_store(WN_opcode(tree)),
06922     ("expected store node, not %s", OPCODE_name(WN_opcode(tree))));
06923 
06924   /* If the store is to memory and the expression begins with a TAS, try to
06925    * replace with a store matching the result type of the TAS's expression.
06926    * Doing so may avoid a move from one register set to another.
06927    */
06928   if (Action(LOWER_TO_CG))
06929   {
06930     WN *tas = WN_kid0(tree);
06931     if (   WN_operator(tas) == OPR_TAS
06932   && (!WN_has_sym(tree) || WN_class(tree) != CLASS_PREG))
06933     {
06934       WN *tas_kid0 = WN_kid0(tas);
06935       TYPE_ID tas_kid0_rtype = WN_rtype(tas_kid0);
06936       if (MTYPE_byte_size(WN_rtype(tas)) == MTYPE_byte_size(tas_kid0_rtype)) {
06937   WN_set_desc(tree, tas_kid0_rtype);
06938   WN_kid0(tree) = tas_kid0;
06939   WN_Delete(tas);
06940       }
06941     }
06942   }
06943 
06944 #if defined(KEY) && !defined(TARG_SL) // bug 11938
06945   // If OPT_Float_Via_Int is on, and both rhs and lhs are indirect memory ops,
06946   // change to use integer type for the copy
06947   if (Action(LOWER_TO_CG) && OPT_Float_Via_Int && ! WN_has_sym(tree)) {
06948     WN *rhs = WN_kid0(tree);
06949     if (MTYPE_is_float(WN_rtype(rhs)) && MTYPE_byte_size(WN_rtype(rhs)) <= 8 &&
06950         OPERATOR_is_load(WN_operator(rhs)) && ! WN_has_sym(rhs)) {
06951       TYPE_ID newtyp = Mtype_TransferSize(WN_rtype(rhs), MTYPE_I4);
06952       WN_set_rtype(rhs, newtyp);
06953       WN_set_desc(rhs, newtyp);
06954       WN_set_desc(tree, newtyp);
06955     }
06956   }
06957 #endif
06958 
06959 #ifdef TARG_X8664 // bug 11800
06960   // If the store is to memory and the expression is a load from memory, both
06961   // of MMX vector type, change to use integer types so it does not need to
06962   // involve MMX registers
06963   if (Action(LOWER_TO_CG) || Action(LOWER_BIT_FIELD_ID)) {
06964     WN *rhs = WN_kid0(tree);
06965     if (MTYPE_is_mmx_vector(WN_rtype(rhs)) &&
06966         OPERATOR_is_load(WN_operator(rhs))) {
06967       if (! (WN_has_sym(rhs) && WN_class(rhs) == CLASS_PREG) &&
06968           ! (WN_has_sym(tree) && WN_class(tree) == CLASS_PREG)) {
06969         TYPE_ID newtyp = Mtype_TransferSize(WN_rtype(rhs), MTYPE_I4);
06970         WN_set_rtype(rhs, newtyp);
06971         WN_set_desc(rhs, newtyp);
06972         WN_set_desc(tree, newtyp);
06973       }
06974     }
06975   }
06976 #endif
06977 
06978 
06979   /*
06980    * create any maps that need to be present
06981    */
06982   lower_map(tree, actions);
06983 
06984 
06985   /* Note: We must split constant offsets after lowering complex stores
06986    * and splitting symbol addresses since these may create new offsets
06987    * that need to be split.
06988    */
06989   
06990   switch (WN_operator(tree))
06991   {
06992   case OPR_ISTORE:
06993     if (Action(LOWER_TO_MEMLIB) && WN_operator(tree) == OPR_ISTORE) {
06994         tree = Lower_Mistore_Memlib(block,tree,actions);
06995         if (tree == NULL || WN_operator(tree)!=OPR_ISTORE) 
06996            return tree; //otherwise continue
06997     } 
06998     if (WN_StoreIsUnused(WN_kid1(tree)))
06999     {
07000       WN  *eval;
07001 
07002       eval = lower_eval(block, WN_CreateEval(WN_kid0(tree)), actions);
07003 
07004       WN_Delete(tree);
07005 
07006       return eval;
07007     }
07008 
07009     if (Action(LOWER_MLDID_MSTID) && WN_desc(tree) == MTYPE_M)
07010       return lower_mistore(block, tree, actions);
07011 
07012     if (Action(LOWER_EARLY_MLOAD) && WN_desc(tree) == MTYPE_M){
07013       if ((WN_opcode(WN_kid0(tree)) == OPC_MMLDID || WN_opcode(WN_kid0(tree)) == OPC_MMILOAD) && Is_small_struct(tree)) {
07014   WN *return_block = lower_mistore_by_type(block, tree, actions);
07015   if (return_block) return return_block;
07016       }
07017     }
07018 
07019     if (Action(LOWER_RETURN_VAL) && WN_desc(tree) == MTYPE_M &&
07020        WN_opcode(WN_kid0(tree)) == OPC_MMLDID && 
07021        WN_st(WN_kid0(tree)) == Return_Val_Preg) {
07022        return lower_return_mistore(block, tree, actions);
07023     }
07024 #ifdef TARG_X8664 // MMX vector return type also uses fake parameters (bug 7733)
07025     if (Action(LOWER_RETURN_VAL) && MTYPE_is_mmx_vector(WN_desc(tree)) &&
07026         WN_operator(WN_kid0(tree)) == OPR_LDID && 
07027         WN_st(WN_kid0(tree)) == Return_Val_Preg) {
07028        return lower_return_mistore(block, tree, actions);
07029     }
07030 #endif
07031 
07032 
07033     if (Action(LOWER_BIT_FIELD_ID) && WN_desc(tree) == MTYPE_BS) {
07034       lower_bit_field_id(tree);
07035       if (Action(LOWER_BITS_OP) && WN_operator (tree) == OPR_ISTBITS)
07036   return lower_store_bits (block, tree, actions);
07037     }
07038 
07039     if (Action(LOWER_COMPLEX) && MTYPE_is_complex(WN_desc(tree)))
07040     {
07041       WN  *realstore, *imagstore;
07042       LEAF  realexpN, imagexpN;
07043       WN_OFFSET offset = WN_store_offset(tree);
07044       TYPE_ID realTY = Mtype_complex_to_real( WN_desc(tree));
07045       {
07046        /*
07047   * create the real/imaginary stores
07048   * load the temporary values into a preg before the store (pv314583)
07049   * as the store may interfere with the expression.
07050   */
07051   WN  *realexp, *imagexp;
07052 
07053   lower_complex_expr(block, WN_kid0(tree), actions, &realexp, &imagexp);
07054   
07055   realexpN = Make_Leaf(block, realexp, realTY);
07056   imagexpN = Make_Leaf(block, imagexp, realTY);
07057       }
07058 
07059       if (Action(LOWER_BASE_INDEX))
07060       {
07061   WN  *base, *index, *addr;
07062   LEAF  indexN;
07063 
07064   base = index= NULL;
07065   lower_to_base_index(WN_kid1(tree), &base, &index) ;
07066 
07067   base = lower_expr(block, base, actions);
07068   index = lower_expr(block, index, actions);
07069 
07070   indexN = Make_Leaf(block, index, Pointer_type);
07071 
07072   addr = WN_Add(Pointer_type,
07073           Load_Leaf(indexN),
07074           lower_copy_tree(base, actions));
07075 
07076   realstore = WN_Istore(realTY,
07077             offset,
07078             coerceTY(WN_ty(tree), realTY),
07079             addr,
07080             Load_Leaf(realexpN));
07081 
07082   addr = WN_Add(Pointer_type, Load_Leaf(indexN), base);
07083 
07084   imagstore = WN_Istore(realTY,
07085             coerceOFFSET(tree, realTY, offset),
07086             coerceTY(WN_ty(tree), realTY),
07087             addr,
07088             Load_Leaf(imagexpN));
07089       }
07090       else
07091       {
07092   WN  *addr;
07093         LEAF  addrN;
07094 
07095   addr = lower_expr(block, WN_kid1(tree), actions);
07096   addrN = Make_Leaf(block, addr, Pointer_type);
07097 
07098         realstore =  WN_Istore(realTY,
07099              offset,
07100              coerceTY(WN_ty(tree), realTY),
07101              Load_Leaf(addrN),
07102              Load_Leaf(realexpN));
07103 
07104         imagstore =  WN_Istore(realTY,
07105              coerceOFFSET(tree, realTY, offset),
07106              coerceTY(WN_ty(tree), realTY),
07107              Load_Leaf(addrN),
07108              Load_Leaf(imagexpN));
07109       }
07110       realstore = lower_store(block, realstore, actions);
07111       WN_Set_Linenum (realstore, WN_Get_Linenum(tree));
07112       WN_INSERT_BlockLast(block, realstore);
07113 
07114       imagstore = lower_store(block, imagstore, actions);
07115       lower_complex_maps(tree, realstore, imagstore, actions);
07116       WN_Delete(tree);
07117 
07118       return imagstore;
07119     }
07120     else if (Action(LOWER_QUAD) && MTYPE_is_quad(WN_desc(tree)))
07121     {
07122       WN  *hi, *lo, *hipart, *lopart;
07123       TYPE_ID realTY = MTYPE_F8;
07124       WN_OFFSET offset = WN_load_offset(tree);
07125 
07126       lower_quad_expr(block, WN_kid0(tree), actions, &hi, &lo);
07127 
07128       if (Action(