00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046 #define __STDC_LIMIT_MACROS
00047 #include <stdint.h>
00048 #ifdef USE_PCH
00049 #include "be_com_pch.h"
00050 #endif
00051 #pragma hdrstop
00052 #if defined(BUILD_OS_DARWIN)
00053 #include <limits.h>
00054 #else
00055 #include <values.h>
00056 #endif
00057 #include <isam.h>
00058 #include <alloca.h>
00059 #ifdef __MINGW32__
00060 #include <signal.h>
00061 #else
00062 #include <sys/signal.h>
00063 #endif
00064 #if defined(BUILD_OS_DARWIN)
00065 #include <darwin_elf.h>
00066 #else
00067 #include <elf.h>
00068 #endif
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"
00114 #include "targ_const_private.h"
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
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
00142 #include "pragma_weak.h"
00143
00144
00145
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
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
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
00202 #define MAX_LOOP_NEST_DEPTH 150
00203
00204
00205
00206
00207
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;
00212 #endif
00213
00214
00215
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
00291 static WN* get_original_wn (WN* derived);
00292 static void set_original_wn (WN* derived, WN* orig);
00293
00294
00295
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
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
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,
00371 MTYPE_UNKNOWN,
00372 MTYPE_I4,
00373 MTYPE_I4,
00374 MTYPE_I4,
00375 MTYPE_I8,
00376 MTYPE_U4,
00377 MTYPE_U4,
00378 MTYPE_U4,
00379 MTYPE_U8,
00380 MTYPE_F4,
00381 MTYPE_F8,
00382 #ifdef TARG_IA64
00383 MTYPE_F10,
00384 #else
00385 MTYPE_UNKNOWN,
00386 #endif
00387 MTYPE_UNKNOWN,
00388 MTYPE_UNKNOWN,
00389 MTYPE_FQ,
00390 MTYPE_M,
00391 MTYPE_C4,
00392 MTYPE_C8,
00393 MTYPE_CQ,
00394 MTYPE_V
00395 #ifdef KEY
00396 ,MTYPE_UNKNOWN,
00397 MTYPE_UNKNOWN,
00398 MTYPE_UNKNOWN,
00399 #ifdef TARG_IA64
00400 MTYPE_C10,
00401 #else
00402 MTYPE_UNKNOWN,
00403 #endif
00404 MTYPE_UNKNOWN,
00405 MTYPE_UNKNOWN,
00406 MTYPE_UNKNOWN,
00407 #if defined(TARG_X8664) || defined(VECTOR_MTYPES)
00408 MTYPE_V16C4,
00409 MTYPE_V16C8,
00410 MTYPE_V16I1,
00411 MTYPE_V16I2,
00412 MTYPE_V16I4,
00413 MTYPE_V16I8,
00414 MTYPE_V16F4,
00415 MTYPE_V16F8,
00416 MTYPE_V8I1,
00417 MTYPE_V8I2,
00418 MTYPE_V8I4,
00419 MTYPE_V8F4,
00420 #if defined(TARG_X8664)
00421 MTYPE_M8I1,
00422 MTYPE_M8I2,
00423 MTYPE_M8I4,
00424 MTYPE_M8F4
00425 #endif // TARG_X8664
00426 #endif // (TARG_X8664) || (VECTOR_MTYPES)
00427 #endif // KEY
00428 };
00429
00430
00431
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
00473
00474
00475
00476
00477
00478
00479
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
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
00531
00532
00533
00534
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
00553
00554
00555
00556 extern WN *WN_I1const(TYPE_ID type, INT64 con)
00557 {
00558
00559
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
00580
00581
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
00629
00630
00631
00632
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
00662
00663
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
00684
00685
00686
00687
00688
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
00709
00710
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
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
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
00807
00808
00809
00810 if( Run_ipl ){
00811 return label;
00812 }
00813 #endif
00814
00815
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
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
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
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
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
00974
00975
00976
00977
00978
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
01054
01055
01056
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
01104
01105
01106
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
01130
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
01170
01171
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
01286
01287
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
01324
01325
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
01382
01383
01384
01385
01386
01387
01388
01389
01390
01391
01392
01393
01394
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
01411
01412
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
01433
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
01483
01484
01485
01486
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
01498
01499
01500
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
01548
01549
01550
01551
01552
01553
01554
01555
01556
01557
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
01599
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
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
01629
01630
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
01737
01738
01739
01740
01741
01742
01743
01744
01745
01746
01747
01748
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
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
01852 *base = add_to_base(base, addr);
01853 *index = add_to_base(index, WN_Zerocon(WN_rtype(addr)));
01854 }
01855 break;
01856 default:
01857
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
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
01882
01883
01884
01885
01886
01887
01888
01889
01890
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
01920
01921
01922
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
01938 }
01939
01940
01941
01942
01943
01944
01945
01946
01947
01948
01949
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
01971
01972
01973
01974
01975
01976
01977
01978
01979
01980 switch (WN_operator(tree))
01981 {
01982 case OPR_LDID:
01983 {
01984
01985
01986
01987
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
02020
02021
02022
02023
02024
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
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
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
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
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
02158
02159
02160
02161 *realpart = lower_expr(block, WN_kid0(tree), actions);
02162 *imagpart = lower_expr(block, WN_kid1(tree), actions);
02163
02164
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
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
02197
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
02237
02238
02239
02240
02241
02242 LEAF rzN, izN;
02243 {
02244
02245
02246
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
02260
02261
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
02280
02281
02282
02283
02284
02285
02286
02287
02288
02289
02290
02291
02292
02293
02294
02295
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
02315
02316
02317
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
02337
02338
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
02363
02364
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);
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);
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
02408
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
02425
02426
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
02461
02462
02463
02464
02465
02466
02467
02468
02469
02470
02471
02472
02473
02474
02475
02476
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
02494
02495
02496
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
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
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
02558
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);
02568 WN_INSERT_BlockLast(if_else, stid);
02569 }
02570 {
02571
02572
02573
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);
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
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
02638
02639
02640
02641
02642
02643
02644
02645
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
02689
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
02706
02707
02708
02709
02710 tree = lower_expr(block, tree, actions);
02711
02712 switch (WN_operator(tree))
02713 {
02714 case OPR_LDID:
02715 {
02716
02717
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
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
02818
02819
02820
02821
02822
02823
02824
02825
02826
02827
02828
02829
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
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
02898 do_reassociate |= ( WN_class(idv) == CLASS_PREG );
02899
02900
02901
02902 }
02903 }
02904
02905 if( !do_reassociate ){
02906 result = WN_Coerce(rtype, WN_array_index(tree, n-1));
02907 }
02908 #else
02909
02910
02911
02912 result = WN_Coerce(rtype, WN_array_index(tree, n-1));
02913 #endif
02914
02915
02916
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
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
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);
02974
02975 return result;
02976 }
02977
02978
02979
02980
02981
02982
02983
02984
02985
02986
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
02997
02998
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
03014
03015
03016 srcNo = Make_Leaf(block, expr, src);
03017
03018
03019
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
03033
03034
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
03058
03059
03060
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
03073 if (dst == MTYPE_U4) {
03074 r = WN_Cvt(MTYPE_I8,dst,WN_Trunc(src,MTYPE_I8,expr));
03075 } else if (src==MTYPE_FQ) {
03076
03077
03078
03079
03080
03081
03082 srcNo = Make_Leaf(block, expr, src);
03083
03084
03085
03086
03087
03088
03089
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
03111
03112
03113 srcNo = Make_Leaf(block, expr, src);
03114
03115
03116
03117
03118
03119
03120
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
03146
03147
03148
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
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
03201
03202
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
03222
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
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
03313
03314
03315
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
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
03455
03456
03457
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
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
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
03515
03516
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
03542
03543
03544
03545
03546
03547
03548 static WN *lower_one_madd_tree_height(WN *block, WN *wn)
03549 {
03550
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
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
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
03594
03595 if (count == 0) {
03596 segments[idx++] = this_wn;
03597 }
03598
03599
03600 WN *tree = sum_madd_segments(segments, 0, idx - 1);
03601 return tree;
03602 }
03603
03604
03605
03606
03607
03608
03609
03610
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
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
03638
03639
03640
03641
03642
03643
03644
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
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
03712
03713
03714
03715
03716
03717
03718
03719
03720
03721
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
03741
03742
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
03755
03756
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
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
03780
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
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
03828
03829
03830 if (base != sym)
03831 {
03832 base = sym;
03833 }
03834 break;
03835
03836 case SCLASS_FORMAL:
03837
03838
03839
03840
03841 return NULL;
03842
03843 case SCLASS_AUTO:
03844
03845
03846
03847
03848
03849
03850
03851
03852
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
03863
03864
03865 if (ST_is_weak_symbol(sym))
03866 return NULL;
03867 break;
03868
03869 case SCLASS_COMMON:
03870
03871
03872
03873
03874
03875
03876
03877
03878
03879
03880
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
03891
03892
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
03924
03925
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
03951
03952
03953
03954
03955
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
03994
03995
03996
03997
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
04011
04012
04013
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
04022
04023
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
04032
04033
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
04049
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 }
04079
04080
04081
04082
04083
04084
04085
04086
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
04100
04101
04102
04103
04104
04105
04106
04107
04108
04109
04110
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
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
04144
04145
04146
04147
04148
04149
04150
04151
04152
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
04178
04179
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
04197
04198
04199
04200
04201 if (WN_field_id (tree) != 0)
04202 lower_field_id (tree);
04203
04204 wn = WN_Istore(WN_desc(tree),
04205 offset,
04206
04207
04208
04209
04210
04211
04212
04213
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
04242
04243
04244
04245
04246
04247
04248
04249
04250
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
04265
04266
04267
04268
04269
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
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
04301
04302
04303
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
04312
04313
04314
04315
04316 deref = WN_Istore(WN_desc(tree), offset, addr_ty, addr, WN_kid0(tree)
04317 #ifdef KEY
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
04334
04335
04336
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;
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
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
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
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
04462 default:
04463 Fail_FmtAssertion ("Unexpected type in lower_return_ldid");
04464
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
04482
04483
04484
04485
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
04519
04520
04521
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
04551
04552
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 }
04612
04613
04614
04615
04616
04617
04618
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
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
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
04668 if (shift > 0)
04669 new_value = WN_Shl (cmp_type, new_value, WN_Intconst (cmp_type, shift));
04670
04671
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 }
04680
04681 #if 0
04682
04683
04684
04685
04686
04687
04688
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
04708
04709
04710
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
04744
04745
04746
04747
04748
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 {
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
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
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 &&
04825 #ifdef KEY
04826 bsize &&
04827 #endif
04828 (bytes_accessed * 8 % bsize) == 0 &&
04829 #ifdef TARG_X8664
04830 (bofst & 7) == 0
04831 #else
04832 (bofst % bsize) == 0
04833 #endif
04834 ) {
04835
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 {
04842 #if defined(TARG_MIPS) || defined(TARG_IA32)
04843 if ((indirect || WN_class(wn) != CLASS_PREG) &&
04844 bofst % 8 == 0 &&
04845 compute_offset_alignment(bytes_accessed*8, bofst) >= bsize) {
04846
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
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
04895
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)
04903 con = WN_Intconst(MTYPE_byte_size(type)==4 ? MTYPE_U4 : MTYPE_U8, 0);
04904 else if (MTYPE_byte_size(type) == 4)
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;
04915
04916 #ifdef KEY
04917 ST *sym = &St_Table[sym_idx];
04918 mstore = WN_CreateMstore(0,
04919 pty_idx,
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);
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
04986
04987
04988
04989
04990
04991
04992
04993
04994
04995
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
05014
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);
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);
05169 }
05170
05171 static INTRINSIC SL_CVT_Intrinsic[6][6] =
05172 {
05173
05174 {INTRINSIC_NONE, INTRINSIC_NONE, INTRINSIC_NONE, INTRINSIC_NONE, INTRN_FPE_INT32_TO_FLOAT, INTRN_FPE_INT32_TO_DOUBLE},
05175 {INTRINSIC_NONE, INTRINSIC_NONE, INTRINSIC_NONE, INTRINSIC_NONE, INTRN_FPE_UINT32_TO_FLOAT, INTRN_FPE_UINT32_TO_DOUBLE},
05176 {INTRINSIC_NONE, INTRINSIC_NONE, INTRINSIC_NONE, INTRINSIC_NONE, INTRN_LLE_LL_TO_FLOAT, INTRN_LLE_LL_TO_DOUBLE},
05177 {INTRINSIC_NONE, INTRINSIC_NONE, INTRINSIC_NONE, INTRINSIC_NONE, INTRN_LLE_ULL_TO_FLOAT, INTRN_LLE_ULL_TO_DOUBLE},
05178 {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 {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);
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
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);
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);
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);
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
05305
05306
05307
05308
05309
05310
05311 static WN *lower_expr(WN *block, WN *tree, LOWER_ACTIONS actions)
05312 {
05313 BOOL kids_lowered = FALSE;
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
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
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
05349
05350
05351
05352 switch (WN_operator(tree))
05353 {
05354 #if defined(TARG_SL) && defined(EMULATE_LONGLONG)
05355 case OPR_LSHR:
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)
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
05405
05406
05407
05408 if( Is_Target_32bit() )
05409 break;
05410
05411
05412
05413
05414
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 ) {
05424 WN * old = tree;
05425 WN * parm = WN_kid0 (WN_kid0 (old));
05426
05427
05428
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
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
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
05483
05484
05485
05486
05487
05488
05489
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
05510
05511
05512
05513
05514
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 }
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
05555
05556
05557
05558
05559
05560
05561
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
05577
05578
05579
05580
05581
05582
05583 WN *kid = WN_kid0(tree);
05584
05585 #ifdef TARG_MIPS
05586
05587
05588
05589
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
05601
05602
05603
05604
05605
05606
05607
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
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
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
05709
05710
05711
05712
05713
05714
05715
05716
05717
05718
05719
05720
05721
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
05747
05748 {
05749 ST *sym = WN_st(tree);
05750
05751
05752
05753
05754
05755
05756
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
05802
05803
05804
05805
05806
05807
05808
05809
05810
05811
05812
05813
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
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);
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
05856
05857
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
05902
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
05922
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
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
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
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
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);
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
06031
06032
06033
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
06051 || WN_kid_count(tree) < 2
06052 #endif
06053 )
06054 {
06055
06056
06057
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
06079
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
06119
06120
06121
06122 if (!is_unsigned) {
06123 tmpY = Make_Leaf(block, WN_kid1(tree), type);
06124 WN_kid1(tree) = Load_Leaf(tmpY);
06125 }
06126
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
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
06154
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
06180
06181
06182
06183
06184 TYPE_ID cdiv_mtype = WN_rtype(tree);
06185
06186
06187
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
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
06224
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);
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
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
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
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
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
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
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
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
06459
06460
06461
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
06481
06482
06483
06484
06485
06486 static ST *coerceST(const ST *st, TYPE_ID type)
06487 {
06488 if (ST_class(st) == CLASS_PREG)
06489 {
06490
06491
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
06505
06506 return MTYPE_To_PREG(type);
06507 }
06508
06509 return (ST *) &st;
06510 }
06511
06512
06513
06514
06515
06516
06517
06518
06519
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
06547
06548
06549
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
06575
06576
06577
06578
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;
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)) {
06592
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;
06615 }
06616 else {
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);
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
06653
06654
06655
06656
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;
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)) {
06671
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) {
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;
06696 }
06697 else {
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);
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
06709
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
06724
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));
06734 for (INT i = 0; i < TY_vector_count(vty); ++i) {
06735 ldid = WN_CreateLdid(OPR_LDID, TY_mtype(ety), TY_mtype(ety),
06736
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
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);
06747 }
06748 WN_DELETE_Tree(tree);
06749 return NULL;
06750 }
06751 #endif // TARG_NVISA
06752
06753
06754
06755
06756
06757
06758
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
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
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
06812
06813
06814
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
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
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);
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
06878
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
06911
06912
06913
06914
06915
06916
06917 static WN *lower_store(WN *block, WN *tree, LOWER_ACTIONS actions)
06918 {
06919 BOOL kids_lowered = FALSE;
06920
06921 Is_True(OPCODE_is_store(WN_opcode(tree)),
06922 ("expected store node, not %s", OPCODE_name(WN_opcode(tree))));
06923
06924
06925
06926
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
06946
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
06961
06962
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
06981
06982 lower_map(tree, actions);
06983
06984
06985
06986
06987
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;
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
07048
07049
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(