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(LOWER_BASE_INDEX))
07129 {
07130 WN *addr, *base, *index;
07131 LEAF indexN;
07132
07133 base = index = NULL;
07134 lower_to_base_index(WN_kid1(tree), &base, &index) ;
07135
07136 base = lower_expr(block, base, actions);
07137 index = lower_expr(block, index, actions);
07138
07139 indexN = Make_Leaf(block, index, Pointer_type);
07140
07141 addr = WN_Add(Pointer_type,
07142 Load_Leaf(indexN),
07143 lower_copy_tree(base, actions));
07144
07145 hipart = WN_Istore(realTY,
07146 offset,
07147 coerceTY(WN_ty(tree), realTY),
07148 addr,
07149 hi);
07150
07151 addr = WN_Add(Pointer_type, Load_Leaf(indexN), base);
07152
07153 lopart = WN_Istore(realTY,
07154 coerceOFFSET(tree, realTY, offset),
07155 coerceTY(WN_ty(tree), realTY),
07156 addr,
07157 lo);
07158 }
07159 else
07160 {
07161 WN *addr;
07162 LEAF addrN;
07163
07164 addr = lower_expr(block, WN_kid1(tree), actions);
07165
07166 addrN = Make_Leaf(block, addr, Pointer_type);
07167
07168 hipart = WN_Istore(realTY,
07169 offset,
07170 coerceTY(WN_ty(tree), realTY),
07171 Load_Leaf(addrN),
07172 hi);
07173
07174 lopart = WN_Istore(realTY,
07175 coerceOFFSET(tree, realTY, offset),
07176 coerceTY(WN_ty(tree), realTY),
07177 Load_Leaf(addrN),
07178 lo);
07179 }
07180 hipart = lower_store(block, hipart, actions);
07181 WN_Set_Linenum (hipart, WN_Get_Linenum(tree));
07182 WN_INSERT_BlockLast(block, hipart);
07183
07184 lopart = lower_store(block, lopart, actions);
07185 lower_quad_maps(tree, hipart, lopart, actions);
07186 WN_Delete(tree);
07187 return lopart;
07188 }
07189 else if (Action(LOWER_SPLIT_CONST_OFFSETS))
07190 {
07191
07192
07193
07194
07195
07196
07197
07198
07199
07200
07201 WN_OFFSET offset = WN_store_offset(tree);
07202
07203 if (mem_offset_must_be_split(offset))
07204 {
07205 WN_kid1(tree) = WN_Add(Pointer_type, WN_kid1(tree),
07206 WN_Intconst(Pointer_type,
07207 mem_offset_hi(offset)));
07208 WN_store_offset(tree) = mem_offset_lo(offset);
07209 }
07210 }
07211 else
07212 {
07213
07214
07215
07216
07217
07218
07219
07220
07221
07222
07223 WN *addr_kid = WN_kid1(tree);
07224
07225 #ifdef TARG_MIPS
07226
07227
07228
07229
07230 if (FALSE)
07231 #else
07232 if (foldLdaOffset(addr_kid, WN_store_offset(tree)))
07233 #endif
07234 {
07235 WN_store_offset(tree) += WN_lda_offset(addr_kid);
07236 WN_lda_offset(addr_kid) = 0;
07237 }
07238 #ifndef TARG_MIPS
07239
07240
07241
07242
07243
07244
07245
07246
07247
07248
07249 if (WN_operator_is(addr_kid, OPR_ADD) &&
07250 foldConstOffset(WN_kid1(addr_kid), WN_store_offset(tree)))
07251 {
07252 WN_store_offset(tree) += WN_const_val(WN_kid1(addr_kid));
07253 WN_kid1(tree) = WN_kid0(addr_kid);
07254 WN_Delete(WN_kid1(addr_kid));
07255 WN_Delete(addr_kid);
07256 if (Action(LOWER_EARLY_MLOAD) && WN_desc(tree) == MTYPE_M){
07257 if ((WN_opcode(WN_kid0(tree)) == OPC_MMLDID || WN_opcode(WN_kid0(tree)) == OPC_MMILOAD) && Is_small_struct(tree)){
07258 WN *return_block = lower_mistore_by_type(block, tree, actions);
07259 if (return_block) return return_block;
07260 }
07261 }
07262 }
07263 #endif
07264 #ifdef TARG_SL2
07265
07266
07267
07268
07269
07270
07271
07272
07273
07274
07275 else if (WN_operator_is(addr_kid, OPR_ADD) &&
07276 foldConstOffset(WN_kid0(addr_kid), WN_store_offset(tree)))
07277 {
07278 WN_store_offset(tree) += WN_const_val(WN_kid0(addr_kid));
07279 WN_kid1(tree) = WN_kid1(addr_kid);
07280 WN_Delete(WN_kid0(addr_kid));
07281 WN_Delete(addr_kid);
07282 }
07283
07284
07285
07286
07287
07288
07289
07290
07291
07292
07293
07294
07295 if (WN_operator_is(WN_kid1(tree), OPR_INTCONST) &&
07296 foldConstOffset(WN_kid1(tree), WN_store_offset(tree)) &&
07297 !mem_offset_must_be_split(WN_store_offset(tree) + WN_const_val(WN_kid1(tree))))
07298 {
07299 WN_store_offset(tree) += WN_const_val(WN_kid1(tree));
07300 WN_const_val(WN_kid1(tree)) = 0;
07301 }
07302
07303 #endif // TARG_SL
07304 }
07305 break;
07306
07307 case OPR_STID:
07308 {
07309 PREG_NUM last_preg = Get_Preg_Num (PREG_Table_Size(CURRENT_SYMTAB));
07310 if (Action(LOWER_TO_MEMLIB)) {
07311 tree = Lower_STID_Memlib(block,tree,actions);
07312 if (tree == NULL || WN_operator(tree) != OPR_STID)
07313 return tree;
07314 }
07315 if ((WN_class(tree) == CLASS_PREG) &&
07316 (WN_store_offset(tree) > last_preg))
07317 {
07318 DevWarn("lower_store() pregno %d > SYMTAB_last_preg(%d)",
07319 WN_load_offset(tree), last_preg);
07320 }
07321 }
07322
07323 #ifdef TARG_NVISA
07324 if ( Action (LOWER_TO_CG)
07325 && (WN_class(tree) == CLASS_PREG)
07326 && (! Preg_Is_Dedicated (WN_store_offset (tree))))
07327 {
07328
07329
07330 WN *lda = Find_Lda (WN_kid0(tree));
07331 if (lda) Set_Preg_Lda (WN_store_offset(tree), lda);
07332 }
07333 #endif
07334
07335 if (WN_StoreIsUnused(tree))
07336 {
07337 WN *eval;
07338
07339 eval = lower_eval(block, WN_CreateEval(WN_kid0(tree)), actions);
07340
07341 WN_Delete(tree);
07342
07343 return eval;
07344 }
07345
07346 if (Action(LOWER_MLDID_MSTID) && WN_desc(tree) == MTYPE_M)
07347 return lower_mstid(block, tree, actions);
07348
07349 if (Action(LOWER_EARLY_MLOAD) && WN_desc(tree) == MTYPE_M){
07350 if ((WN_opcode(WN_kid0(tree)) == OPC_MMILOAD || WN_opcode(WN_kid0(tree)) == OPC_MMLDID) && Is_small_struct(tree)) {
07351 WN *return_block = lower_mistore_by_type(block, tree, actions);
07352 if (return_block) return return_block;
07353 }
07354 }
07355
07356 if (Action(LOWER_RETURN_VAL) && WN_desc(tree) == MTYPE_M &&
07357 WN_opcode(WN_kid0(tree)) == OPC_MMLDID &&
07358 WN_st(WN_kid0(tree)) == Return_Val_Preg) {
07359 return lower_return_mstid(block, tree, actions);
07360 }
07361 #ifdef TARG_NVISA
07362 if (Action(LOWER_RETURN_VAL) && WN_desc(tree) == MTYPE_M &&
07363 WN_opcode(WN_kid0(tree)) == OPC_MMLDID &&
07364 WN_class(WN_kid0(tree)) == CLASS_PREG &&
07365 WN_load_offset(WN_kid0(tree)) < -1)
07366 {
07367 return lower_asm_mstid(block, tree, actions);
07368 }
07369 #endif
07370 #ifdef TARG_X8664 // fortran complex treated as structs (bug 1664)
07371 if (Action(LOWER_RETURN_VAL) && MTYPE_is_complex(WN_desc(tree)) &&
07372 (Is_Target_32bit() || last_call_ff2c_abi || F2c_Abi) &&
07373 WN_operator(WN_kid0(tree)) == OPR_LDID &&
07374 WN_st(WN_kid0(tree)) == Return_Val_Preg) {
07375 return lower_return_mstid(block, tree, actions);
07376 }
07377 #endif
07378 #ifdef TARG_X8664 // MMX vector return type also uses fake parameters (bug 7733)
07379 if (Action(LOWER_RETURN_VAL) && MTYPE_is_mmx_vector(WN_desc(tree)) &&
07380 WN_operator(WN_kid0(tree)) == OPR_LDID &&
07381 WN_st(WN_kid0(tree)) == Return_Val_Preg) {
07382 return lower_return_mstid(block, tree, actions);
07383 }
07384 #endif
07385
07386 if (Action(LOWER_BIT_FIELD_ID) && WN_desc(tree) == MTYPE_BS) {
07387 lower_bit_field_id(tree);
07388 if (Action(LOWER_BITS_OP) && WN_operator (tree) == OPR_STBITS)
07389 return lower_store_bits (block, tree, actions);
07390 }
07391
07392 if (Action(LOWER_COMPLEX) && MTYPE_is_complex(WN_desc(tree)))
07393 {
07394 WN *realexp, *imagexp;
07395 TYPE_ID realTY;
07396
07397 realTY = Mtype_complex_to_real( WN_desc(tree));
07398 lower_complex_expr(block, WN_kid0(tree), actions, &realexp, &imagexp);
07399
07400 #ifdef TARG_X8664 // MTYPE_C4 is returned in one SSE register
07401 if (WN_rtype(WN_kid0(tree)) == MTYPE_F8) {
07402
07403 Is_True(WN_desc(tree) == MTYPE_C4,
07404 ("lower_store: error in handling return of 32-bit complex"));
07405 WN_set_desc(tree, MTYPE_F8);
07406 return tree;
07407 }
07408 else if (WN_desc(tree) == MTYPE_C4 && WN_st(tree) == Float_Preg &&
07409 WN_load_offset(tree) == First_Float_Preg_Return_Offset) {
07410
07411 ST *c4temp_st = Gen_Temp_Symbol(MTYPE_To_TY(MTYPE_F8), ".c4");
07412
07413
07414 WN *realexp_copy, *imagexp_copy;
07415 PREG_NUM realexpN, imagexpN;
07416 if (WN_operator(realexp) == OPR_CONST) {
07417 realexp_copy = realexp;
07418 } else {
07419 realexpN = AssignExpr(block, realexp, realTY);
07420 realexp_copy = WN_LdidPreg(realTY, realexpN);
07421 }
07422 if (WN_operator(imagexp) == OPR_CONST) {
07423 imagexp_copy = imagexp;
07424 } else {
07425 imagexpN = AssignExpr(block, imagexp, realTY);
07426 imagexp_copy = WN_LdidPreg(realTY, imagexpN);
07427 }
07428
07429
07430 WN *stid = WN_Stid(WN_rtype(realexp), 0, c4temp_st, realTY,
07431 realexp_copy);
07432 WN_Set_Linenum (stid, WN_Get_Linenum(tree));
07433 WN_INSERT_BlockLast(block, stid);
07434
07435
07436 stid = WN_Stid(WN_rtype(imagexp), 4, c4temp_st, realTY, imagexp_copy);
07437 WN_Set_Linenum (stid, WN_Get_Linenum(tree));
07438 WN_INSERT_BlockLast(block, stid);
07439
07440 WN_Delete(WN_kid0(tree));
07441 WN_kid0(tree) = WN_Ldid(MTYPE_F8, 0, c4temp_st, MTYPE_To_TY(MTYPE_F8));
07442 WN_set_desc(tree, MTYPE_F8);
07443 return tree;
07444
07445 } else if( Is_Target_32bit() &&
07446 WN_desc(tree) == MTYPE_C4 &&
07447 WN_st(tree) == Float_Preg &&
07448 WN_load_offset(tree) == First_X87_Preg_Return_Offset &&
07449 (
07450 #if defined(BUILD_OS_DARWIN)
07451
07452 1
07453 #else
07454 PU_c_lang(Get_Current_PU()) ||
07455 PU_cxx_lang(Get_Current_PU())
07456 #endif
07457 ) ){
07458
07459
07460
07461
07462 const TYPE_ID mtype = MTYPE_I4;
07463
07464 ST *c4temp_st = Gen_Temp_Symbol(MTYPE_To_TY(MTYPE_C4), ".c4");
07465
07466 WN *realexp_copy = realexp;
07467 WN *imagexp_copy = imagexp;
07468 #ifdef KEY // bug 12787
07469 if (has_call(realexp)) {
07470 PREG_NUM realexpN = AssignExpr(block, realexp, realTY);
07471 realexp_copy = WN_LdidPreg(realTY, realexpN);
07472 }
07473 if (has_call(imagexp)) {
07474 PREG_NUM imagexpN = AssignExpr(block, imagexp, realTY);
07475 imagexp_copy = WN_LdidPreg(realTY, imagexpN);
07476 }
07477 #endif
07478
07479
07480 WN *stid = WN_Stid( WN_rtype(realexp), 0, c4temp_st, realTY, realexp_copy );
07481 WN_Set_Linenum( stid, WN_Get_Linenum(tree) );
07482 WN_INSERT_BlockLast( block, stid );
07483
07484 WN* ldid = WN_Ldid( mtype, 0, c4temp_st, MTYPE_To_TY(mtype) );
07485 stid = WN_Stid( mtype, First_Int_Preg_Return_Offset,
07486 Int_Preg, mtype, ldid );
07487 WN_Set_Linenum( stid, WN_Get_Linenum(tree) );
07488 WN_INSERT_BlockLast( block, stid );
07489
07490
07491 stid = WN_Stid( WN_rtype(imagexp), 4, c4temp_st, realTY, imagexp_copy );
07492 WN_Set_Linenum (stid, WN_Get_Linenum(tree));
07493 WN_INSERT_BlockLast(block, stid);
07494
07495 WN_Delete(WN_kid0(tree));
07496 WN_Delete( tree );
07497
07498 ldid = WN_Ldid( mtype, 4, c4temp_st, MTYPE_To_TY(mtype) );
07499 tree = WN_Stid( mtype, Last_Int_Preg_Return_Offset,
07500 Int_Preg, mtype, ldid );
07501
07502 return tree;
07503 }
07504 else
07505 #endif
07506
07507
07508
07509
07510
07511 {
07512 WN_OFFSET offset = WN_store_offset(tree);
07513 PREG_NUM realexpN, imagexpN;
07514 WN *wn;
07515 WN *realexp_copy,*imagexp_copy;
07516
07517 if (WN_operator(realexp) == OPR_CONST) {
07518 realexp_copy = realexp;
07519 } else {
07520 realexpN = AssignExpr(block, realexp, realTY);
07521 realexp_copy = WN_LdidPreg(realTY, realexpN);
07522 }
07523
07524 if (WN_operator(imagexp) == OPR_CONST) {
07525 imagexp_copy = imagexp;
07526 } else {
07527 imagexpN = AssignExpr(block, imagexp, realTY);
07528 imagexp_copy = WN_LdidPreg(realTY, imagexpN);
07529 }
07530
07531 wn = WN_Stid(realTY,
07532 offset,
07533 coerceST(WN_st(tree), realTY),
07534 MTYPE_To_TY(realTY),
07535 realexp_copy);
07536
07537 realexp = lower_store(block, wn, actions);
07538 WN_Set_Linenum (realexp, WN_Get_Linenum(tree));
07539 WN_INSERT_BlockLast(block, realexp);
07540
07541 wn = WN_Stid(realTY,
07542 coerceOFFSET(tree, realTY, offset),
07543 coerceST(WN_st(tree), realTY),
07544 MTYPE_To_TY(realTY),
07545 imagexp_copy);
07546
07547 imagexp = lower_store(block, wn, actions);
07548
07549 lower_complex_maps(tree, realexp, imagexp, actions);
07550
07551 WN_Delete(tree);
07552
07553 return imagexp;
07554 }
07555 }
07556
07557 else if (Action(LOWER_QUAD) && MTYPE_is_quad(WN_desc(tree)))
07558 {
07559 WN_OFFSET offset = WN_store_offset(tree);
07560 WN *hiexp, *loexp, *wn, *hipart, *lopart;
07561 TYPE_ID realTY = MTYPE_F8;
07562
07563 lower_quad_expr(block, WN_kid0(tree), actions, &hiexp, &loexp);
07564
07565
07566
07567
07568 wn = WN_Stid(realTY,
07569 offset,
07570 coerceST(WN_st(tree), realTY),
07571 MTYPE_To_TY(realTY), hiexp);
07572
07573 hipart = lower_store(block, wn, actions);
07574 WN_Set_Linenum (hipart, WN_Get_Linenum(tree));
07575 WN_INSERT_BlockLast(block, hipart);
07576
07577 wn = WN_Stid(realTY,
07578 coerceOFFSET(tree, realTY, offset),
07579 coerceST(WN_st(tree), realTY),
07580 MTYPE_To_TY(realTY), loexp);
07581 lopart = lower_store(block, wn, actions);
07582
07583 lower_quad_maps(tree, hipart, lopart, actions);
07584
07585 WN_Delete(tree);
07586
07587 return lopart;
07588 }
07589
07590 if (Action(LOWER_SPLIT_SYM_ADDRS))
07591 {
07592
07593
07594
07595
07596
07597 WN *istore;
07598
07599 istore = lower_split_sym_addrs(tree, WN_store_offset(tree), actions);
07600 if (istore)
07601 {
07602 return lower_store(block, istore, actions);
07603 }
07604 }
07605
07606 if ( Action(LOWER_FORMAL_REF) && WN_class(tree) == CLASS_VAR)
07607 {
07608 WN *istore;
07609
07610 istore = lower_formal_ref(tree, WN_store_offset(tree),
07611 WN_st(tree), actions);
07612 if (istore)
07613 {
07614 return lower_store(block, istore, actions);
07615 }
07616 }
07617
07618 if ( Action(LOWER_UPLEVEL))
07619 {
07620 ST *sym = WN_st(tree);
07621
07622 if (ST_is_uplevelTemp(sym))
07623 {
07624 WN *istore;
07625
07626 istore = lower_uplevel_reference(tree, WN_store_offset(tree), actions);
07627 return lower_store(block, istore, actions);
07628 }
07629 }
07630
07631 break;
07632
07633 case OPR_ISTBITS:
07634 case OPR_STBITS:
07635 if (Action(LOWER_BITS_OP))
07636 return lower_store_bits (block, tree, actions);
07637 break;
07638
07639 case OPR_MSTORE:
07640 {
07641 WN *rhs = WN_kid0(tree);
07642 Is_True(!(WN_opcode(rhs) == OPC_MMLDID && WN_st(rhs) == Return_Val_Preg),
07643 ("MMLDID of Return_Val_Preg cannot be rhs of MSTORE"));
07644 }
07645
07646 if (Align_Object)
07647 {
07648 INT16 i;
07649 for (i = 0; i < WN_kid_count(tree); i++)
07650 WN_kid(tree,i) = lower_expr(block, WN_kid(tree,i), actions);
07651
07652 tree = improve_Malignment(tree, WN_kid1(tree), WN_kid2(tree),
07653 WN_store_offset(tree));
07654 }
07655
07656 if (Action(LOWER_MSTORE))
07657 {
07658 if (WN_StoreIsUnused(WN_kid1(tree)))
07659 {
07660 WN *eval;
07661
07662 eval = lower_eval(block, WN_CreateEval(WN_kid0(tree)), actions);
07663
07664 WN_Delete(tree);
07665
07666 return eval;
07667 }
07668
07669
07670
07671
07672
07673
07674 if (WN_opcode(WN_kid0(tree)) == OPC_MCSELECT)
07675 {
07676 WN *select, *expr, *mload0, *mload1, *cselect;
07677
07678 select = WN_kid0(tree);
07679 expr = WN_kid0(select);
07680 mload0 = WN_kid1(select);
07681 mload1 = WN_kid2(select);
07682
07683 Is_True(WN_operator_is(mload0, OPR_MLOAD),
07684 ("unexpected MSTORE (MCSELECT) pattern"));
07685 Is_True(WN_operator_is(mload1, OPR_MLOAD),
07686 ("unexpected MSTORE (MCSELECT) pattern"));
07687
07688 cselect = WN_Cselect(Pointer_type, expr, WN_kid0(mload0),
07689 WN_kid0(mload1));
07690 WN_kid0(mload0) = cselect;
07691 WN_kid0(tree) = mload0;
07692 }
07693 tree = lower_mstore(block, tree, actions);
07694 kids_lowered = TRUE;
07695 }
07696
07697 break;
07698
07699 }
07700
07701 #ifndef TARG_NVISA
07702
07703
07704
07705 #ifdef KEY
07706
07707
07708
07709
07710
07711
07712
07713
07714
07715
07716 if (VHO_Enable_Simple_If_Conv &&
07717 !Action(LOWER_RETURN_VAL) &&
07718
07719
07720 !Action(LOWER_FAST_EXP) &&
07721 !Action(LOWER_TREEHEIGHT) &&
07722 !Action(LOWER_INLINE_INTRINSIC) &&
07723 OPCODE_is_store(WN_opcode(tree)) &&
07724 WN_operator(WN_kid0(tree)) == OPR_SELECT &&
07725 !MTYPE_is_vector(WN_desc(tree)) && MTYPE_is_float(WN_desc(tree))) {
07726 WN* store = tree;
07727 WN* load = WN_kid2(WN_kid0(tree));
07728 WN* array_l = WN_kid0(load);
07729 WN* array_s = WN_kid1(store);
07730 if ((WN_operator(load) == OPR_ILOAD &&
07731 WN_operator(store) == OPR_ISTORE &&
07732 WN_store_offset(store) == WN_load_offset(load) &&
07733 Equiv(array_l, array_s) &&
07734 WN_field_id(load) == WN_field_id(store)) ||
07735 (WN_operator(load) == OPR_LDID &&
07736 WN_operator(store) == OPR_STID &&
07737 WN_offset(store) == WN_offset(load) &&
07738 ST_base(WN_st(store)) == ST_base(WN_st(load)) &&
07739 ST_ofst(WN_st(store)) == ST_ofst(WN_st(load)))) {
07740 WN* select = WN_kid0(tree);
07741 WN* test = WN_COPY_Tree(WN_kid0(select));
07742 WN* then_block = WN_CreateBlock();
07743 WN* else_block = WN_CreateBlock();
07744 WN* istore = WN_COPY_Tree(tree);
07745 WN_kid0(istore) = WN_COPY_Tree(WN_kid1(select));
07746 tree = WN_CreateIf (test, then_block, else_block);
07747 WN_INSERT_BlockLast(then_block, istore);
07748 tree = lower_if(block, tree, actions);
07749 return tree;
07750 }
07751 }
07752 #endif
07753 #endif // !TARG_NVISA
07754
07755 if (! kids_lowered)
07756 {
07757 INT16 i;
07758
07759 for (i = 0; i < WN_kid_count(tree); i++)
07760 WN_kid(tree,i) = lower_expr(block, WN_kid(tree,i), actions);
07761 }
07762
07763 return tree;
07764 }
07765
07766
07767
07768
07769
07770
07771
07772
07773
07774
07775
07776
07777
07778 static WN *lower_eval(WN *block, WN *tree, LOWER_ACTIONS actions)
07779 {
07780 WN *child = WN_kid0(tree);
07781
07782 Is_True(WN_opcode(tree) == OPC_EVAL,
07783 ("expected EVAL node, not %s", OPCODE_name(WN_opcode(tree))));
07784
07785 if (Action(LOWER_MLDID_MSTID) && WN_opcode(child) == OPC_MMLDID) {
07786 child = lower_mldid(block, child, actions);
07787 }
07788
07789 if (Action(LOWER_COMPLEX) && MTYPE_is_complex(WN_rtype(child)))
07790 {
07791 WN *realexp, *imagexp, *eval;
07792
07793 lower_complex_expr(block, child, actions, &realexp, &imagexp);
07794
07795 realexp = lower_expr(block, realexp, actions);
07796 eval = WN_CreateEval(realexp);
07797 WN_Set_Linenum(eval, current_srcpos);
07798 WN_INSERT_BlockLast(block, eval);
07799
07800 child = imagexp;
07801 }
07802 else if (Action(LOWER_QUAD) && MTYPE_is_quad(WN_rtype(child)))
07803 {
07804 WN *hi, *lo, *eval;
07805
07806 lower_quad_expr(block, child, actions, &hi, &lo);
07807
07808 hi = lower_expr(block, hi, actions);
07809 eval = WN_CreateEval(hi);
07810 WN_Set_Linenum(eval, current_srcpos);
07811 WN_INSERT_BlockLast(block, eval);
07812
07813 child = lo;
07814 }
07815 else if ((Action(LOWER_MSTORE) || Action(LOWER_TO_CG)) && WN_operator_is(child, OPR_MLOAD))
07816 {
07817 TY_IDX mloadTY = TY_pointed(Ty_Table[WN_ty(child)]);
07818
07819 if (TY_is_volatile(mloadTY))
07820 {
07821 DevWarn("eval of volatile (mload) seen. I hoped to never see this");
07822 }
07823 else if (Action(LOWER_TO_CG) && traceWoptFinishedOpt)
07824 {
07825 DevWarn("eval of (mload) processed (wopt should have removed this)");
07826 }
07827 block = lower_mload(block, child, actions);
07828 return block;
07829 }
07830
07831 {
07832 WN *eval;
07833
07834 child = lower_expr(block, child, actions);
07835 eval = WN_CreateEval(child);
07836 WN_Delete(tree);
07837
07838 return eval;
07839 }
07840
07841 }
07842
07843
07844
07845 static INT32
07846 calculateLoadStore(INT64 size, INT64 offset, TYPE_ID quantum, WN *src)
07847 {
07848 INT32 n = (size-offset) / MTYPE_RegisterSize(quantum);
07849
07850 return WN_operator_is(src, OPR_INTCONST) ? n : 2*n;
07851 }
07852
07853
07854
07855
07856
07857
07858
07859
07860
07861
07862
07863
07864
07865
07866
07867
07868
07869
07870
07871
07872
07873
07874
07875
07876
07877 static MSTORE_ACTIONS
07878 GenerateMstoreAction(WN *size, INT32 offset, TYPE_ID quantum, WN *expr)
07879 {
07880 MSTORE_ACTIONS action;
07881
07882 INT32 nMoves;
07883 BOOL sizeIsConstant = WN_operator_is(size, OPR_INTCONST);
07884
07885 if (sizeIsConstant)
07886 {
07887 nMoves = calculateLoadStore(WN_const_val(size), offset, quantum, expr);
07888 }
07889
07890 if (MinStructCopyMemIntrSize &&
07891 ((sizeIsConstant==FALSE) ||
07892 (sizeIsConstant==TRUE && MinStructCopyMemIntrSize <= nMoves)))
07893 {
07894 if (WN_operator_is(expr, OPR_INTCONST))
07895 {
07896 INT64 val= WN_const_val(expr);
07897
07898 if (val == 0)
07899 action = MSTORE_intrinsic_bzero;
07900 else
07901 {
07902 WN *i1con= WN_I1const(WN_rtype(expr), val);
07903
07904 action = (val == WN_const_val(i1con)) ? MSTORE_intrinsic_memset
07905 : MSTORE_loop;
07906 WN_Delete(i1con);
07907 }
07908 }
07909 else if (WN_operator_is(expr, OPR_MLOAD))
07910 {
07911 #ifdef KEY
07912 int sizenum = WN_const_val(size);
07913 if (sizeIsConstant &&
07914 ((sizenum-offset)%8 == 0 ||
07915 (sizenum - offset) > MinStructCopyMemIntrSize * 1.5))
07916 action = MSTORE_intrinsic_memcpy;
07917 else
07918 action = MSTORE_loop;
07919 #else
07920 action = MSTORE_intrinsic_bcopy;
07921 #endif
07922 }
07923 else
07924 {
07925 action = MSTORE_loop;
07926 }
07927 }
07928 else if (sizeIsConstant==TRUE &&
07929 MinStructCopyLoopSize &&
07930 MinStructCopyLoopSize <= nMoves)
07931 {
07932 action = MSTORE_loop;
07933 }
07934 else
07935 {
07936 action = (sizeIsConstant) ? MSTORE_aggregate : MSTORE_loop;
07937 }
07938
07939 if (traceMload)
07940 {
07941 if (sizeIsConstant) {
07942 DevWarn("GenerateMstoreAction: %s : line %d: quantum %d, "
07943 "size %lld, nMoves %d",
07944 MSTORE_ACTIONS_name(action),
07945 Srcpos_To_Line(current_srcpos),
07946 MTYPE_alignment(quantum),
07947 WN_const_val(size),
07948 nMoves);
07949 } else {
07950 DevWarn("GenerateMstoreAction: %s : line %d: quantum %d, "
07951 "size unknown",
07952 MSTORE_ACTIONS_name(action),
07953 Srcpos_To_Line(current_srcpos),
07954 MTYPE_alignment(quantum));
07955 }
07956 }
07957
07958 return action;
07959 }
07960
07961
07962
07963
07964 static inline TY_IDX
07965 struct_memop_type (TYPE_ID mtype, TY_IDX struct_type)
07966 {
07967 if (TY_size (struct_type) != MTYPE_byte_size (mtype))
07968 Set_TY_IDX_index (struct_type, TY_IDX_index(MTYPE_To_TY (mtype)));
07969 return struct_type;
07970 }
07971
07972
07973
07974
07975
07976
07977
07978
07979
07980
07981
07982
07983
07984
07985
07986
07987
07988
07989
07990
07991
07992
07993
07994
07995
07996
07997
07998
07999
08000
08001
08002
08003
08004
08005
08006
08007
08008
08009 static void
08010 copy_aggregate(WN *block, TY_IDX srcAlign, TY_IDX dstAlign, INT32 offset,
08011 INT32 size, TYPE_ID quantum, PREG_NUM srcPreg,
08012 PREG_NUM dstPreg, WN *origLoad, WN *origStore,
08013 INT32 copy_alignment, LOWER_ACTIONS actions)
08014 {
08015 BOOL unweave = UnweaveCopyForStructs;
08016 WN *storeBlock = unweave ? WN_CreateBlock() : block;
08017
08018 while (size > 0) {
08019
08020 INT32 stride = MTYPE_RegisterSize(quantum);
08021
08022 for ( ; size >= stride; size -= stride, offset += stride) {
08023
08024
08025
08026
08027 WN *wn_value, *wn_addr, *wn_store;
08028
08029 rename_preg("mstore_tmp", NULL);
08030 if (! srcAlign) {
08031 wn_value = WN_LdidPreg(quantum, srcPreg);
08032 } else {
08033 TY_IDX ty_src = struct_memop_type(quantum, srcAlign);
08034 wn_value = WN_LdidPreg(Pointer_type, srcPreg);
08035 wn_value = WN_Iload(quantum, offset, ty_src, wn_value);
08036 lower_copy_maps(origLoad, wn_value, actions);
08037 if (unweave) {
08038 PREG_NUM preg = AssignExpr(block, wn_value, quantum);
08039 wn_value = WN_LdidPreg(quantum, preg);
08040 }
08041 }
08042
08043 wn_addr = WN_LdidPreg(Pointer_type, dstPreg);
08044 TY_IDX ty_dst = struct_memop_type(quantum, dstAlign);
08045 wn_store = WN_Istore(quantum, offset,
08046 Make_Pointer_Type(ty_dst), wn_addr, wn_value);
08047 lower_copy_maps(origStore, wn_store, actions);
08048 WN_Set_Linenum(wn_store, current_srcpos);
08049 WN_INSERT_BlockLast(storeBlock, wn_store);
08050 }
08051
08052
08053
08054 if (size > 0) {
08055 quantum = compute_next_copy_quantum(quantum, copy_alignment);
08056 }
08057 }
08058
08059 if (unweave) WN_INSERT_BlockLast(block, storeBlock);
08060 }
08061
08062
08063
08064
08065
08066
08067
08068
08069
08070 static void
08071 copy_element_and_increment(WN *block, TY_IDX srcAlign, TY_IDX dstAlign,
08072 INT32 offset, INT32 size, TYPE_ID quantum,
08073 PREG_NUM srcPreg, PREG_NUM dstPreg,
08074 WN *origLoad, WN *origStore,
08075 INT32 copy_alignment, LOWER_ACTIONS actions)
08076 {
08077
08078 copy_aggregate(block, srcAlign, dstAlign, offset, size, quantum,
08079 srcPreg, dstPreg, origLoad, origStore,
08080 copy_alignment, actions);
08081
08082
08083 WN *wn;
08084 ST *pointerPreg = MTYPE_To_PREG(Pointer_type);
08085 if (srcAlign) {
08086 wn = WN_Add(Pointer_type,
08087 WN_LdidPreg(Pointer_type, srcPreg),
08088 WN_Intconst(Integer_type, size));
08089 wn = WN_StidIntoPreg(Pointer_type, srcPreg, pointerPreg, wn);
08090 WN_Set_Linenum(wn, current_srcpos);
08091 WN_INSERT_BlockLast(block, wn);
08092 }
08093
08094
08095 wn = WN_Add(Pointer_type,
08096 WN_LdidPreg(Pointer_type, dstPreg),
08097 WN_Intconst(Integer_type, size));
08098 wn = WN_StidIntoPreg(Pointer_type, dstPreg, pointerPreg, wn);
08099 WN_Set_Linenum(wn, current_srcpos);
08100 WN_INSERT_BlockLast(block, wn);
08101 }
08102
08103
08104
08105
08106
08107
08108
08109
08110
08111 static void
08112 copy_aggregate_loop_const(WN *block, TY_IDX srcAlign, TY_IDX dstAlign,
08113 INT32 offset, INT32 size, TYPE_ID quantum,
08114 PREG_NUM srcPregInit, PREG_NUM dstPregInit,
08115 WN *origLoad, WN *origStore,
08116 INT32 copy_alignment, LOWER_ACTIONS actions)
08117 {
08118
08119
08120
08121
08122
08123
08124
08125
08126
08127
08128
08129
08130 WN *wn;
08131 ST *intPreg = MTYPE_To_PREG(Integer_type);
08132 INT32 stride = MTYPE_RegisterSize(quantum);
08133 INT32 bigstride = Aggregate_UnrollFactor * stride;
08134 INT64 nMoves = size / bigstride;
08135 INT64 residue = size - ( nMoves * bigstride );
08136 PREG_NUM srcPreg, dstPreg;
08137
08138
08139 if (nMoves <= 0 && residue == 0)
08140 return;
08141
08142
08143 rename_preg("mstore_src", NULL);
08144 if (srcAlign == 0) {
08145
08146 srcPreg = srcPregInit;
08147 } else {
08148 wn = WN_LdidPreg( Pointer_type, srcPregInit );
08149 if (offset != 0) {
08150 wn = WN_Add( Pointer_type, wn,
08151 WN_Intconst(Integer_type, offset) );
08152 }
08153 srcPreg = AssignExpr( block, wn, Pointer_type );
08154 }
08155
08156
08157 rename_preg("mstore_dst", NULL);
08158 wn = WN_LdidPreg( Pointer_type, dstPregInit );
08159 if (offset != 0) {
08160 wn = WN_Add( Pointer_type, wn,
08161 WN_Intconst(Integer_type, offset) );
08162 }
08163 dstPreg = AssignExpr( block, wn, Pointer_type );
08164 rename_reset();
08165
08166 if (nMoves > 0)
08167 {
08168
08169 PREG_NUM n;
08170 WN *body, *incr, *start, *test, *doLoop;
08171 n = Create_Preg( Integer_type, "mstore_loopcount" );
08172 body = WN_CreateBlock();
08173 start = WN_StidIntoPreg( Integer_type, n, intPreg,
08174 WN_Intconst(Integer_type, nMoves) );
08175 incr = WN_StidIntoPreg( Integer_type, n, intPreg,
08176 WN_Sub(Integer_type,
08177 WN_LdidPreg(Integer_type, n),
08178 WN_Intconst(Integer_type, 1)) );
08179 test = WN_GT( Integer_type,
08180 WN_LdidPreg(Integer_type, n),
08181 WN_Zerocon(Integer_type) );
08182
08183
08184 copy_element_and_increment( body, srcAlign, dstAlign, 0 ,
08185 bigstride, quantum,
08186 srcPreg, dstPreg, origLoad, origStore,
08187 copy_alignment, actions );
08188
08189 doLoop = WN_CreateDO( WN_CreateIdname(n, intPreg),
08190 start, test, incr, body, NULL );
08191 WN_Set_Linenum(doLoop, current_srcpos);
08192 WN_INSERT_BlockLast(block, doLoop);
08193 if ( Cur_PU_Feedback && (origStore != NULL) )
08194 Cur_PU_Feedback->FB_lower_mstore_to_loop( origStore, doLoop, nMoves );
08195 }
08196
08197
08198
08199
08200
08201 if (residue > 0) {
08202 WN *residue_block = WN_CreateBlock();
08203 copy_aggregate(residue_block, srcAlign, dstAlign, 0 ,
08204 residue , quantum, srcPreg, dstPreg,
08205 origLoad, origStore, copy_alignment, actions);
08206 WN_INSERT_BlockLast(block, residue_block);
08207 }
08208 }
08209
08210
08211
08212
08213
08214
08215
08216
08217
08218
08219 static void
08220 copy_aggregate_loop_n(WN *block, TY_IDX srcAlign, TY_IDX dstAlign,
08221 INT32 offset, WN *size, TYPE_ID quantum,
08222 PREG_NUM srcPregInit, PREG_NUM dstPregInit,
08223 WN *origLoad, WN *origStore,
08224 INT32 copy_alignment, LOWER_ACTIONS actions)
08225 {
08226
08227
08228
08229
08230
08231
08232
08233
08234
08235
08236 WN *wn;
08237 PREG_NUM nMovesN, residueN, srcPreg, dstPreg;
08238 ST *intPreg = MTYPE_To_PREG(Integer_type);
08239 INT32 stride = MTYPE_RegisterSize(quantum);
08240 Is_True( (WN_operator(size) != OPR_INTCONST), ("unexpected const") );
08241
08242
08243 rename_preg("mstore_src", NULL);
08244 if (srcAlign == 0) {
08245
08246 srcPreg = srcPregInit;
08247 } else {
08248 wn = WN_LdidPreg( Pointer_type, srcPregInit );
08249 if (offset != 0) {
08250 wn = WN_Add( Pointer_type, wn,
08251 WN_Intconst(Integer_type, offset) );
08252 }
08253 srcPreg = AssignExpr( block, wn, Pointer_type );
08254
08255 }
08256
08257
08258 rename_preg("mstore_dst", NULL);
08259 wn = WN_LdidPreg( Pointer_type, dstPregInit );
08260 if (offset != 0) {
08261 wn = WN_Add( Pointer_type, wn,
08262 WN_Intconst(Integer_type, offset) );
08263 }
08264 dstPreg = AssignExpr( block, wn, Pointer_type );
08265
08266 rename_reset();
08267
08268
08269 wn = WN_Div( Integer_type, WN_COPY_Tree(size),
08270 WN_Intconst(Integer_type, stride) );
08271 nMovesN = AssignExpr( block, wn, Integer_type );
08272
08273
08274 wn = WN_Sub( Integer_type, WN_COPY_Tree(size),
08275 WN_Mpy( Integer_type,
08276 WN_LdidPreg(Integer_type, nMovesN),
08277 WN_Intconst(Integer_type, stride) ) );
08278 residueN = AssignExpr( block, wn, Integer_type );
08279
08280
08281 PREG_NUM n = Create_Preg( Integer_type, "mstore_loopcount" );
08282
08283 WN *body, *incr, *start, *test, *doLoop;
08284 body = WN_CreateBlock();
08285 start = WN_StidIntoPreg( Integer_type, n, intPreg,
08286 WN_LdidPreg(Integer_type, nMovesN) );
08287 incr = WN_StidIntoPreg( Integer_type, n, intPreg,
08288 WN_Sub( Integer_type,
08289 WN_LdidPreg(Integer_type, n),
08290 WN_Intconst(Integer_type, 1) ) );
08291 test = WN_GT( Integer_type,
08292 WN_LdidPreg(Integer_type, n),
08293 WN_Zerocon(Integer_type) );
08294
08295
08296
08297 copy_element_and_increment( body, srcAlign, dstAlign, 0 ,
08298 stride, quantum, srcPreg, dstPreg,
08299 origLoad, origStore,
08300 copy_alignment, actions);
08301
08302 doLoop = WN_CreateDO( WN_CreateIdname(n, intPreg),
08303 start, test, incr, body, NULL );
08304 WN_Set_Linenum(doLoop, current_srcpos);
08305 WN_INSERT_BlockLast( block, doLoop );
08306
08307
08308
08309
08310
08311
08312
08313
08314
08315
08316
08317
08318
08319
08320
08321
08322
08323
08324
08325
08326
08327
08328
08329
08330
08331
08332 WN *block_checks = WN_CreateBlock();
08333 quantum = compute_next_copy_quantum( quantum,
08334 MTYPE_alignment(Max_Uint_Mtype) );
08335 while (MTYPE_alignment(quantum) > 0) {
08336
08337
08338 WN *block_residue = WN_CreateBlock();
08339
08340
08341
08342 INT32 stride = MTYPE_RegisterSize(quantum);
08343 copy_element_and_increment( block_residue, srcAlign, dstAlign,
08344 0 , stride, quantum,
08345 srcPreg, dstPreg, origLoad, origStore,
08346 copy_alignment, actions );
08347
08348
08349 wn = WN_Sub( Integer_type,
08350 WN_LdidPreg( Integer_type, residueN ),
08351 WN_Intconst( Integer_type, MTYPE_alignment(quantum) ) );
08352 wn = WN_StidIntoPreg( Integer_type, residueN, intPreg, wn );
08353 lower_copy_maps( origStore, wn, actions );
08354 WN_Set_Linenum(wn, current_srcpos);
08355 WN_INSERT_BlockLast( block_residue, wn );
08356
08357
08358 wn = WN_GE( Integer_type,
08359 WN_LdidPreg( Integer_type, residueN ),
08360 WN_Intconst( Integer_type, MTYPE_alignment(quantum) ) );
08361 wn = WN_CreateIf( wn, block_residue, WN_CreateBlock() );
08362
08363 lower_copy_maps( origStore, wn, actions );
08364 WN_Set_Linenum(wn, current_srcpos);
08365 WN_INSERT_BlockLast( block_checks, wn );
08366
08367 quantum = compute_next_copy_quantum( quantum,
08368 MTYPE_alignment(Max_Uint_Mtype) );
08369 }
08370
08371
08372 wn = WN_GT( Integer_type, WN_LdidPreg( Integer_type, residueN ),
08373 WN_Zerocon(Integer_type) );
08374 wn = WN_CreateIf( wn, block_checks, WN_CreateBlock() );
08375
08376 WN_Set_Linenum(wn, current_srcpos);
08377 WN_INSERT_BlockLast( block, wn );
08378 }
08379
08380
08381
08382
08383
08384
08385
08386
08387
08388
08389
08390
08391
08392
08393
08394
08395
08396 static void
08397 copy_aggregate_loop(WN *block, TY_IDX srcTY, TY_IDX dstTY, INT32 offset,
08398 WN *size, TYPE_ID quantum, PREG_NUM srcPreg,
08399 PREG_NUM dstPreg, WN *origLoad, WN *origStore,
08400 INT32 copy_alignment, LOWER_ACTIONS actions)
08401 {
08402 if (WN_operator_is(size, OPR_INTCONST))
08403 {
08404 if (WN_const_val(size)>0)
08405 {
08406 copy_aggregate_loop_const(block, srcTY, dstTY, offset,
08407 WN_const_val(size), quantum,
08408 srcPreg, dstPreg, origLoad, origStore,
08409 copy_alignment, actions);
08410 }
08411 }
08412 else
08413 {
08414 copy_aggregate_loop_n(block, srcTY, dstTY, offset, size, quantum,
08415 srcPreg, dstPreg, origLoad, origStore,
08416 copy_alignment, actions);
08417 }
08418 }
08419
08420
08421
08422
08423
08424
08425 static void markAddrTakenPassed(WN *expr)
08426 {
08427 switch(WN_operator(expr))
08428 {
08429 case OPR_LDA:
08430 {
08431 ST *sym = WN_st(expr);
08432
08433
08434
08435
08436
08437
08438 }
08439 return;
08440 case OPR_ILOAD:
08441 case OPR_ILOADX:
08442 return;
08443 }
08444
08445 {
08446 INT32 i;
08447 for (i = 0; i < WN_kid_count(expr); i++)
08448 markAddrTakenPassed(WN_actual(expr,i));
08449 }
08450 }
08451
08452
08453
08454
08455
08456
08457
08458
08459
08460 inline WN *WN_Generate_Intrinsic_Call(WN *block, INTRINSIC id,
08461 INT32 nparm, WN *parm[])
08462 {
08463 WN *call = WN_Create_Intrinsic(OPC_VINTRINSIC_CALL, id, nparm, parm);
08464 return intrinsic_runtime(block, call);
08465 }
08466
08467
08468 static void copy_aggregate_bzero(WN *block, TY_IDX dstTY, WN *dst, WN *size)
08469 {
08470 WN *call, *parms[2];
08471
08472 markAddrTakenPassed(dst);
08473
08474 parms[0]= WN_CreateParm(Pointer_type,
08475 dst,
08476 dstTY,
08477 WN_PARM_BY_VALUE);
08478
08479 parms[1]= WN_CreateParm(WN_rtype(size),
08480 WN_COPY_Tree(size),
08481 MTYPE_To_TY(WN_rtype(size)),
08482 WN_PARM_BY_VALUE);
08483
08484 call= WN_Generate_Intrinsic_Call(block, INTRN_BZERO, 2, parms);
08485 WN_Set_Linenum(call, current_srcpos);
08486 WN_INSERT_BlockLast(block, call);
08487 }
08488
08489 static void copy_aggregate_memset(WN *block, TY_IDX dstTY, WN *src, WN *dst,
08490 WN *size)
08491 {
08492 WN *call, *parms[3];
08493
08494 markAddrTakenPassed(dst);
08495 parms[0]= WN_CreateParm(Pointer_type,
08496 dst,
08497 dstTY,
08498 WN_PARM_BY_VALUE);
08499
08500
08501
08502
08503 parms[1]= WN_CreateParm(MTYPE_I4,
08504 src,
08505 MTYPE_To_TY(MTYPE_I4),
08506 WN_PARM_BY_VALUE);
08507
08508 parms[2]= WN_CreateParm(WN_rtype(size),
08509 WN_COPY_Tree(size),
08510 MTYPE_To_TY(WN_rtype(size)),
08511 WN_PARM_BY_VALUE);
08512
08513 call= WN_Generate_Intrinsic_Call(block, INTRN_MEMSET, 3, parms);
08514 WN_Set_Linenum(call, current_srcpos);
08515 WN_INSERT_BlockLast(block, call);
08516 }
08517
08518 #ifdef KEY
08519 static void copy_aggregate_memcpy(WN *block, INT32 offset, TY_IDX srcTY,
08520 TY_IDX dstTY, WN *src, WN *dst, WN *size)
08521 {
08522 WN *call, *parms[3];
08523
08524 if (offset)
08525 {
08526 src = WN_Add(Pointer_type, src, WN_Intconst(Pointer_type, offset));
08527 dst = WN_Add(Pointer_type, dst, WN_Intconst(Pointer_type, offset));
08528 }
08529 markAddrTakenPassed(src);
08530 markAddrTakenPassed(dst);
08531
08532 parms[0]= WN_CreateParm(Pointer_type,
08533 dst,
08534 dstTY ? dstTY : MTYPE_To_TY(WN_rtype(dst)),
08535 WN_PARM_BY_VALUE);
08536
08537 parms[1]= WN_CreateParm(WN_rtype(src),
08538 src,
08539 srcTY ? srcTY : MTYPE_To_TY(WN_rtype(src)),
08540 WN_PARM_BY_VALUE);
08541
08542 parms[2]= WN_CreateParm(WN_rtype(size),
08543 WN_COPY_Tree(size),
08544 MTYPE_To_TY(WN_rtype(size)),
08545 WN_PARM_BY_VALUE);
08546
08547 call= WN_Generate_Intrinsic_Call(block, INTRN_MEMCPY, 3, parms);
08548 WN_Set_Linenum(call, current_srcpos);
08549 WN_INSERT_BlockLast(block, call);
08550 }
08551
08552 #endif
08553 static void copy_aggregate_bcopy(WN *block, INT32 offset, TY_IDX srcTY,
08554 TY_IDX dstTY, WN *src, WN *dst, WN *size)
08555 {
08556 WN *call, *parms[3];
08557
08558 if (offset)
08559 {
08560 src = WN_Add(Pointer_type, src, WN_Intconst(Pointer_type, offset));
08561 dst = WN_Add(Pointer_type, dst, WN_Intconst(Pointer_type, offset));
08562 }
08563 markAddrTakenPassed(src);
08564 markAddrTakenPassed(dst);
08565
08566 parms[0]= WN_CreateParm(WN_rtype(src),
08567 src,
08568 srcTY ? srcTY : MTYPE_To_TY(WN_rtype(src)),
08569 WN_PARM_BY_VALUE);
08570
08571 parms[1]= WN_CreateParm(Pointer_type,
08572 dst,
08573 dstTY ? dstTY : MTYPE_To_TY(WN_rtype(dst)),
08574 WN_PARM_BY_VALUE);
08575
08576
08577 parms[2]= WN_CreateParm(WN_rtype(size),
08578 WN_COPY_Tree(size),
08579 MTYPE_To_TY(WN_rtype(size)),
08580 WN_PARM_BY_VALUE);
08581
08582 call= WN_Generate_Intrinsic_Call(block, INTRN_BCOPY, 3, parms);
08583 WN_Set_Linenum(call, current_srcpos);
08584 WN_INSERT_BlockLast(block, call);
08585 }
08586
08587
08588
08589
08590
08591
08592
08593
08594
08595
08596
08597
08598
08599
08600
08601
08602
08603
08604
08605
08606
08607 extern INT32 compute_copy_alignment(TY_IDX src, TY_IDX dst, INT32 offset)
08608 {
08609 INT32 srcAlign, dstAlign, align;
08610 INT32 max= MTYPE_alignment(Max_Uint_Mtype);
08611
08612 srcAlign= (src) ? TY_align(src) : max;
08613 dstAlign= (dst) ? TY_align(dst) : max;
08614
08615 align= MIN(srcAlign, dstAlign);
08616 align= MIN(align, max);
08617
08618 #ifndef KEY // bug 1990
08619 Is_True((compute_offset_alignment(offset, align) == align),
08620 ("compute_copy_alignment: alignment not consistent with offset"));
08621 #endif
08622
08623 return MIN(align, max);
08624 }
08625
08626
08627 extern TYPE_ID compute_copy_quantum(INT32 alignment)
08628 {
08629 if (UseAlignedCopyForStructs==FALSE)
08630 {
08631 INT32 maxAlign= MTYPE_alignment(Max_Uint_Mtype);
08632 INT32 ratio = Copy_Quantum_Ratio();
08633
08634 if (alignment*ratio < maxAlign)
08635 return Max_Uint_Mtype;
08636 }
08637
08638 #ifdef TARG_NVISA
08639 if (alignment > 4) {
08640
08641 DevWarn("for quantum change alignment from %d to 4", alignment);
08642 alignment = 4;
08643 }
08644 #endif
08645 return Mtype_AlignmentClass(alignment, MTYPE_CLASS_UNSIGNED_INTEGER);
08646 }
08647
08648 static TYPE_ID compute_next_copy_quantum(TYPE_ID quantum, INT32 alignment)
08649 {
08650 TYPE_ID next = Mtype_prev_alignment(quantum);
08651
08652 if (UseAlignedCopyForStructs==FALSE)
08653 {
08654 if ((MTYPE_alignment(next) > alignment) &&
08655 (next == MTYPE_U2 || next == MTYPE_I2))
08656 next = Mtype_prev_alignment(next);
08657 }
08658 return next;
08659 }
08660
08661
08662
08663
08664
08665
08666
08667
08668
08669
08670
08671
08672
08673
08674 static TY_IDX computeNewAlignmentTY(WN *addr, TY_IDX type, INT32 size,
08675 INT64 offset)
08676 {
08677 TY_IDX newType;
08678 INT32 align = TY_align(type);
08679 INT32 maxAlign = MTYPE_alignment(Max_Uint_Mtype);
08680
08681 if ((size <= align) || (align >= maxAlign))
08682 return TY_IDX_ZERO;
08683
08684
08685
08686
08687 newType = compute_alignment_type(addr, type, offset);
08688
08689 if (WN_operator_is(addr, OPR_LDA) && ST_class(WN_st(addr)) != CLASS_BLOCK)
08690 {
08691 ST *sym = WN_st(addr);
08692 TY_IDX symType = compute_alignment_type(addr, ST_type(sym), offset);
08693
08694
08695
08696
08697
08698
08699 if (ST_pu_defined(sym) && !Is_Allocated(sym))
08700 {
08701 INT32 stAlign;
08702
08703 stAlign = compute_offset_alignment(WN_lda_offset(addr), maxAlign);
08704 stAlign = compute_offset_alignment(offset, stAlign);
08705
08706 if (TY_align(symType) < stAlign)
08707 {
08708 if (traceAlignment)
08709 {
08710 DevWarn("realign ST %s (from %d to %d) line %d", ST_name(sym),
08711 TY_align(symType), stAlign, Srcpos_To_Line(current_srcpos));
08712 }
08713
08714
08715 symType = Make_Align_Type(symType, stAlign);
08716
08717 if ((ST_class(sym) == CLASS_CONST) &&
08718 (TCON_ty(STC_val(sym)) == MTYPE_STR) &&
08719 TY_is_pointer(Ty_Table[ST_type(sym)]))
08720 {
08721 symType = Make_Pointer_Type(newType);
08722 }
08723 Set_ST_type(sym, symType);
08724
08725 if (stAlign > align)
08726 {
08727 return Make_Align_Type(newType, stAlign);
08728 }
08729 return TY_IDX_ZERO;
08730 }
08731 }
08732 }
08733
08734 if (TY_align(newType) > align)
08735 return newType;
08736
08737 return TY_IDX_ZERO;
08738 }
08739
08740
08741
08742
08743 static WN *compute_new_size(WN *tree, WN *size, INT32 align)
08744 {
08745 if (Align_Padding)
08746 {
08747 INT64 sizeN = WN_const_val(size);
08748 INT64 residue = sizeN % align;
08749 INT32 popcnt = TARG_INT_Pop_Count(residue);
08750
08751 if (popcnt > 1)
08752 {
08753 INT64 newsize = sizeN + (align-residue);
08754
08755 return WN_Intconst(WN_rtype(size), newsize);
08756 }
08757 }
08758 return size;
08759 }
08760
08761
08762
08763
08764
08765
08766
08767
08768
08769
08770
08771
08772 static WN *improve_Malignment(WN *tree, WN *addr, WN *size, INT64 offset)
08773 {
08774 TY_IDX type, newType;
08775
08776 if (Align_Object == FALSE)
08777 return tree;
08778
08779 if (!WN_operator_is(size, OPR_INTCONST))
08780 {
08781 return tree;
08782 }
08783
08784 TY &tree_ty = Ty_Table[WN_ty(tree)];
08785
08786 if (TY_is_f90_pointer(tree_ty)) {
08787
08788 return tree;
08789 }
08790
08791 type = TY_pointed(tree_ty);
08792
08793 newType = computeNewAlignmentTY(addr, type, WN_const_val(size), offset);
08794
08795 if (newType)
08796 {
08797 if (traceAlignment)
08798 {
08799 DevWarn("realign OPCODE %s (from %d to %d) line %d",
08800 OPCODE_name(WN_opcode(tree)), TY_align(type), TY_align(newType),
08801 Srcpos_To_Line(current_srcpos));
08802 }
08803
08804 WN_set_ty(tree, Make_Pointer_Type(newType));
08805
08806 switch(WN_operator(tree))
08807 {
08808 case OPR_MSTORE:
08809 WN_kid2(tree)= compute_new_size(tree, size, TY_align(newType));
08810 break;
08811
08812 case OPR_MLOAD:
08813 WN_kid1(tree)= compute_new_size(tree, size, TY_align(newType));
08814 break;
08815 }
08816 }
08817
08818 return tree;
08819 }
08820
08821
08822
08823
08824
08825
08826
08827
08828
08829
08830
08831
08832
08833
08834
08835
08836
08837
08838
08839
08840
08841
08842
08843
08844 static WN *lower_mstore(WN * , WN *mstore, LOWER_ACTIONS actions)
08845 {
08846 WN *newblock;
08847 WN *load, *addr, *size;
08848 SRCPOS srcpos = WN_Get_Linenum(mstore);
08849 CURRENT_STATE mstate = pushCurrentState(mstore, actions);
08850
08851 load = WN_kid0(mstore);
08852 addr = WN_kid1(mstore);
08853 size = WN_kid2(mstore);
08854
08855 Is_True((WN_opcode(mstore) == OPC_MSTORE),
08856 ("expected MSTORE node, not %s", OPCODE_name(WN_opcode(mstore))));
08857
08858 if (WN_field_id (mstore) != 0)
08859 lower_field_id (mstore);
08860
08861 newblock = WN_CreateBlock();
08862 {
08863 TY_IDX dstTY = TY_pointed(Ty_Table[WN_ty(mstore)]);
08864 TY_IDX srcTY = TY_IDX_ZERO;
08865 WN *expr = load;
08866
08867
08868
08869
08870
08871 if (WN_opcode(load) == OPC_MLOAD)
08872 {
08873 #ifdef KEY
08874 if (WN_field_id(load) != 0)
08875 lower_field_id (load);
08876 #endif
08877
08878 srcTY = TY_pointed(Ty_Table[WN_ty(load)]);
08879 expr = WN_kid0(load);
08880
08881
08882
08883 if (WN_load_offset(load))
08884 #ifdef KEY
08885 if (WN_operator(expr) == OPR_LDA || WN_operator(expr) == OPR_ILDA) {
08886 WN_lda_offset(expr) += WN_load_offset(load);
08887 }
08888 else
08889 #endif
08890 {
08891 expr = WN_Add(Pointer_type,
08892 expr,
08893 WN_Intconst(Pointer_type, WN_load_offset(load)));
08894 WN_kid0(load)= expr;
08895 }
08896 }
08897 else
08898 {
08899 load = NULL;
08900 }
08901
08902 {
08903 INT32 copy_alignment;
08904 PREG_NUM dstPreg, srcPreg;
08905 TYPE_ID quantum;
08906 ST *preg= MTYPE_To_PREG(Pointer_type);
08907
08908 if (WN_store_offset(mstore))
08909 #ifdef KEY
08910 if (WN_operator(addr) == OPR_LDA || WN_operator(addr) == OPR_ILDA) {
08911 WN_lda_offset(addr) += WN_store_offset(mstore);
08912 }
08913 else
08914 #endif
08915 {
08916 addr = WN_Add(Pointer_type,
08917 addr,
08918 WN_Intconst(Pointer_type, WN_store_offset(mstore)));
08919 }
08920
08921 copy_alignment = compute_copy_alignment(srcTY, dstTY,
08922 WN_store_offset(mstore));
08923 quantum = compute_copy_quantum(copy_alignment);
08924
08925 switch(GenerateMstoreAction(size, 0, quantum, WN_kid0(mstore)))
08926 {
08927 case MSTORE_intrinsic_bzero:
08928 copy_aggregate_bzero(newblock, WN_ty(mstore), addr, size);
08929 break;
08930
08931 case MSTORE_intrinsic_memset:
08932 copy_aggregate_memset(newblock, WN_ty(mstore), expr, addr, size);
08933 break;
08934
08935 #ifdef KEY
08936 case MSTORE_intrinsic_memcpy:
08937 copy_aggregate_memcpy(newblock, 0,
08938 TY_pointer(srcTY), TY_pointer(dstTY),
08939 expr, addr, size);
08940 break;
08941
08942 #endif
08943 case MSTORE_intrinsic_bcopy:
08944 copy_aggregate_bcopy(newblock, 0, TY_pointer(srcTY), TY_pointer(dstTY),
08945 expr, addr, size);
08946 break;
08947
08948 case MSTORE_loop:
08949 #ifdef KEY // if the source and dest overlap, use smaller quantum
08950 if ((WN_operator(expr) == OPR_LDA || WN_operator(expr) == OPR_ILDA) &&
08951 WN_operator(expr) == WN_operator(addr) &&
08952 WN_st_idx(expr) == WN_st_idx(addr)) {
08953 WN_OFFSET diff = abs(WN_lda_offset(expr) - WN_lda_offset(addr));
08954 if (diff < MTYPE_byte_size(quantum) && diff != 0)
08955 quantum = Mtype_AlignmentClass(diff, MTYPE_CLASS_UNSIGNED_INTEGER);
08956 }
08957 #endif
08958 srcPreg = AssignExpr(newblock, expr, WN_rtype(expr));
08959 dstPreg = AssignExpr(newblock, addr, Pointer_type);
08960 copy_aggregate_loop(newblock, srcTY, dstTY, 0, size, quantum,
08961 srcPreg, dstPreg, load, mstore,
08962 copy_alignment, actions);
08963 break;
08964
08965 case MSTORE_aggregate:
08966 #ifdef KEY // if the source and dest overlap, use smaller quantum
08967 if (! UnweaveCopyForStructs &&
08968 (WN_operator(expr) == OPR_LDA || WN_operator(expr) == OPR_ILDA) &&
08969 WN_operator(expr) == WN_operator(addr) &&
08970 WN_st_idx(expr) == WN_st_idx(addr)) {
08971 WN_OFFSET diff = abs(WN_lda_offset(expr) - WN_lda_offset(addr));
08972 if (diff < MTYPE_byte_size(quantum) && diff != 0)
08973 quantum = Mtype_AlignmentClass(diff, MTYPE_CLASS_UNSIGNED_INTEGER);
08974 }
08975 #endif
08976 srcPreg = AssignExpr(newblock, expr, WN_rtype(expr));
08977 dstPreg = AssignExpr(newblock, addr, Pointer_type);
08978 copy_aggregate(newblock, srcTY, dstTY, 0, WN_const_val(size),
08979 quantum, srcPreg, dstPreg, load, mstore,
08980 copy_alignment, actions);
08981 break;
08982 }
08983 }
08984 }
08985
08986 WN_Delete( WN_kid2(mstore));
08987 WN_Delete(mstore);
08988
08989 newblock = lower_block(newblock, actions);
08990
08991 popCurrentState(mstate);
08992 return newblock;
08993 }
08994
08995
08996 static UINT64
08997 get_field_ofst (TY_IDX struct_type, UINT field_id)
08998 {
08999 Is_True (TY_kind (struct_type) == KIND_STRUCT, ("expecting KIND_STRUCT"));
09000 UINT cur_field_id = 0;
09001 FLD_HANDLE fld = FLD_get_to_field (struct_type, field_id, cur_field_id);
09002 Is_True (! fld.Is_Null(), ("Invalid field id %d for type 0x%x",
09003 field_id, struct_type));
09004 return FLD_ofst (fld);
09005 }
09006
09007
09008
09009
09010 static WN *lower_mistore_by_type(WN *block, WN *mistore, LOWER_ACTIONS actions)
09011 {
09012 WN *load, *addr, *expr;
09013 load = WN_kid0(mistore);
09014 CURRENT_STATE mstate = pushCurrentState(mistore, actions);
09015 Total_M_Count++;
09016
09017 if (WN_kid_count(load) > 0)
09018 WN_kid0(load) = lower_expr(block, WN_kid0(load), actions);
09019 if (WN_kid_count(mistore) > 1)
09020 WN_kid1(mistore) = lower_expr(block, WN_kid1(mistore), actions);
09021
09022 WN *base_expr;
09023 INT32 copy_alignment;
09024 PREG_NUM srcPreg;
09025 PREG_NUM dstPreg;
09026
09027 WN *newblock;
09028 newblock = WN_CreateBlock();
09029
09030 TY_IDX dstTY = (WN_kid_count(mistore) > 1) ? TY_pointed(Ty_Table[WN_ty(mistore)]) : WN_ty(mistore);
09031 TY_IDX srcTY = TY_IDX_ZERO;
09032 ST *preg= MTYPE_To_PREG(Pointer_type);
09033 INT32 initoffset=0;
09034 INT32 storeoffset=0;
09035 INT32 loadoffset=0;
09036
09037 srcTY = WN_ty(load);
09038 expr = (WN_kid_count(load) > 0) ? WN_kid0(load) : 0;
09039 addr = (WN_kid_count(mistore) > 1) ? WN_kid1(mistore) : 0;
09040
09041 if (WN_field_id(load) != 0 || WN_field_id(mistore) !=0) {
09042 WN_Delete(newblock);
09043 return NULL;
09044 }
09045
09046 loadoffset = WN_load_offset(load);
09047
09048 if (WN_store_offset(mistore)){
09049 storeoffset += WN_store_offset(mistore);
09050 }
09051
09052 copy_alignment = compute_copy_alignment(srcTY, dstTY,
09053 WN_store_offset(mistore));
09054
09055 TYPE_ID type;
09056 TY_IDX ty_idx;
09057 if (expr && !(WN_has_sym(expr))) {
09058 srcPreg = AssignExpr(newblock, expr, WN_rtype(expr));
09059 }
09060 if (addr && !(WN_has_sym(addr))) {
09061 dstPreg = AssignExpr(newblock, addr, WN_rtype(addr));
09062 }
09063
09064 INT32 offset = 0;
09065 INT32 size = TY_size(Ty_Table[srcTY]);
09066 UINT i = 1;
09067 UINT cur_field_id = 0;
09068
09069 FLD_ITER iter = Make_fld_iter (FLD_get_to_field (srcTY, i, cur_field_id));
09070 do {
09071 FLD fld = (*iter);
09072 WN *value, *address, *store;
09073
09074 ty_idx = fld.type;
09075 if ((fld.flags & FLD_IS_BIT_FIELD) || TY_size(ty_idx)<=0) {
09076 WN_Delete(newblock);
09077 return NULL;
09078 }
09079 offset = fld.ofst;
09080 type = TY_mtype(Ty_Table[ty_idx]);
09081 if(type == MTYPE_UNKNOWN)
09082 type = Fix_TY_mtype(ty_idx);
09083
09084
09085 if (WN_opcode(load) == OPC_MMLDID) {
09086 value = WN_Ldid(type, loadoffset+offset, WN_st(load), ty_idx);
09087 }
09088 else{
09089 if (WN_has_sym(expr) && WN_operator(expr)) {
09090 if (WN_operator(expr) == OPR_LDA) {
09091 value = WN_Ldid(type, WN_offset(expr)+loadoffset+offset, WN_st(expr), ty_idx, WN_field_id(expr));
09092 }
09093 else {
09094 if (TY_kind(ty_idx) == KIND_ARRAY || TY_kind(ty_idx) == KIND_STRUCT) {
09095 WN *ldid = WN_Ldid(Pointer_type,WN_offset(expr),WN_st(expr),WN_ty(expr), WN_field_id(expr));
09096 if(offset != 0)
09097 ldid = WN_Add(Pointer_type,
09098 ldid,
09099 WN_Intconst(Pointer_type, offset));
09100
09101 value = WN_Iload(type,
09102 loadoffset,
09103 ty_idx,
09104 ldid, 0);
09105 if (TY_kind(ty_idx) == KIND_STRUCT) FLD_get_to_field(ty_idx,999999,i);
09106 }
09107 else {
09108 WN *ldid = WN_Ldid(Pointer_type,WN_offset(expr),WN_st(expr),WN_ty(expr), WN_field_id(expr));
09109
09110 value = WN_Iload(type,
09111 loadoffset+offset,
09112 srcTY,
09113 ldid);
09114 WN_set_field_id(value,i);
09115 lower_copy_maps(load, value, actions);
09116 }
09117 }
09118 }
09119 else{
09120 if (TY_kind(ty_idx) == KIND_ARRAY || TY_kind(ty_idx) == KIND_STRUCT){
09121 value = WN_IloadLdid(type, loadoffset+offset,
09122 ty_idx,
09123 preg, srcPreg);
09124 if (TY_kind(ty_idx) == KIND_STRUCT) FLD_get_to_field(ty_idx,999999,i);
09125 }
09126 else{
09127 value = WN_IloadLdid(type, loadoffset+offset,
09128 srcTY,
09129 preg, srcPreg);
09130 WN_set_field_id(value,i);
09131 lower_copy_maps(load, value, actions);
09132 }
09133 }
09134 }
09135
09136
09137
09138 if (WN_kid_count(mistore) > 1) {
09139 if (WN_has_sym(addr) && WN_operator(addr)){
09140 if (WN_operator(addr) == OPR_LDA){
09141 store = WN_Stid(type, WN_offset(addr)+storeoffset+offset, WN_st(addr), ty_idx, value);
09142 }
09143 else {
09144 address = WN_Ldid(Pointer_type, WN_offset(addr), WN_st(addr), WN_ty(addr), WN_field_id(addr));
09145 if (!(TY_kind(ty_idx) == KIND_ARRAY || TY_kind(ty_idx) == KIND_STRUCT)){
09146 store = WN_Istore(type,
09147 storeoffset + offset,
09148 Make_Pointer_Type (dstTY),
09149 address,
09150 value);
09151 WN_set_field_id(store,i);
09152 }
09153 else {
09154 store = WN_Istore(type,
09155 storeoffset + offset,
09156 Make_Pointer_Type (ty_idx),
09157 address,
09158 value);
09159 }
09160 lower_copy_maps(mistore, store, actions);
09161 }
09162 }
09163 else {
09164 address = WN_Ldid(Pointer_type, dstPreg, preg, ST_type(preg));
09165 if(!(TY_kind(ty_idx) == KIND_ARRAY || TY_kind(ty_idx) == KIND_STRUCT)){
09166 store = WN_Istore(type,
09167 storeoffset + offset,
09168 Make_Pointer_Type (dstTY),
09169 address,
09170 value);
09171 WN_set_field_id(store,i);
09172 }
09173 else {
09174 store = WN_Istore(type,
09175 storeoffset + offset,
09176 Make_Pointer_Type (ty_idx),
09177 address,
09178 value);
09179 }
09180 lower_copy_maps(mistore, store, actions);
09181 }
09182 }
09183 else {
09184 store = WN_Stid(type,
09185 storeoffset + offset,
09186 WN_st(mistore),
09187 ty_idx,
09188 value);
09189 }
09190
09191 WN_copy_linenum(load, store);
09192 WN_INSERT_BlockLast(newblock, store);
09193 i++;
09194 } while (!FLD_last_field (iter++));
09195
09196 WN_Delete(mistore);
09197 newblock = lower_block(newblock, actions);
09198 Total_MLower_Count++;
09199 popCurrentState(mstate);
09200 return newblock;
09201 }
09202
09203
09204
09205
09206
09207
09208
09209
09210
09211
09212
09213
09214 static WN *lower_mload(WN * , WN *mload, LOWER_ACTIONS actions)
09215 {
09216 PREG_NUM srcPreg;
09217 TYPE_ID quantum;
09218 INT32 size, copy_alignment;
09219 WN *newblock;
09220
09221 Is_True((WN_opcode(mload) == OPC_MLOAD),
09222 ("expected MLOAD node, not %s", OPCODE_name(WN_opcode(mload))));
09223 Is_True((WN_operator_is(WN_kid1(mload), OPR_INTCONST)),
09224 ("expected MLOAD size constant "));
09225
09226 if (WN_field_id (mload) != 0)
09227 lower_field_id (mload);
09228
09229 WN *addr = WN_kid0(mload);
09230 INT32 offset = WN_load_offset(mload);
09231 TY_IDX srcTY = TY_pointed(Ty_Table[WN_ty(mload)]);
09232
09233 newblock = WN_CreateBlock();
09234
09235 size = WN_const_val( WN_kid1(mload) );
09236 copy_alignment = compute_copy_alignment( srcTY, TY_IDX_ZERO, offset );
09237 quantum = compute_copy_quantum( copy_alignment );
09238
09239 srcPreg = AssignExpr(newblock, addr, WN_rtype(addr));
09240
09241 while (size > 0)
09242 {
09243 INT32 stride = MTYPE_RegisterSize(quantum);
09244 INT32 nMoves = size / stride;
09245
09246
09247
09248
09249 while (nMoves > 0)
09250 {
09251 WN *value, *eval;
09252
09253
09254 value = WN_IloadLdid(quantum, offset, MTYPE_To_TY(quantum),
09255 MTYPE_To_PREG(Pointer_type), srcPreg);
09256
09257 lower_copy_maps(mload, value, actions);
09258
09259 eval = WN_CreateEval(value);
09260
09261 WN_INSERT_BlockLast(newblock, eval);
09262
09263 offset += stride;
09264 size -= stride;
09265 nMoves--;
09266 }
09267
09268
09269
09270
09271 if (size > 0)
09272 {
09273 quantum = compute_next_copy_quantum(quantum, copy_alignment);
09274 }
09275 }
09276
09277 WN_Delete( WN_kid1(mload));
09278 WN_Delete(mload);
09279
09280 newblock = lower_block(newblock, actions);
09281
09282 return newblock;
09283 }
09284
09285
09286
09287
09288
09289
09290
09291
09292
09293
09294
09295
09296
09297
09298 #ifdef TARG_IA64
09299 static void lower_compound_non_struct_actual (WN *block, WN *val, PLOC ploc,
09300 #else
09301 static void lower_complex_actual (WN *block, WN *val, PLOC ploc,
09302 #endif
09303 LOWER_ACTIONS actions)
09304 {
09305 WN *size, *mload, *addr;
09306 TY_IDX complexType = TY_Of_Expr(val);
09307
09308 size = WN_Intconst(Integer_type, TY_size(Ty_Table[complexType]));
09309
09310 addr = make_pointer_to_node(block, val);
09311
09312 mload = WN_CreateMload(0, Make_Pointer_Type(complexType), addr, size);
09313
09314 lower_mload_actual (block, mload, ploc, actions);
09315 }
09316
09317
09318
09319
09320
09321
09322
09323
09324
09325
09326
09327
09328
09329
09330 static void lower_mload_actual (WN *block, WN *mload, PLOC ploc,
09331 LOWER_ACTIONS actions)
09332 {
09333 ST *preg;
09334 INT32 size, mloadOffset = 0;
09335 PREG_NUM addrN;
09336
09337 if (WN_field_id(mload) != 0)
09338 lower_field_id (mload);
09339
09340 TY_IDX mloadTY = TY_pointed(Ty_Table[WN_ty(mload)]);
09341 WN *mloadSize = WN_kid1(mload);
09342
09343 if (WN_operator(mloadSize) != OPR_INTCONST) {
09344 DevWarn("mload_actual size is not INTCONST");
09345 if (WN_operator(mloadSize) == OPR_CVTL) {
09346 mloadSize = WN_kid0(mloadSize);
09347 }
09348 }
09349 size = WN_const_val(mloadSize);
09350 if (size<=0 || WN_operator(mloadSize) != OPR_INTCONST)
09351 {
09352 DevWarn("size of mload actual should be > 0");
09353 size = TY_size(Ty_Table[mloadTY]);
09354 DevWarn("adjusting size of (%s) to TY_size= %d",
09355 TY_name(Ty_Table[mloadTY]), size);
09356 mloadSize = WN_Intconst(Integer_type, size);
09357 }
09358
09359 Is_True((WN_opcode(mload) == OPC_MLOAD),
09360 ("expected MLOAD node, not %s", OPCODE_name(WN_opcode(mload))));
09361
09362 Setup_Struct_Output_Parameter_Locations(mloadTY);
09363 ploc = Get_Struct_Output_Parameter_Location(ploc);
09364
09365
09366
09367
09368
09369 preg = MTYPE_To_PREG(Pointer_type);
09370 {
09371 WN *addr = WN_COPY_Tree(WN_kid0(mload));
09372
09373 if (WN_load_offset(mload))
09374 {
09375 addr = WN_Add(Pointer_type,
09376 addr,
09377 WN_Intconst(Pointer_type, WN_load_offset(mload)));
09378 }
09379 addrN = AssignExpr(block, addr, Pointer_type);
09380 }
09381
09382 while (PLOC_is_nonempty(ploc))
09383 {
09384 if (PLOC_on_stack(ploc))
09385 {
09386 PREG_NUM dstPreg;
09387
09388
09389
09390
09391
09392
09393 {
09394 WN *add;
09395 INT64 offset;
09396
09397 offset = PLOC_offset(ploc) - Formal_Save_Area_Size
09398 + Stack_Offset_Adjustment - mloadOffset;
09399
09400 add = WN_Add(Pointer_type,
09401 WN_LdidPreg(Pointer_type, Stack_Pointer_Preg_Offset),
09402 WN_Intconst(Pointer_type, offset));
09403 dstPreg = AssignExpr(block, add, Pointer_type);
09404 }
09405 {
09406 TY_IDX srcTY = mloadTY;
09407 TY_IDX dstTY = MTYPE_To_TY(Max_Uint_Mtype);
09408 TYPE_ID quantum;
09409 WN *con;
09410 INT32 copy_alignment, nMoves;
09411 INT32 todo= size - mloadOffset;
09412
09413
09414
09415
09416 copy_alignment= compute_copy_alignment(srcTY, dstTY, 0);
09417 quantum = compute_copy_quantum(copy_alignment);
09418
09419
09420
09421
09422
09423 nMoves= calculateLoadStore(todo, mloadOffset, quantum, WN_kid0(mload));
09424
09425 if (MinStructCopyLoopSize && MinStructCopyLoopSize <= nMoves)
09426 {
09427 con = WN_Intconst(Integer_type, todo);
09428
09429 copy_aggregate_loop(block, srcTY, dstTY, mloadOffset, con,
09430 quantum, addrN, dstPreg, mload, NULL,
09431 copy_alignment, actions);
09432 WN_Delete(con);
09433 }
09434 else
09435 {
09436 copy_aggregate(block, srcTY, dstTY, mloadOffset, todo,
09437 quantum, addrN, dstPreg, mload, NULL,
09438 copy_alignment, actions);
09439 }
09440 }
09441 return;
09442 }
09443 else
09444 {
09445
09446
09447
09448 PREG_NUM regNo = PLOC_reg(ploc);
09449 #ifdef TARG_NVISA
09450 ST *reg;
09451 if (Preg_Offset_Is_Float32(regNo))
09452 reg = Float32_Preg;
09453 else if (Preg_Offset_Is_Float64(regNo))
09454 reg = Float64_Preg;
09455 else if (Preg_Offset_Is_Int64(regNo))
09456 reg = Int64_Preg;
09457 else
09458 reg = Int32_Preg;
09459 #else
09460 ST *reg = Preg_Offset_Is_Float(regNo) ? Float_Preg : Int_Preg;
09461 #endif
09462 TYPE_ID type = TY_mtype(Ty_Table[ST_type(reg)]);
09463
09464 {
09465 WN *load, *stid;
09466 INT32 todo = size - mloadOffset;
09467
09468 if (PLOC_size(ploc) < MTYPE_size_reg(type)
09469 && type == MTYPE_F8 && PLOC_size(ploc) == 4)
09470 {
09471 #ifndef TARG_X8664 // can happen in reality for X86-64
09472
09473 DevWarn("actual_mload: switch from mtype_f8 to mtype_f4");
09474 #endif
09475 type = MTYPE_F4;
09476 reg = MTYPE_To_PREG(type);
09477 }
09478
09479
09480
09481
09482
09483 if (todo < MTYPE_alignment(type))
09484 {
09485 TYPE_ID quantum;
09486 INT32 newAlign, shiftn;
09487
09488 Is_True(Preg_Offset_Is_Int(regNo),
09489 ("mload actual->reg(size/alignment problem"));
09490 newAlign = nearest_power_of_two(todo);
09491
09492 quantum = Mtype_AlignmentClass(newAlign, MTYPE_type_class(type));
09493
09494 load = WN_IloadLdid(quantum, mloadOffset,
09495 struct_memop_type (quantum, mloadTY), preg,
09496 addrN);
09497
09498 lower_copy_maps(mload, load, actions);
09499
09500 if (Target_Byte_Sex == BIG_ENDIAN) {
09501 shiftn = MTYPE_size_reg(type) - MTYPE_size_reg(quantum);
09502
09503 load = WN_Shl(type, load, WN_Intconst(type, shiftn));
09504 }
09505 }
09506 else
09507 {
09508 load = WN_IloadLdid(type, mloadOffset,
09509 struct_memop_type (type, mloadTY), preg,
09510 addrN);
09511
09512 lower_copy_maps(mload, load, actions);
09513 }
09514
09515 stid= WN_Stid(type, regNo, reg, ST_type(reg), load);
09516 WN_Set_Linenum(stid, current_srcpos);
09517 WN_INSERT_BlockLast(block, stid);
09518 }
09519 }
09520 mloadOffset += PLOC_size(ploc);
09521 ploc = Get_Struct_Output_Parameter_Location(ploc);
09522 }
09523 }
09524
09525
09526
09527
09528
09529
09530
09531
09532
09533
09534
09535 static void lower_mload_formal(WN *block, WN *mload, PLOC ploc,
09536 LOWER_ACTIONS actions)
09537 {
09538 INT32 size, offset = 0;
09539 ST *sym = WN_st(mload);
09540 TY_IDX symTY = ST_type(sym);
09541
09542 Setup_Struct_Input_Parameter_Locations(symTY);
09543 ploc = Get_Struct_Input_Parameter_Location(ploc);
09544 size = TY_size(Ty_Table[symTY]);
09545
09546 while (PLOC_is_nonempty(ploc))
09547 {
09548 if (PLOC_on_stack(ploc))
09549 {
09550
09551
09552
09553 return;
09554 }
09555 else
09556 {
09557
09558
09559
09560 PREG_NUM regNo = PLOC_reg(ploc);
09561 #ifdef TARG_NVISA
09562 ST *reg;
09563 if (Preg_Offset_Is_Float32(regNo))
09564 reg = Float32_Preg;
09565 else if (Preg_Offset_Is_Float64(regNo))
09566 reg = Float64_Preg;
09567 else if (Preg_Offset_Is_Int64(regNo))
09568 reg = Int64_Preg;
09569 else
09570 reg = Int32_Preg;
09571 #else
09572 ST *reg = Preg_Offset_Is_Float(regNo) ? Float_Preg : Int_Preg;
09573 #endif
09574 TYPE_ID type = TY_mtype(ST_type(reg));
09575 INT32 todo = size - offset;
09576 {
09577 WN *ldid, *store;
09578
09579 if (PLOC_size(ploc) < MTYPE_size_reg(type)
09580 && type == MTYPE_F8 && PLOC_size(ploc) == 4)
09581 {
09582 #ifndef TARG_X8664 // can happen in reality for X86-64
09583
09584 DevWarn("formal_mload: switch from mtype_f8 to mtype_f4");
09585 #endif
09586 type = MTYPE_F4;
09587 reg = MTYPE_To_PREG(type);
09588 }
09589
09590 ldid = WN_LdidPreg(type, regNo);
09591
09592
09593
09594
09595 if (todo < MTYPE_alignment(type))
09596 {
09597 TYPE_ID quantum;
09598 INT32 newAlign, shiftn;
09599
09600 Is_True(Preg_Offset_Is_Int(regNo),
09601 ("mload actual->reg(size/alignment problem"));
09602 newAlign = nearest_power_of_two(todo);
09603
09604 quantum = Mtype_AlignmentClass(newAlign, MTYPE_type_class(type));
09605
09606 shiftn = MTYPE_size_reg(type) - MTYPE_size_reg(quantum);
09607
09608 if (Target_Byte_Sex == BIG_ENDIAN) {
09609
09610
09611
09612
09613
09614 if (MTYPE_alignment(quantum) == 4)
09615 {
09616 ldid= WN_Ashr(type, ldid, WN_Intconst(type, shiftn));
09617 }
09618 else
09619 {
09620 ldid= WN_Lshr(type, ldid, WN_Intconst(type, shiftn));
09621 }
09622 }
09623
09624 store = WN_Stid (quantum, offset, sym,
09625 struct_memop_type (quantum, symTY) , ldid);
09626 }
09627 else
09628 {
09629 store = WN_Stid (type, offset, sym, struct_memop_type (type, symTY),
09630 ldid);
09631 }
09632 lower_copy_maps(mload, store, actions);
09633 WN_Set_Linenum(store, current_srcpos);
09634 WN_INSERT_BlockLast(block, store);
09635 }
09636 offset += PLOC_size(ploc);
09637 }
09638 ploc = Get_Struct_Input_Parameter_Location(ploc);
09639 }
09640 }
09641
09642
09643
09644
09645
09646
09647
09648
09649
09650
09651
09652
09653
09654 static void lower_complex_emulation(WN *block, WN *tree, LOWER_ACTIONS actions,
09655 WN **realpart, WN **imagpart)
09656 {
09657 WN *wn;
09658 BOOL intrinsic_lowered;
09659
09660 Is_True(MTYPE_is_complex(WN_rtype(tree)),
09661 ("expected complex type in lower_complex_emulation"));
09662
09663
09664
09665
09666
09667
09668
09669
09670 wn = lower_emulation(block, tree, actions, intrinsic_lowered);
09671
09672
09673
09674 if (!intrinsic_lowered) {
09675 actions |= LOWER_INTRINSIC;
09676 }
09677 #ifdef TARG_X8664 // for C4INTRINSIC_OP, wn is type MTYPE_F8
09678 if (WN_rtype(wn) == MTYPE_F8) {
09679 ST *c4temp_st = Gen_Temp_Symbol(MTYPE_To_TY(MTYPE_F8), ".c4");
09680 WN *stid = WN_Stid(MTYPE_F8, 0, c4temp_st, MTYPE_To_TY(MTYPE_F8), wn);
09681 WN_Set_Linenum (stid, WN_Get_Linenum(tree));
09682 WN_INSERT_BlockLast(block, stid);
09683
09684 *realpart = WN_Ldid(MTYPE_F4, 0, c4temp_st, MTYPE_To_TY(MTYPE_F4));
09685 *imagpart = WN_Ldid(MTYPE_F4, 4, c4temp_st, MTYPE_To_TY(MTYPE_F4));
09686 }
09687 else
09688 #endif
09689 lower_complex_expr(block, wn, actions, realpart, imagpart);
09690 }
09691
09692
09693
09694
09695
09696
09697
09698
09699
09700
09701
09702
09703
09704
09705
09706 static WN *lower_emulation(WN *block, WN *tree, LOWER_ACTIONS actions,
09707 BOOL & intrinsic_lowered)
09708 {
09709 WN *wn, *emBlock, *node;
09710 OPCODE op = WN_opcode(tree);
09711
09712 intrinsic_lowered = FALSE;
09713
09714
09715
09716
09717 {
09718 INT32 i;
09719
09720 for (i = 0; i < WN_kid_count(tree); i++)
09721 WN_actual(tree,i) = lower_expr(block, WN_actual(tree,i), actions);
09722 }
09723
09724
09725
09726
09727 wn = NULL;
09728 emBlock = WN_CreateBlock();
09729
09730 if (OPCODE_is_intrinsic(WN_opcode(tree)))
09731 {
09732 Is_True((INTRN_is_nary(WN_intrinsic(tree))==FALSE),("nary slipped by"));
09733 if (Action(LOWER_INLINE_INTRINSIC) || Action(LOWER_INL_STACK_INTRINSIC))
09734 {
09735 wn = emulate(emBlock , tree);
09736 }
09737 #ifdef KEY // bug 6938
09738 else if (Action(LOWER_FAST_EXP) && OPCODE_is_intrinsic(WN_opcode(tree)))
09739 {
09740 wn = emulate_fast_exp(emBlock , tree);
09741 }
09742 #endif
09743 if (wn == NULL && NotAction(LOWER_INTRINSIC))
09744 {
09745 return tree;
09746 }
09747 intrinsic_lowered = TRUE;
09748 }
09749
09750
09751
09752 else
09753 {
09754 wn = emulate(emBlock , tree);
09755 }
09756
09757
09758 if (wn)
09759 {
09760 #ifdef KEY
09761
09762
09763 for (node = WN_first(emBlock); node; node = WN_next(node)) {
09764 WN_Set_Linenum(node, current_srcpos);
09765 }
09766 #endif
09767
09768 emBlock = lower_block(emBlock, actions);
09769 WN_INSERT_BlockLast(block, emBlock);
09770
09771
09772
09773
09774 if (OPCODE_is_stmt(WN_opcode(wn)))
09775 {
09776 WN_Set_Linenum(wn, current_srcpos);
09777 wn = lower_stmt(block, wn, actions);
09778 }
09779 else if (OPCODE_is_expression(WN_opcode(wn)))
09780 {
09781 wn = lower_expr(block, wn, actions);
09782 }
09783 }
09784 else
09785 {
09786 WN_Delete(emBlock);
09787
09788 if (OPCODE_is_call(op))
09789 {
09790 wn = lower_intrinsic(block, tree, actions);
09791 }
09792 else
09793 {
09794 wn = lower_intrinsic_op(block, tree, actions);
09795 }
09796 }
09797 return wn;
09798 }
09799
09800 #if defined(linux) || defined(__CYGWIN__) || defined(__MINGW32__)
09801
09802
09803
09804
09805
09806
09807
09808
09809
09810
09811
09812
09813
09814
09815
09816
09817
09818
09819
09820
09821
09822
09823
09824
09825
09826 static WN *lower_cis_intrinsic(WN *block, WN *tree, LOWER_ACTIONS actions)
09827 {
09828 WN *callblock, *call, *parms[3];
09829 INTRINSIC sincos_id;
09830 TYPE_ID real_mtyp, complex_mtyp;
09831 TY_IDX real_ty, complex_ty;
09832 ST *return_sincos;
09833 WN *asinx, *acosx;
09834
09835 complex_mtyp = WN_rtype(tree);
09836 real_mtyp = Mtype_complex_to_real(complex_mtyp);
09837 complex_ty = MTYPE_To_TY(complex_mtyp);
09838 real_ty = MTYPE_To_TY(real_mtyp);
09839
09840 return_sincos = Gen_Temp_Symbol(complex_ty, ".sincos");
09841 acosx = WN_CreateLda(OPR_LDA, Pointer_Mtype, MTYPE_V,
09842 0,
09843 Make_Pointer_Type(real_ty), return_sincos);
09844 asinx = WN_CreateLda(OPR_LDA, Pointer_Mtype, MTYPE_V,
09845 MTYPE_byte_size(real_mtyp),
09846 Make_Pointer_Type(real_ty), return_sincos);
09847
09848 switch (real_mtyp) {
09849 case MTYPE_F4: sincos_id = INTRN_SINCOSF; break;
09850 case MTYPE_F8: sincos_id = INTRN_SINCOS; break;
09851 case MTYPE_F10: sincos_id = INTRN_SINCOSL; break;
09852 default: sincos_id = INTRINSIC_INVALID; break;
09853 }
09854
09855 parms[0] = WN_kid0(tree);
09856 parms[1] = WN_CreateParm(Pointer_type, asinx, MTYPE_To_TY(Pointer_type),
09857 WN_PARM_BY_VALUE);
09858 parms[2] = WN_CreateParm(Pointer_type, acosx, MTYPE_To_TY(Pointer_type),
09859 WN_PARM_BY_VALUE);
09860 call = WN_Create_Intrinsic(OPC_VINTRINSIC_CALL, sincos_id, 3, parms);
09861 WN_Set_Linenum(call, current_srcpos);
09862 #ifndef KEY // cannot delete because it needs to be around to be looked at after
09863
09864 WN_Delete(tree);
09865 #endif
09866
09867 call = lower_intrinsic_call(block, call, actions);
09868 WN_INSERT_BlockLast(block, call);
09869
09870 WN *ldid = WN_Ldid(complex_mtyp, 0, return_sincos, complex_ty);
09871 return lower_expr(block, ldid, actions);
09872 }
09873 #endif
09874
09875
09876
09877
09878
09879
09880
09881
09882
09883
09884
09885
09886
09887
09888
09889
09890
09891
09892
09893 static WN *lower_intrinsic_op(WN *block, WN *tree, LOWER_ACTIONS actions)
09894 {
09895 WN *wn;
09896 OPCODE op = WN_opcode(tree);
09897 INTRINSIC id = WN_intrinsic(tree);
09898
09899 Is_True(Action(LOWER_INTRINSIC),
09900 ("actions does not contain LOWER_INTRINSIC"));
09901 Is_True(OPCODE_is_intrinsic(op),
09902 ("expression is not intrinsic"));
09903
09904 #if !defined(IRIX)
09905 switch (id) {
09906 case INTRN_F4CIS:
09907 case INTRN_F8CIS:
09908
09909 #ifdef KEY
09910 if (! Is_Target_R10K())
09911 #endif
09912 return lower_cis_intrinsic(block, tree, actions);
09913 }
09914 #endif
09915
09916
09917
09918
09919
09920 wn = lower_intrinsic(block, tree, actions);
09921
09922 Is_True(OPCODE_is_call(WN_opcode(wn)),
09923 ("lowered instrinsic op is not a call"));
09924 WN_Set_Linenum(wn, current_srcpos);
09925 WN_INSERT_BlockLast(block, wn);
09926
09927 {
09928 TYPE_ID ty1, ty2;
09929 PREG_NUM reg1, reg2;
09930 TYPE_ID type = WN_rtype(tree);
09931 #ifdef TARG_X8664
09932 if (Is_Target_64bit() && type == MTYPE_C4)
09933 type = MTYPE_F8;
09934 #endif
09935
09936 rename_preg(INTR_intrinsic_name(tree), ".return");
09937
09938 if (WHIRL_Return_Info_On) {
09939
09940 RETURN_INFO return_info = Get_Return_Info (MTYPE_To_TY(type),
09941 Complex_Not_Simulated
09942 #ifdef TARG_X8664
09943 , FALSE
09944 #endif
09945 );
09946
09947 if (RETURN_INFO_count(return_info) <= 2) {
09948
09949 ty1 = RETURN_INFO_mtype (return_info, 0);
09950 ty2 = RETURN_INFO_mtype (return_info, 1);
09951 reg1 = RETURN_INFO_preg (return_info, 0);
09952 reg2 = RETURN_INFO_preg (return_info, 1);
09953 }
09954
09955 else
09956 Fail_FmtAssertion("lower_intrinsic_op: more than 2 return registers");
09957
09958 }
09959
09960 else
09961 Get_Return_Mtypes(MTYPE_To_TY(type), Complex_Not_Simulated, &ty1, &ty2);
09962
09963 switch(type)
09964 {
09965 case MTYPE_C4:
09966 case MTYPE_C8:
09967 case MTYPE_C10:
09968 #ifdef TARG_X8664
09969 if (Is_Target_64bit())
09970 #endif
09971 {
09972 PREG_NUM rzN, izN;
09973 TYPE_ID real = Mtype_complex_to_real(type);
09974
09975 if (!WHIRL_Return_Info_On)
09976 Get_Return_Pregs ( ty1, ty2, ®1, ®2 );
09977 Is_True((reg1 && reg2),
09978 ("expected complex return value from intrinsic_op"));
09979
09980 rzN = AssignExpr(block, WN_LdidPreg(real, reg1), real);
09981 izN = AssignExpr(block, WN_LdidPreg(real, reg2), real);
09982
09983 wn = WN_Complex(type,
09984 WN_LdidPreg(real, rzN),
09985 WN_LdidPreg(real, izN));
09986 break;
09987 }
09988 #ifdef TARG_X8664
09989
09990 #endif
09991
09992 case MTYPE_CQ:
09993
09994
09995
09996
09997
09998
09999 {
10000 TYPE_ID real = Mtype_complex_to_real(type);
10001 TY_IDX realTY = MTYPE_To_TY(real);
10002 WN *temp,*temp1, *actual = WN_kid0(wn);
10003
10004 if (WN_operator_is(actual, OPR_PARM))
10005 actual = WN_kid0(actual);
10006
10007 temp = lower_copy_tree( actual, actions);
10008 temp1 = lower_copy_tree( actual, actions);
10009
10010 Is_True((OPCODE_is_call(WN_opcode(wn))), ("expected call opcode"));
10011
10012 wn = WN_Complex(type,
10013 WN_Iload(real, 0, realTY, temp),
10014 WN_Iload(real, MTYPE_RegisterSize(real),
10015 realTY, temp1));
10016 }
10017 break;
10018
10019 default:
10020 {
10021 PREG_NUM retReg;
10022
10023 if (!WHIRL_Return_Info_On)
10024 Get_Return_Pregs ( ty1, ty2, ®1, ®2 );
10025
10026 Is_True((reg1 != 0), ("expected return value from intrinsic_op"));
10027 Is_True((reg2 == 0), ("cannot evaluate 2 regs into an expression"));
10028
10029 retReg = AssignExpr(block,
10030 WN_LdidPreg(ty1, reg1),
10031 type);
10032
10033 wn = WN_LdidPreg(type, retReg);
10034 }
10035 break;
10036 }
10037 rename_reset();
10038 }
10039
10040
10041
10042
10043
10044
10045
10046
10047
10048
10049 switch (id) {
10050 case INTRN_CEQEXPR:
10051 wn = WN_EQ(Boolean_type, wn, WN_Zerocon(Boolean_type));
10052 break;
10053 case INTRN_CNEEXPR:
10054 wn = WN_NE(Boolean_type, wn, WN_Zerocon(Boolean_type));
10055 break;
10056 case INTRN_CGEEXPR:
10057 wn = WN_GE(Boolean_type, wn, WN_Zerocon(Boolean_type));
10058 break;
10059 case INTRN_CGTEXPR:
10060 wn = WN_GT(Boolean_type, wn, WN_Zerocon(Boolean_type));
10061 break;
10062 case INTRN_CLEEXPR:
10063 wn = WN_LE(Boolean_type, wn, WN_Zerocon(Boolean_type));
10064 break;
10065 case INTRN_CLTEXPR:
10066 wn = WN_LT(Boolean_type, wn, WN_Zerocon(Boolean_type));
10067 break;
10068 }
10069
10070
10071
10072
10073 return lower_expr(block, wn, actions);
10074 }
10075
10076
10077
10078
10079
10080
10081
10082
10083
10084
10085
10086
10087
10088
10089 static WN *lower_intrinsic(WN *block, WN *tree, LOWER_ACTIONS actions)
10090 {
10091
10092 Is_True(Action(LOWER_INTRINSIC),
10093 ("actions does not contain LOWER_INTRINSIC"));
10094 Is_True(OPCODE_is_intrinsic(WN_opcode(tree)),
10095 ("expression is not intrinsic"));
10096
10097 {
10098 INTRINSIC id = (INTRINSIC) WN_intrinsic(tree);
10099
10100 if (INTRN_is_actual(id))
10101 {
10102
10103
10104
10105
10106 TYPE_ID rtype = WN_rtype(tree);
10107 WN *lda;
10108 {
10109 TY_IDX ty = Make_Function_Type(MTYPE_To_TY(rtype));
10110 ST *st = Gen_Intrinsic_Function(ty, INTRN_rt_name(id));
10111 lda = WN_Lda(Pointer_type, 0, st);
10112 }
10113
10114 WN_Delete(tree);
10115 return lower_expr(block, lda, actions);
10116 }
10117 }
10118 {
10119
10120
10121
10122
10123 WN *call, *callblock;
10124
10125 callblock = WN_CreateBlock();
10126
10127 call = intrinsic_runtime(callblock, tree);
10128
10129 callblock = lower_block(callblock, actions);
10130 WN_INSERT_BlockLast(block, callblock);
10131
10132 if (Action(LOWER_TO_CG))
10133 actions |= LOWER_CALL;
10134 call = lower_call(block, call, actions);
10135
10136 return call;
10137 }
10138 }
10139
10140
10141
10142
10143
10144
10145
10146
10147
10148
10149
10150
10151 static WN *lower_actual(WN *block, WN *actual, TYPE_ID parmType, INT32 reg)
10152 {
10153 #ifndef TARG_SL
10154
10155
10156
10157 if (MTYPE_float(parmType) && Preg_Offset_Is_Int(reg))
10158 {
10159 TYPE_ID type = TY_mtype(ST_type(Int_Preg));
10160
10161 actual = WN_Tas(type, ST_type(Int_Preg), actual);
10162 }
10163 #endif
10164
10165 {
10166 WN *stid;
10167 ST *regST;
10168
10169 #ifdef TARG_X8664
10170 if (Is_Target_64bit() && parmType == MTYPE_C4) {
10171 regST = MTYPE_To_PREG(MTYPE_F8);
10172 WN_set_rtype(actual, MTYPE_F8);
10173 WN_set_desc( actual,
10174 WN_operator_is(actual,OPR_CONST) ? MTYPE_V : MTYPE_F8 );
10175 }
10176 else
10177 #endif
10178
10179 #if defined(TARG_NVISA)
10180 regST = Standard_Preg_For_Mtype(parmType);
10181 #else
10182 if (Preg_Offset_Is_Int(reg)) {
10183 #if defined(TARG_SL)
10184
10185 #if defined(EMULATE_LONGLONG)
10186 if (parmType == MTYPE_I8 || parmType == MTYPE_U8)
10187 regST = Int64_Preg;
10188 else
10189 regST = Int_Preg;
10190 #endif
10191
10192 #if defined(EMULATE_FLOAT_POINT)
10193 if (parmType == MTYPE_F8)
10194 regST = Float64_Preg;
10195 if (parmType == MTYPE_F4)
10196 regST = Float32_Preg;
10197 #endif
10198
10199 #else // !defined(TARG_SL)
10200 regST = Int_Preg;
10201 #endif // defined(TARG_SL)
10202 }
10203 else
10204
10205 regST= MTYPE_To_PREG(parmType);
10206 #endif
10207
10208 TYPE_ID type = TY_mtype(ST_type(regST));
10209
10210 stid = WN_StidIntoPreg (type, reg, regST, actual);
10211 WN_Set_Linenum(stid, current_srcpos);
10212 WN_INSERT_BlockLast(block, stid);
10213 }
10214
10215 return actual;
10216 }
10217
10218
10219
10220
10221
10222
10223
10224
10225
10226
10227 static WN *lower_profile_call(WN *block, WN *tree, INT32 state,
10228 LOWER_ACTIONS actions)
10229 {
10230 if (Gen_Profile && WN_has_sym(current_function))
10231 {
10232 WN *profcall;
10233 char *name;
10234
10235 {
10236 TY_IDX ty = Make_Function_Type(MTYPE_To_TY(MTYPE_V));
10237 ST *st = Gen_Intrinsic_Function(ty, Gen_Profile_Name);
10238
10239 Set_PU_no_side_effects(Pu_Table[ST_pu(st)]);
10240 Set_PU_is_pure(Pu_Table[ST_pu(st)]);
10241
10242 profcall = WN_Call(MTYPE_V, MTYPE_V, 5, st);
10243 }
10244
10245 ST *current_fcn_st = WN_st(current_function);
10246
10247 WN_actual(profcall, 0) = WN_Lda(Pointer_type, 0, current_fcn_st);
10248 name = ST_name(current_fcn_st);
10249 WN_actual(profcall, 2) = WN_LdaString(name, 0, strlen(name)+1);
10250 WN_actual(profcall, 4) = WN_Intconst(MTYPE_I4, state);
10251
10252 if (WN_has_sym(tree))
10253 {
10254 ST *st = WN_st(tree);
10255
10256 WN_actual(profcall, 1) = WN_Lda(Pointer_type, 0, st);
10257 name = ST_name(st);
10258 WN_actual(profcall, 3) = WN_LdaString(name, 0, strlen(name)+1);
10259 }
10260 else
10261 {
10262 Is_True((WN_operator_is(tree, OPR_ICALL)),
10263 ("expected icall node, not %s", OPCODE_name(WN_opcode(tree))));
10264
10265 WN_actual(profcall, 1)
10266 = lower_copy_tree(WN_actual(tree, WN_num_actuals(tree)), actions);
10267 WN_actual(profcall, 3) = WN_Zerocon(Pointer_type);
10268 }
10269
10270 Gen_Profile = FALSE;
10271 profcall = lower_call(block, profcall, actions);
10272 Gen_Profile = TRUE;
10273
10274 return profcall;
10275 }
10276 return NULL;
10277 }
10278
10279 #ifdef TARG_X8664
10280
10281
10282
10283
10284
10285
10286
10287
10288
10289 static WN *take_out_special_ia32_ops(WN *block, WN *tree)
10290 {
10291 if (MTYPE_is_integral(WN_rtype(tree)) &&
10292 (WN_operator(tree) == OPR_DIV ||
10293 WN_operator(tree) == OPR_REM ||
10294 WN_operator(tree) == OPR_MOD ||
10295 ((WN_operator(tree) == OPR_ASHR ||
10296 WN_operator(tree) == OPR_LSHR ||
10297 WN_operator(tree) == OPR_SHL ||
10298 WN_operator(tree) == OPR_RROTATE) &&
10299 WN_operator(WN_kid(tree,1)) != OPR_INTCONST)) ||
10300 WN_operator(tree) == OPR_CVT && MTYPE_is_float(WN_rtype(tree)) &&
10301 (WN_desc(tree) == MTYPE_U8 && Is_Target_64bit() ||
10302 WN_desc(tree) == MTYPE_U4 && Is_Target_32bit()) ||
10303 Is_Target_64bit() &&
10304 (WN_opcode(tree) == OPC_U8F4TRUNC || WN_opcode(tree) == OPC_U8F8TRUNC)) {
10305 TYPE_ID mtype = WN_rtype(tree);
10306 TY_IDX ty_idx = MTYPE_To_TY(mtype);
10307 ST *temp_st = Gen_Temp_Symbol(ty_idx, ".unnested_parm");
10308 WN *stid = WN_Stid(mtype, 0, temp_st, ty_idx, tree);
10309 WN_Set_Linenum (stid, current_srcpos);
10310 WN_INSERT_BlockLast(block, stid);
10311 WN *ldid = WN_Ldid(mtype, 0, temp_st, ty_idx);
10312 return ldid;
10313 }
10314
10315 for (INT i = 0; i < WN_kid_count(tree); i++)
10316 WN_kid(tree,i) = take_out_special_ia32_ops(block, WN_kid(tree,i));
10317 return tree;
10318 }
10319 #endif
10320
10321
10322
10323
10324
10325
10326
10327
10328
10329
10330 static WN *lower_call(WN *block, WN *tree, LOWER_ACTIONS actions)
10331 {
10332 INT16 i;
10333 PLOC ploc;
10334 TY_IDX call_ty;
10335 WN *callblock;
10336 SRCPOS srcpos = WN_Get_Linenum(tree);
10337 INT num_actuals = WN_num_actuals(tree);
10338 ST *callee_st = NULL;
10339
10340 Is_True(OPERATOR_is_call(WN_operator(tree)),
10341 ("expected call node, not %s", OPERATOR_name(WN_operator(tree))));
10342
10343
10344 TLS_init();
10345
10346
10347
10348
10349 if( Action(LOWER_TO_CG) &&
10350 (TLS_model == TLS_MODEL_GLOBAL_DYNAMIC ||
10351 TLS_model == TLS_MODEL_LOCAL_DYNAMIC )) {
10352 #if !defined(TARG_SL)
10353 promote_tls_ldst = TRUE;
10354 #else
10355 promote_tls_ldst = FALSE;
10356 #endif
10357 }
10358
10359 for (i = 0; i < WN_kid_count(tree); i++) {
10360 #ifdef KEY // handle actual parameter being a complex under LOWER_COMPLEX action
10361 if (WN_operator(WN_actual(tree,i)) == OPR_PARM &&
10362 MTYPE_is_complex(WN_rtype(WN_actual(tree,i))) &&
10363 !OPERATOR_is_leaf(WN_operator(WN_kid0(WN_actual(tree,i)))) &&
10364 Action(LOWER_COMPLEX))
10365 {
10366 TYPE_ID mtype = WN_rtype(WN_actual(tree,i));
10367 WN *parm_tree = WN_kid0(WN_actual(tree,i));
10368 TY_IDX ty_idx = MTYPE_To_TY(mtype);
10369 ST *temp_st = Gen_Temp_Symbol(ty_idx, ".complex_parm");
10370 WN *stid = WN_Stid(mtype, 0, temp_st, ty_idx, parm_tree);
10371 WN_Set_Linenum (stid, current_srcpos);
10372 stid = lower_stmt(block, stid, actions);
10373
10374 WN_Set_Linenum (stid, current_srcpos);
10375 WN_INSERT_BlockLast(block, stid);
10376 WN_kid0(WN_actual(tree,i)) = WN_Ldid(mtype, 0, temp_st, ty_idx);
10377 }
10378 else
10379 #endif
10380 WN_actual(tree, i) = lower_expr(block, WN_actual(tree, i), actions);
10381 }
10382 promote_tls_ldst = FALSE;
10383
10384
10385 if (WN_has_sym(tree)) {
10386 callee_st = WN_st(tree);
10387 }
10388
10389 #ifdef TARG_X8664
10390 last_call_ff2c_abi = FALSE;
10391 if (WN_operator(tree) == OPR_CALL)
10392 last_call_ff2c_abi =PU_ff2c_abi(Pu_Table[ST_pu(St_Table[WN_st_idx(tree)])]);
10393 #endif
10394 if (WHIRL_Return_Val_On && Action(LOWER_RETURN_VAL) &&
10395 WN_rtype(tree) == MTYPE_V &&
10396 (WN_operator(tree) == OPR_CALL || WN_operator(tree) == OPR_ICALL ||
10397 WN_operator(tree) == OPR_PICCALL)) {
10398
10399
10400 TY_IDX prototype;
10401 if (WN_operator(tree) == OPR_ICALL)
10402 prototype = WN_ty(tree);
10403 else {
10404 ST_IDX func_stidx = WN_st_idx(tree);
10405 PU_IDX puidx = ST_pu(St_Table[func_stidx]);
10406 prototype = PU_prototype(Pu_Table[puidx]);
10407 }
10408 RETURN_INFO return_info = Get_Return_Info(TY_ret_type(prototype),
10409 Complex_Not_Simulated
10410 #ifdef TARG_X8664
10411 , last_call_ff2c_abi
10412 #endif
10413 );
10414 if (RETURN_INFO_return_via_first_arg(return_info)
10415 #ifdef KEY
10416 && (callee_st == NULL || strncmp(ST_name(callee_st),"_TRANSFER",9) != 0)
10417 #endif
10418 ) {
10419 ST *return_st = Gen_Temp_Symbol(TY_ret_type(prototype), ".vcall");
10420 WN *awn = WN_CreateLda(OPR_LDA, Pointer_Mtype, MTYPE_V, 0,
10421 Make_Pointer_Type(TY_ret_type(prototype)),
10422 return_st);
10423 awn = lower_expr(block, awn, actions);
10424 WN *n_call = add_fake_parm(tree, awn, WN_ty(awn));
10425 WN_Delete(tree);
10426 tree = n_call;
10427 }
10428 }
10429
10430 if (Action(LOWER_PICCALL))
10431 {
10432
10433
10434
10435
10436
10437
10438
10439
10440 if (WN_operator_is(tree, OPR_CALL) &&
10441 (Force_Jalr ||
10442 PU_needs_t9(Pu_Table[ST_pu(callee_st)]) ||
10443 (Gen_PIC_Calls &&
10444 (Gen_PIC_Shared ||
10445 (Gen_PIC_Call_Shared &&
10446 ST_visible_outside_dso(*callee_st)) ))))
10447 {
10448 INT16 n = WN_kid_count(tree);
10449 WN *itree;
10450
10451
10452
10453
10454 itree = WN_Piccall( WN_rtype(tree), WN_desc(tree), n+1, callee_st);
10455
10456 Is_True(callee_st == WN_st(tree),
10457 ("lower_call: something changed that Robert didn't expect!"));
10458 WN_actual(itree, n) = WN_Lda(Pointer_type, 0, callee_st);
10459 WN_Set_Linenum(itree, srcpos);
10460 WN_Set_Flags(tree, itree);
10461
10462 while (--n >= 0)
10463 WN_actual(itree, n) = WN_actual(tree, n);
10464
10465 if (Cur_PU_Feedback) {
10466 Cur_PU_Feedback->FB_lower_call( tree, itree );
10467 }
10468 WN_Delete(tree);
10469 tree = itree;
10470 }
10471 }
10472
10473 if (NotAction(LOWER_CALL))
10474 return tree;
10475
10476
10477
10478
10479
10480 if (Gen_Profile)
10481 {
10482 WN *profcall = lower_profile_call(block, tree, 0, actions);
10483 WN_Set_Linenum(profcall, current_srcpos);
10484 WN_INSERT_BlockLast (block, profcall);
10485 }
10486
10487 callblock = WN_CreateBlock();
10488
10489 #ifdef TARG_X8664
10490
10491
10492 for (i = 0; i < num_actuals; i++)
10493 WN_actual(tree, i) = take_out_special_ia32_ops(callblock, WN_actual(tree, i));
10494 #endif
10495
10496
10497
10498
10499
10500
10501
10502
10503
10504
10505
10506
10507
10508
10509
10510
10511
10512
10513
10514
10515 call_ty = (WN_operator_is(tree,OPR_ICALL) ? WN_ty(tree) :
10516 ST_pu_type(callee_st));
10517 Is_True(WN_operator_is(tree, OPR_ICALL) ||
10518 callee_st == WN_st(tree),
10519 ("lower_call: something changed that Robert didn't expect!"));
10520 ploc = Setup_Output_Parameter_Locations(call_ty);
10521
10522 for (i = 0; i < num_actuals; i++)
10523 {
10524 WN *parm = WN_actual(tree, i);
10525 TYPE_ID parmType = WN_rtype(parm);
10526 WN *actual = WN_operator_is(parm, OPR_PARM) ? WN_kid0(parm)
10527 : parm;
10528
10529 ploc = Get_Output_Parameter_Location(TY_Of_Parameter(parm));
10530
10531 if (MTYPE_is_m(parmType))
10532 {
10533
10534
10535
10536 lower_mload_actual (callblock, actual, ploc, actions);
10537 }
10538 #ifdef TARG_IA64
10539 else if (parmType == MTYPE_F10 &&
10540 (PLOC_on_stack(ploc) || Is_Int_Output_Preg(PLOC_reg(ploc))))
10541 {
10542
10543
10544
10545
10546
10547
10548 lower_compound_non_struct_actual (callblock, actual, ploc, actions);
10549 }
10550 #endif
10551 #ifndef TARG_X8664
10552 else if (MTYPE_is_complex(parmType) && PU_ftn_lang(Get_Current_PU()))
10553 {
10554
10555
10556
10557
10558
10559
10560 #ifdef TARG_IA64
10561 lower_compound_non_struct_actual (callblock, actual, ploc, actions);
10562 #else
10563 lower_complex_actual (callblock, actual, ploc, actions);
10564 #endif
10565 }
10566 #endif
10567 }
10568
10569 #ifdef TARG_X8664
10570 INT sse_args = 0;
10571 #endif
10572
10573 ploc = Setup_Output_Parameter_Locations(call_ty);
10574 for (i = 0; i < num_actuals; i++)
10575 {
10576
10577
10578
10579
10580
10581
10582 WN *parm = WN_actual(tree, i);
10583 TYPE_ID parmType = WN_rtype(parm);
10584 WN *actual = WN_operator_is(parm, OPR_PARM) ? WN_kid0(parm) : parm;
10585 TY_IDX ty;
10586
10587 ty = TY_Of_Parameter(parm);
10588 ploc = Get_Output_Parameter_Location( ty );
10589
10590 if (MTYPE_is_m(parmType) ||
10591 #if defined(TARG_IA64)
10592 (parmType == MTYPE_F10 &&
10593 (PLOC_on_stack(ploc) || Is_Int_Output_Preg(PLOC_reg(ploc)))) ||
10594 #endif
10595 (MTYPE_is_complex(parmType) && PU_ftn_lang(Get_Current_PU())) )
10596 {
10597
10598
10599
10600 #ifdef TARG_X8664
10601 if (Preg_Offset_Is_Float(PLOC_reg(ploc)))
10602 sse_args++;
10603 if (Preg_Offset_Is_Float(PLOC_reg2(ploc)))
10604 sse_args++;
10605 #endif
10606 continue;
10607 }
10608
10609
10610
10611
10612 TYPE_ID type = Mtype_comparison( Fix_TY_mtype(ty));
10613
10614 if (parmType != type) {
10615 DevWarn("lower_call(): line %d, parm #%d type mismatch (WN_rtype(parm)"
10616 " = %s) (cannonical TY_mtype(parm))) %s)",
10617 Srcpos_To_Line(WN_Get_Linenum(tree)), i,
10618 Mtype_Name(parmType), Mtype_Name(type));
10619 }
10620
10621
10622 #ifdef TARG_X8664
10623 if (Preg_Offset_Is_Float(PLOC_reg(ploc)))
10624 sse_args++;
10625 if (Preg_Offset_Is_Float(PLOC_reg2(ploc)))
10626 sse_args++;
10627 #endif
10628
10629 if (PLOC_on_stack(ploc))
10630 {
10631
10632
10633
10634
10635
10636 WN *wn;
10637
10638 wn = WN_Stid(parmType, PLOC_offset(ploc) - Formal_Save_Area_Size
10639 + Stack_Offset_Adjustment,
10640 SP_Sym, ty, actual);
10641 WN_Set_Linenum(wn, srcpos);
10642 WN_INSERT_BlockLast(callblock, wn);
10643 }
10644
10645
10646
10647
10648 else if (MTYPE_is_quad(parmType) && Preg_Offset_Is_Int(PLOC_reg(ploc)))
10649 {
10650 PREG_NUM qN;
10651
10652 qN = AssignExpr(callblock, actual, parmType);
10653
10654 lower_actual(callblock, WN_LdidPreg(MTYPE_F8, qN), MTYPE_F8,
10655 PLOC_reg(ploc));
10656
10657 lower_actual(callblock, WN_LdidPreg(MTYPE_F8, qN+1), MTYPE_F8,
10658 PLOC_reg(ploc)+1);
10659 }
10660 else
10661 {
10662 actual = lower_actual(callblock, actual, parmType, PLOC_reg(ploc));
10663
10664 if (WN_operator_is(parm, OPR_PARM))
10665 WN_kid0(parm) = actual;
10666 else
10667 WN_actual(tree, i) = actual;
10668
10669 if (! TY_has_prototype(call_ty) &&
10670 DEBUG_Varargs_Prototypes == FALSE &&
10671 Preg_Offset_Is_Float(PLOC_reg(ploc)))
10672 {
10673 actual = lower_copy_tree(actual, actions);
10674
10675 if (MTYPE_is_quad(parmType))
10676 {
10677 PREG_NUM qN;
10678
10679 qN = AssignExpr(callblock, actual, parmType);
10680
10681 lower_actual(callblock, WN_LdidPreg(MTYPE_F8, qN), MTYPE_F8,
10682 PLOC_vararg_reg(ploc));
10683 lower_actual(callblock, WN_LdidPreg(MTYPE_F8, qN+1), MTYPE_F8,
10684 PLOC_vararg_reg(ploc)+1);
10685 }
10686 else
10687 {
10688 lower_actual(callblock, actual, parmType, PLOC_vararg_reg(ploc));
10689 }
10690 }
10691 }
10692 }
10693
10694 #ifdef TARG_X8664
10695 if( Is_Target_64bit() ){
10696
10697 if (TY_is_varargs(call_ty) ||
10698 (! TY_has_prototype(call_ty) &&
10699 (callee_st == NULL || ST_sclass(callee_st) != SCLASS_TEXT))) {
10700 WN *sse_cnt_wn = WN_Intconst(MTYPE_I4, MIN(8, sse_args));
10701 WN *sse_cnt_stid = WN_StidIntoPreg(MTYPE_I4, RAX, Int32_Preg, sse_cnt_wn);
10702
10703 WN_Set_Linenum(sse_cnt_stid, srcpos);
10704 WN_INSERT_BlockLast(callblock, sse_cnt_stid);
10705 }
10706 }
10707 #endif
10708
10709
10710
10711
10712
10713 if (num_actuals > 0 &&
10714 TY_has_prototype(call_ty) &&
10715 Get_PU_arg_area_size(call_ty) == 0 &&
10716 ! TY_is_varargs(call_ty))
10717 {
10718 Set_PU_arg_area_size(call_ty, PLOC_total_size(ploc));
10719 }
10720
10721
10722
10723
10724
10725
10726
10727 {
10728 INT16 n= num_actuals;
10729
10730 while (--n >= 0)
10731 WN_actual(tree, n) = lower_copy_tree( WN_actual(tree, n), actions);
10732 }
10733
10734 if (MTYPE_is_complex(WN_rtype(tree))
10735 #ifdef TARG_X8664
10736 && !(last_call_ff2c_abi || F2c_Abi)
10737 #endif
10738 )
10739 {
10740 INT16 n = WN_kid_count(tree);
10741 WN *itree;
10742 TYPE_ID rtype, desc;
10743
10744 #ifdef TARG_X8664
10745 if (Is_Target_64bit() && WN_rtype(tree) == MTYPE_C4)
10746 rtype = MTYPE_F8;
10747 else
10748 #endif
10749 rtype = Mtype_complex_to_real(WN_rtype(tree));
10750 desc = Mtype_complex_to_real(WN_desc(tree));
10751
10752
10753
10754
10755
10756 if (WN_operator_is(tree, OPR_CALL))
10757 {
10758 itree = WN_Call( rtype, desc, n, WN_st(tree));
10759 }
10760 else if (WN_operator_is(tree, OPR_ICALL))
10761 {
10762 itree = WN_Icall( rtype, desc, n, WN_ty(tree));
10763 }
10764 WN_Set_Linenum(itree, srcpos);
10765 WN_Set_Flags(tree, itree);
10766
10767 while (--n >= 0)
10768 WN_actual(itree, n) = WN_actual(tree, n);
10769
10770 if (Cur_PU_Feedback) {
10771 Cur_PU_Feedback->FB_lower_call( tree, itree );
10772 }
10773 WN_Delete(tree);
10774 tree = itree;
10775 }
10776
10777
10778
10779
10780
10781 if (Action(LOWER_UPLEVEL))
10782 {
10783 if (callee_st && PU_is_nested_func(Pu_Table[ST_pu(callee_st)]))
10784 {
10785 WN *wn, *link;
10786
10787
10788
10789
10790
10791
10792 if (PU_lexical_level(&St_Table[WN_st_idx(current_function)]) <
10793 PU_lexical_level(callee_st))
10794 {
10795 link = WN_LdidPreg(Pointer_type, Frame_Pointer_Preg_Offset);
10796 }
10797
10798
10799
10800
10801
10802 else
10803 {
10804 ST *slink = Find_Slink_For_Scope(WN_st(current_function),
10805 callee_st);
10806
10807 link = WN_Ldid (Pointer_type, 0, slink, ST_type(slink));
10808 }
10809
10810 wn = WN_StidIntoPreg(Pointer_type,
10811 Static_Link_Preg_Offset,
10812 MTYPE_To_PREG(Pointer_type), link);
10813
10814 WN_Set_Linenum(wn, srcpos);
10815 WN_INSERT_BlockLast(callblock, wn);
10816 }
10817 }
10818
10819
10820
10821
10822
10823 Check_Actual_Stack_Size (tree);
10824
10825 callblock = lower_block(callblock, actions);
10826 WN_INSERT_BlockLast (block, callblock);
10827
10828
10829
10830
10831
10832
10833
10834
10835
10836
10837
10838
10839 return tree;
10840 }
10841
10842
10843
10844
10845
10846
10847
10848
10849
10850
10851
10852
10853
10854 static WN *lower_compgoto(WN *block, WN *tree, LOWER_ACTIONS actions)
10855 {
10856 INT32 pointerSize = MTYPE_RegisterSize(Pointer_type);
10857 INT32 num_entries = WN_num_entries(tree);
10858 WN *index, *add;
10859 ST *table_st;
10860 LEAF indexN, addN;
10861
10862 Is_True(WN_opcode(tree) == OPC_COMPGOTO,
10863 ("expected COMPGOTO node, not %s", OPCODE_name(WN_opcode(tree))));
10864 Is_True(WN_num_entries(tree) > 0,
10865 ("expected COMPGOTO nu,_entries > 0 not %d", WN_num_entries(tree)));
10866
10867 WN_kid0(tree) = lower_expr(block,
10868 #ifndef KEY
10869 WN_Coerce(Pointer_type, WN_kid0(tree)),
10870 #else
10871 WN_Coerce(Mtype_TransferSign(WN_rtype(WN_kid0(tree)), Pointer_type), WN_kid0(tree)),
10872 #endif
10873 actions);
10874
10875 if (NotAction(LOWER_COMPGOTO))
10876 return tree;
10877
10878 index = WN_kid0(tree);
10879
10880 indexN = Make_Leaf(block,
10881 #ifndef KEY
10882 WN_Coerce(Pointer_type, index),
10883 #else
10884 WN_Coerce(Mtype_TransferSign(WN_rtype(index), Pointer_type), index),
10885 #endif
10886 Pointer_type);
10887
10888
10889
10890
10891
10892
10893
10894
10895
10896
10897 {
10898 TY_IDX table;
10899 WN *mpy;
10900
10901 table = Make_Array_Type(Pointer_type, 1, num_entries);
10902
10903 table_st = Gen_Read_Only_Symbol (table, "jump_table");
10904 Set_ST_is_initialized(table_st);
10905
10906 mpy = WN_Mpy(Pointer_type,
10907 Load_Leaf(indexN),
10908 WN_Intconst(Pointer_type, pointerSize));
10909
10910 add = WN_Add(Pointer_type,
10911 WN_Lda (Pointer_type, 0, table_st),
10912 mpy);
10913 addN = Make_Leaf(block, add, Pointer_type);
10914 }
10915
10916
10917
10918
10919 WN *wn_truebr = NULL;
10920 if (WN_kid_count(tree) == 3)
10921 {
10922
10923
10924
10925
10926
10927 WN *ge, *truebr;
10928 WN *def = WN_kid2(tree);
10929
10930 ge = WN_GE(Pointer_type,
10931 Load_Leaf(indexN),
10932 WN_Intconst(Pointer_type, num_entries));
10933
10934 truebr = lower_truebr(WN_label_number(def), ge, &wn_truebr, actions);
10935 WN_INSERT_BlockLast(block, truebr);
10936 }
10937
10938
10939
10940
10941
10942
10943
10944 {
10945 WN *xgoto;
10946 WN *gotoTable = WN_kid1(tree);
10947
10948 index = WN_Iload(Pointer_type,
10949 0,
10950 MTYPE_To_TY(Pointer_type),
10951 Load_Leaf(addN));
10952
10953 index = lower_expr(block, index, actions);
10954
10955 xgoto = WN_CreateXgoto(num_entries, index, gotoTable, table_st);
10956 WN_Set_Linenum (xgoto, WN_Get_Linenum(tree));
10957
10958
10959 if ( Cur_PU_Feedback )
10960 Cur_PU_Feedback->FB_lower_compgoto( tree, xgoto, wn_truebr );
10961
10962 #ifdef TARG_SL2 //fork_joint
10963 if(WN_is_compgoto_para(tree))
10964 WN_Set_is_compgoto_para(xgoto);
10965 else if(WN_is_compgoto_for_minor(tree))
10966 WN_Set_is_compgoto_for_minor(xgoto);
10967 #endif
10968
10969 return xgoto;
10970 }
10971 }
10972
10973
10974
10975
10976
10977
10978
10979
10980
10981
10982
10983
10984
10985 static WN *lower_assert(WN *block, WN *tree, LOWER_ACTIONS actions)
10986 {
10987 WN *if_else, *if_then, *IF, *trap, *cond;
10988
10989 Is_True(WN_opcode(tree) == OPC_ASSERT,
10990 ("expected ASSERT node, not %s", OPCODE_name(WN_opcode(tree))));
10991
10992 WN_kid0(tree) = lower_expr(block, WN_kid0(tree), actions);
10993
10994 if (NotAction(LOWER_ASSERT))
10995 return tree;
10996
10997 if_then = WN_CreateBlock();
10998 if_else = WN_CreateBlock();
10999 cond = lower_expr(block, WN_kid0(tree), actions);
11000
11001
11002
11003
11004 switch ( WN_offset(tree) ) {
11005 case WN_TRAP_F77_BOUNDS_ERROR:
11006 {
11007 char *name;
11008 WN **kids = (WN **) alloca(4 * sizeof(WN *));
11009
11010
11011 kids[0] = WN_LdaString ( "? ", 0, 2 );
11012 kids[1] = WN_Intconst ( MTYPE_I4, -1 );
11013
11014
11015 name = ST_name(&St_Table[PU_Info_proc_sym(Current_PU_Info)]);
11016 kids[2] = WN_LdaString ( name, 0, strlen(name)+1 );
11017
11018 kids[3] = WN_Intconst(MTYPE_I4, Srcpos_To_Line(WN_Get_Linenum(tree)));
11019 trap = WN_Create_Intrinsic ( OPC_VINTRINSIC_CALL,
11020 INTRN_F77_BOUNDS_ERR, 4, kids );
11021 }
11022 break;
11023
11024 case WN_TRAP_C_BOUNDS_ERROR:
11025
11026
11027
11028
11029
11030
11031 if ( DEBUG_Verbose_Runtime ) {
11032 char *name;
11033 WN **kids = (WN **) alloca(4 * sizeof(WN *));
11034
11035
11036
11037 #if defined(IRIX)
11038 kids[0] = WN_Intconst ( MTYPE_I4, BRK_RANGE );
11039 #else
11040 fprintf(stderr, "Don't know how to do BRK_RANGE\n");
11041 exit(-1);
11042 #endif
11043
11044
11045 name = ST_name(&St_Table[PU_Info_proc_sym(Current_PU_Info)]);
11046 kids[1] = WN_LdaString ( name, 0, strlen(name)+1 );
11047
11048
11049 kids[2] = WN_Intconst ( MTYPE_I4,
11050 Srcpos_To_Line(WN_Get_Linenum(tree)) );
11051
11052
11053
11054
11055
11056 kids[3] = WN_LdaString ( "unknown array", 0, 14 );
11057
11058
11059 trap = WN_Create_Intrinsic ( OPC_VINTRINSIC_CALL,
11060 INTRN_RT_ERR, 4, kids );
11061 } else {
11062 #if defined(IRIX)
11063 trap = WN_CreateTrap ( BRK_RANGE );
11064 #else
11065 fprintf(stderr, "Don't know how to do BRK_RANGE\n");
11066 exit(-1);
11067 #endif
11068
11069
11070 }
11071 break;
11072
11073 default:
11074 trap = WN_CreateTrap ( WN_offset(tree) );
11075
11076 break;
11077 }
11078
11079 WN_Set_Linenum(trap, WN_Get_Linenum(tree));
11080 WN_INSERT_BlockLast(if_else, trap);
11081
11082 IF = WN_CreateIf(cond, if_then, if_else);
11083
11084 WN_Set_Linenum(IF, WN_Get_Linenum(tree));
11085 WN_Delete(tree);
11086
11087 IF = lower_scf(block, IF, actions);
11088 return IF;
11089 }
11090
11091
11092 static WN *lower_branch(WN *block, WN *tree, LOWER_ACTIONS actions)
11093 {
11094 Is_True((WN_opcode(tree) == OPC_TRUEBR || WN_opcode(tree) == OPC_FALSEBR),
11095 ("expected true/false"));
11096
11097 WN * const kid = lower_expr(block, WN_kid0(tree), actions);
11098 WN_kid0(tree) = kid;
11099
11100 #if !defined(KEY) || defined(TARG_IA64)
11101 if (WN_operator(kid) == OPR_LNOT)
11102 #else
11103
11104
11105 if (WN_operator(kid) == OPR_LNOT &&
11106 (!Force_IEEE_Comparisons ||
11107 !OPCODE_is_compare(WN_opcode(WN_kid0(kid))) ||
11108 MTYPE_is_integral(WN_desc(WN_kid0(kid)))))
11109 #endif
11110 {
11111 switch(WN_opcode(tree))
11112 {
11113 case OPC_TRUEBR:
11114 WN_set_opcode(tree, OPC_FALSEBR);
11115 break;
11116
11117 case OPC_FALSEBR:
11118 WN_set_opcode(tree, OPC_TRUEBR);
11119 break;
11120
11121 default:
11122 break;
11123 }
11124
11125 WN_kid0(tree) = WN_kid0(kid);
11126 WN_Delete(kid);
11127 }
11128
11129 return tree;
11130 }
11131
11132
11133
11134
11135
11136
11137
11138
11139
11140
11141
11142
11143 static WN *lower_return_val(WN *block, WN *tree, LOWER_ACTIONS actions)
11144 {
11145 PREG_NUM preg;
11146 ST *preg_st;
11147 TYPE_ID mtype;
11148 RETURN_INFO return_info;
11149 WN *wn;
11150
11151 Is_True((WN_operator(tree) == OPR_RETURN_VAL),
11152 ("expected RETURN_VAL node, not %s", OPCODE_name(WN_opcode(tree))));
11153
11154 TYPE_ID return_mtype = WN_rtype(tree);
11155
11156 if (return_mtype != MTYPE_M) {
11157 TY_IDX return_ty_idx = Be_Type_Tbl(return_mtype);
11158 return_info = Get_Return_Info (return_ty_idx, Use_Simulated
11159 #ifdef TARG_X8664
11160 , PU_ff2c_abi(Get_Current_PU())
11161 #endif
11162 );
11163
11164 WN_kid0(tree) = lower_expr (block, WN_kid0(tree), actions);
11165 if (RETURN_INFO_return_via_first_arg(return_info)) {
11166
11167
11168
11169 WN *first_formal = WN_formal(current_function, 0);
11170 TY_IDX tidx = ST_type(WN_st(first_formal));
11171 OPCODE const_op = OPCODE_make_op(OPR_INTCONST, MTYPE_I8, MTYPE_V);
11172
11173 WN *awn = WN_CreateLdid(OPR_LDID,
11174 TY_mtype(Ty_Table[tidx]),
11175 TY_mtype(Ty_Table[tidx]),
11176 WN_idname_offset(first_formal),
11177 WN_st(first_formal),
11178 tidx);
11179
11180 wn = WN_CreateIstore(OPR_ISTORE, MTYPE_V,
11181 return_mtype, 0, tidx, WN_kid0(tree), awn);
11182 } else {
11183 Is_True(RETURN_INFO_count(return_info) == 1,
11184 ("expected return_info count to be 1"));
11185
11186 mtype = RETURN_INFO_mtype (return_info, 0);
11187 preg = RETURN_INFO_preg (return_info, 0);
11188 if (MTYPE_is_float(mtype))
11189 #ifndef TARG_X8664
11190 #if defined(TARG_SL) && defined(EMULATE_FLOAT_POINT)
11191 preg_st = (mtype==MTYPE_F8)? Int64_Preg : Int32_Preg;
11192 #else
11193 preg_st = Float_Preg;
11194 #endif
11195 #else
11196 preg_st = (mtype==MTYPE_FQ || mtype==MTYPE_CQ)
11197 ? MTYPE_To_PREG(mtype) : Float_Preg;
11198 #endif
11199 else preg_st = (mtype==MTYPE_I8 || mtype==MTYPE_U8) ?
11200 MTYPE_To_PREG(mtype) : Int_Preg;
11201 #ifdef TARG_NVISA
11202 preg_st = Standard_Preg_For_Mtype(mtype);
11203 #endif
11204
11205 #ifdef TARG_X8664
11206 if( Is_Target_SSE2() &&
11207 Preg_Offset_Is_X87(preg) &&
11208 mtype != MTYPE_C4 &&
11209 !MTYPE_is_quad( mtype ) ){
11210 WN_kid0(tree) = WN_Cvt( Promoted_Mtype[mtype], MTYPE_FQ, WN_kid0(tree) );
11211 wn = WN_CreateStid( OPR_STID, MTYPE_V, MTYPE_FQ,
11212 preg, preg_st, Be_Type_Tbl(mtype), WN_kid0(tree) );
11213 } else
11214 #endif // TARG_X8664
11215 wn = WN_CreateStid (OPR_STID, MTYPE_V, Promoted_Mtype[mtype],
11216 preg, preg_st, Be_Type_Tbl(mtype), WN_kid0(tree));
11217 }
11218 WN_Set_Linenum(wn, current_srcpos);
11219 WN_INSERT_BlockLast (block, wn);
11220 }
11221 else {
11222 WN *o_rhs = WN_kid0(tree);
11223 OPERATOR rhs_opr = WN_operator(o_rhs);
11224 TY_IDX ty_idx = WN_ty(o_rhs);
11225 if (OPERATOR_is_load(rhs_opr) && WN_field_id(o_rhs) != 0) {
11226 if (rhs_opr == OPR_ILOAD || rhs_opr == OPR_LDID)
11227 ty_idx = get_field_type(ty_idx, WN_field_id(o_rhs));
11228 else {
11229 ty_idx = TY_pointed(Ty_Table[ty_idx]);
11230 ty_idx = get_field_type(ty_idx, WN_field_id(o_rhs));
11231 }
11232 }
11233 return_info = Get_Return_Info(ty_idx, Complex_Not_Simulated
11234 #ifdef TARG_X8664
11235 , PU_ff2c_abi(Get_Current_PU())
11236 #endif
11237 );
11238
11239 if (RETURN_INFO_return_via_first_arg(return_info)) {
11240 Is_True(RETURN_INFO_count(return_info) == 0,
11241 ("expected RETURN_INFO to have 0 count"));
11242 WN *n_rhs;
11243
11244
11245 if (WN_operator(o_rhs) == OPR_LDID)
11246 n_rhs = lower_mldid(block, o_rhs, LOWER_MLDID_MSTID);
11247 else if (WN_operator(o_rhs) == OPR_ILOAD)
11248 n_rhs = lower_miload(block, o_rhs, LOWER_MLDID_MSTID);
11249 else n_rhs = o_rhs;
11250
11251
11252 WN *first_formal = WN_formal(current_function, 0);
11253 TY_IDX tidx = ST_type(WN_st(first_formal));
11254 WN *awn = WN_CreateLdid(OPR_LDID,
11255 TY_mtype(Ty_Table[tidx]),
11256 TY_mtype(Ty_Table[tidx]),
11257 WN_idname_offset(first_formal),
11258 WN_st(first_formal),
11259 tidx);
11260 WN *swn = WN_CopyNode(WN_kid1(n_rhs));
11261 wn = WN_CreateMstore (0, tidx, n_rhs, awn, swn);
11262 WN_Set_Linenum(wn, current_srcpos);
11263 WN_INSERT_BlockLast (block, wn);
11264 }
11265 else {
11266 INT32 i;
11267 WN *n_rhs;
11268 UINT algn;
11269 TY_IDX ty_idx_used;
11270
11271 if (WN_operator(o_rhs) == OPR_LDID) {
11272 Is_True(WN_rtype(o_rhs) == MTYPE_M,
11273 ("expected RETURN_VAL kid not type M"));
11274
11275 algn = TY_align(ty_idx);
11276 for (i = 0; i < RETURN_INFO_count(return_info); i++) {
11277 mtype = RETURN_INFO_mtype(return_info, i);
11278 ty_idx_used = Be_Type_Tbl(mtype);
11279 Set_TY_align(ty_idx_used, algn);
11280 preg = RETURN_INFO_preg (return_info, i);
11281 preg_st = Standard_Preg_For_Mtype(mtype);
11282 #ifdef KEY // bug 12812
11283 if (WN_opcode(o_rhs) == OPC_MMLDID && WN_st(o_rhs) == Return_Val_Preg)
11284 n_rhs = WN_CreateLdid(OPR_LDID, mtype, mtype, preg, preg_st,
11285 Be_Type_Tbl(mtype));
11286 else
11287 #endif
11288 n_rhs = WN_CreateLdid (OPR_LDID, mtype, mtype,
11289 WN_load_offset(o_rhs)
11290 + i * MTYPE_byte_size(mtype),
11291 WN_st_idx(o_rhs), ty_idx_used);
11292 wn = WN_CreateStid(OPR_STID, MTYPE_V, mtype, preg, preg_st,
11293 Be_Type_Tbl(mtype), n_rhs);
11294 WN_Set_Linenum(wn, current_srcpos);
11295 WN_INSERT_BlockLast (block, wn);
11296 }
11297 }
11298 else if (WN_operator(o_rhs) == OPR_ILOAD) {
11299 Is_True(WN_rtype(o_rhs) == MTYPE_M,
11300 ("expected RETURN_VAL kid not type M"));
11301
11302 algn = TY_align(ty_idx);
11303 for (i = 0; i < RETURN_INFO_count(return_info); i++) {
11304 mtype = RETURN_INFO_mtype(return_info, i);
11305 ty_idx_used = Be_Type_Tbl(mtype);
11306 Set_TY_align(ty_idx_used, algn);
11307 if (i == 0)
11308 n_rhs = WN_kid0(o_rhs);
11309 else n_rhs = WN_COPY_Tree(WN_kid0(o_rhs));
11310 n_rhs = WN_CreateIload(OPR_ILOAD, mtype, mtype,
11311 WN_load_offset(o_rhs)
11312 + i * MTYPE_byte_size(mtype),
11313 ty_idx_used,
11314 Make_Pointer_Type(ty_idx_used), n_rhs);
11315 n_rhs = lower_expr(block, n_rhs, actions);
11316 preg = RETURN_INFO_preg (return_info, i);
11317 preg_st = Standard_Preg_For_Mtype(mtype);
11318 wn = WN_CreateStid(OPR_STID, MTYPE_V, mtype, preg, preg_st,
11319 Be_Type_Tbl(mtype), n_rhs);
11320 WN_Set_Linenum(wn, current_srcpos);
11321 WN_INSERT_BlockLast (block, wn);
11322 }
11323 }
11324 else {
11325 Is_True(WN_operator(WN_kid1(o_rhs)) == OPR_INTCONST,
11326 ("expected RETURN_VAL's MLOAD kid to be of constant size"));
11327 algn = TY_align(TY_pointed(WN_load_addr_ty(o_rhs)));
11328 for (i = 0; i < RETURN_INFO_count(return_info); i++) {
11329 mtype = RETURN_INFO_mtype(return_info, i);
11330 ty_idx_used = Be_Type_Tbl(mtype);
11331 Set_TY_align(ty_idx_used, algn);
11332 if (i == 0)
11333 n_rhs = WN_kid0(o_rhs);
11334 else n_rhs = WN_COPY_Tree(WN_kid0(o_rhs));
11335 n_rhs = WN_CreateIload(OPR_ILOAD, mtype, mtype,
11336 WN_load_offset(o_rhs)
11337 + i * MTYPE_byte_size(mtype),
11338 ty_idx_used,
11339 Make_Pointer_Type(ty_idx_used), n_rhs);
11340 n_rhs = lower_expr(block, n_rhs, actions);
11341 preg = RETURN_INFO_preg (return_info, i);
11342 preg_st = Standard_Preg_For_Mtype(mtype);
11343 wn = WN_CreateStid(OPR_STID, MTYPE_V, mtype, preg, preg_st,
11344 Be_Type_Tbl(mtype), n_rhs);
11345 WN_Set_Linenum(wn, current_srcpos);
11346 WN_INSERT_BlockLast (block, wn);
11347 }
11348 }
11349
11350 WN_Delete (o_rhs);
11351 }
11352 }
11353
11354 WN *wn_return = WN_CreateReturn ();
11355 WN_Set_Linenum(wn_return, current_srcpos);
11356 if ( Cur_PU_Feedback )
11357 Cur_PU_Feedback->FB_lower_return_val( tree, wn_return );
11358 tree = wn_return;
11359 return tree;
11360 }
11361
11362
11363
11364
11365
11366
11367
11368
11369
11370
11371
11372
11373
11374 static WN *lower_stmt(WN *block, WN *tree, LOWER_ACTIONS actions)
11375 {
11376 CURRENT_STATE stmtState = pushCurrentState(tree, actions);
11377
11378 Is_True(OPCODE_is_stmt(WN_opcode(tree)),
11379 ("expected statement node, not %s", OPCODE_name(WN_opcode(tree))));
11380
11381 switch(WN_operator(tree))
11382 {
11383 case OPR_CALL:
11384 case OPR_ICALL:
11385 case OPR_PICCALL:
11386 tree = lower_call(block, tree, actions);
11387 break;
11388
11389 case OPR_INTRINSIC_CALL:
11390 tree = lower_intrinsic_call(block, tree, actions);
11391 break;
11392
11393 case OPR_ISTORE:
11394 case OPR_STID:
11395 case OPR_MSTORE:
11396 tree = lower_store(block, tree, actions);
11397 break;
11398
11399 case OPR_COMPGOTO:
11400 tree = lower_compgoto(block, tree, actions);
11401 break;
11402
11403 case OPR_IO:
11404 if (Action(LOWER_IO_STATEMENT))
11405 {
11406 if (traceIO)
11407 {
11408 fputs(DBar, TFile);
11409 fprintf(TFile, "Io Lower: Before Lowering\n");
11410 fdump_tree(TFile, tree);
11411 fputs(DBar, TFile);
11412 }
11413
11414 tree = lower_io_statement(tree, actions);
11415
11416 if (traceIO)
11417 {
11418 fputs(DBar, TFile);
11419 fprintf(TFile, "Io Lower: After Lowering\n");
11420 fdump_tree(TFile, tree);
11421 fputs(DBar, TFile);
11422 }
11423 }
11424 break;
11425 case OPR_ALTENTRY:
11426 tree = lower_entry(tree, actions);
11427 break;
11428
11429 case OPR_EVAL:
11430 tree = lower_eval(block, tree, actions);
11431 break;
11432
11433 case OPR_LABEL:
11434
11435
11436
11437 if (WN_label_loop_info(tree))
11438 {
11439 WN *infoblock= WN_CreateBlock();
11440 WN *info= WN_label_loop_info(tree);
11441
11442 info = lower_expr(infoblock, info, actions);
11443 WN_set_label_loop_info(tree, info);
11444 }
11445 #ifdef LOW_LANDING_PAD
11446 if (Action(LOWER_ENTRY_EXIT) && WN_Label_Is_Handler_Begin (tree))
11447 tree = lower_landing_pad_entry (tree);
11448 #endif
11449 break;
11450
11451 case OPR_EXC_SCOPE_BEGIN:
11452
11453
11454
11455
11456 break;
11457
11458 case OPR_REGION_EXIT:
11459
11460
11461
11462 if (Action(LOWER_REGION_EXITS))
11463 WN_set_opcode(tree, OPC_GOTO);
11464 break;
11465
11466 case OPR_ASSERT:
11467 tree = lower_assert(block, tree, actions);
11468 break;
11469
11470 case OPR_TRUEBR:
11471 case OPR_FALSEBR:
11472 tree = lower_branch(block, tree, actions);
11473 break;
11474
11475 case OPR_RETURN_VAL:
11476 if (Action(LOWER_RETURN_VAL))
11477 tree = lower_return_val(block, tree, actions);
11478 else
11479 WN_kid0(tree) = lower_expr(block, WN_kid0(tree), actions);
11480 break;
11481
11482 case OPR_ASM_STMT:
11483 {
11484
11485 INT16 i;
11486 for (i = 2; i < WN_kid_count(tree); i++) {
11487 WN_kid0(WN_kid(tree,i)) = lower_expr(block, WN_kid0(WN_kid(tree,i)), actions);
11488 }
11489 break;
11490 }
11491
11492 #ifdef KEY
11493 case OPR_GOTO_OUTER_BLOCK:
11494 if (Action(LOWER_TO_CG)) {
11495 WN *wn;
11496 LABEL_IDX label_idx = WN_label_number(tree);
11497
11498
11499 ST *spsave_sym = Find_SPSave_Symbol(LABEL_IDX_level(label_idx));
11500 wn = WN_Ldid(Pointer_type, 0, spsave_sym, ST_type(spsave_sym));
11501 wn = lower_expr(block, wn, actions);
11502 wn = WN_StidIntoPreg(Pointer_type, Stack_Pointer_Preg_Offset,
11503 MTYPE_To_PREG(Pointer_type), wn);
11504 WN_Set_Linenum (wn, current_srcpos);
11505 WN_INSERT_BlockLast(block, wn);
11506
11507
11508 ST *fpsave_sym = Find_FPSave_Symbol(LABEL_IDX_level(label_idx));
11509 wn = WN_Ldid(Pointer_type, 0, fpsave_sym, ST_type(fpsave_sym));
11510 wn = lower_expr(block, wn, actions);
11511 wn = WN_StidIntoPreg(Pointer_type, Frame_Pointer_Preg_Offset,
11512 MTYPE_To_PREG(Pointer_type), wn);
11513 WN_Set_Linenum (wn, current_srcpos);
11514 WN_INSERT_BlockLast(block, wn);
11515 }
11516 #endif
11517
11518 default:
11519 {
11520 INT16 i;
11521 for (i = 0; i < WN_kid_count(tree); i++)
11522 WN_kid(tree,i) = lower_expr(block, WN_kid(tree,i), actions);
11523 }
11524 }
11525
11526 popCurrentState(stmtState);
11527 return tree;
11528 }
11529
11530
11531
11532
11533
11534
11535
11536
11537
11538
11539
11540
11541 static WN *replace_ldidPreg(WN *expr, PREG_NUM reg, WN *replacement)
11542 {
11543 INT16 i;
11544
11545 if (expr==NULL)
11546 return NULL;
11547
11548 for (i = 0; i < WN_kid_count(expr); i++)
11549 {
11550 WN *child= WN_kid(expr, i);
11551
11552 if ((WN_operator_is(child, OPR_LDID)) &&
11553 (WN_class(child) == CLASS_PREG) &&
11554 (WN_load_offset(child) == reg
11555 #ifdef KEY
11556 || WN_load_offset(child) == -1
11557 #endif
11558 ))
11559 {
11560 if (replacement)
11561 {
11562 WN_kid(expr, i) = replacement;
11563 }
11564 return child;
11565 }
11566
11567 {
11568 WN *tree;
11569 if (tree = replace_ldidPreg(child, reg, replacement))
11570 return tree;
11571 }
11572 }
11573 return NULL;
11574 }
11575
11576
11577
11578
11579
11580
11581
11582
11583
11584
11585
11586
11587
11588
11589
11590
11591
11592 static WN *lower_intrinsic_call(WN *block, WN *tree, LOWER_ACTIONS actions)
11593 {
11594 WN *next, *em, *newBlock;
11595 INTRINSIC id = (INTRINSIC) WN_intrinsic(tree);
11596 SRCPOS srcpos = WN_Get_Linenum(tree);
11597 TYPE_ID type;
11598 PREG_NUM reg1, reg2;
11599 BOOL intrinsic_lowered;
11600
11601 Is_True(OPCODE_is_stmt(WN_opcode(tree)),
11602 ("expected statement node, not %s", OPCODE_name(WN_opcode(tree))));
11603 {
11604
11605
11606
11607 INT16 i;
11608 for (i = 0; i < WN_kid_count(tree); i++)
11609 WN_kid(tree,i) = lower_expr(block, WN_kid(tree,i), actions);
11610 }
11611
11612 if (INTRN_cg_intrinsic(id))
11613 return tree;
11614
11615 if (NotAction(LOWER_INTRINSIC |
11616 LOWER_INLINE_INTRINSIC |
11617 LOWER_INL_STACK_INTRINSIC)) {
11618 return tree;
11619 }
11620 else if (NotAction(LOWER_INL_STACK_INTRINSIC)) {
11621 INTRINSIC intr = (INTRINSIC) WN_intrinsic(tree);
11622 if (intr == INTRN_U4I4SETSTACKPOINTER ||
11623 intr == INTRN_U8I8SETSTACKPOINTER ||
11624 intr == INTRN_U4READSTACKPOINTER ||
11625 intr == INTRN_U8READSTACKPOINTER ||
11626 #ifdef KEY
11627 intr == INTRN_U4READFRAMEPOINTER ||
11628 intr == INTRN_U8READFRAMEPOINTER ||
11629 #endif
11630 intr == INTRN_U4I4ALLOCA ||
11631 intr == INTRN_U8I8ALLOCA) {
11632 return tree;
11633 }
11634 }
11635
11636 next = WN_next(tree);
11637 type = WN_rtype(tree);
11638 newBlock = WN_CreateBlock();
11639
11640
11641
11642
11643
11644 {
11645 TYPE_ID ty1, ty2;
11646 BOOL returnValueUnused = FALSE;
11647
11648 if (WHIRL_Return_Info_On) {
11649
11650 RETURN_INFO return_info = Get_Return_Info (MTYPE_To_TY(type),
11651 Complex_Not_Simulated
11652 #ifdef TARG_X8664
11653 , FALSE
11654 #endif
11655 );
11656
11657 if (RETURN_INFO_count(return_info) <= 2) {
11658
11659 ty1 = RETURN_INFO_mtype (return_info, 0);
11660 ty2 = RETURN_INFO_mtype (return_info, 1);
11661 reg1 = RETURN_INFO_preg (return_info, 0);
11662 reg2 = RETURN_INFO_preg (return_info, 1);
11663 }
11664
11665 else
11666 ErrMsg (EC_Unimplemented,
11667 "lower_intrinsic_call: more than 2 return registers");
11668 }
11669
11670 else {
11671 Get_Return_Mtypes(MTYPE_To_TY(type), Complex_Not_Simulated, &ty1, &ty2);
11672 Get_Return_Pregs(ty1, ty2, ®1, ®2);
11673 }
11674
11675 if (MTYPE_is_void(type))
11676 {
11677 returnValueUnused = TRUE;
11678 }
11679 if (replace_ldidPreg(next, reg1, NULL)==NULL)
11680 {
11681 returnValueUnused = TRUE;
11682 }
11683 if (returnValueUnused && INTRN_has_no_side_effects(id))
11684 {
11685 DevWarn("lower_intrinsic_call(): function %s is void or unused and has"
11686 " no_side_effects. It will be removed", INTRINSIC_name(id));
11687
11688 return newBlock;
11689 }
11690 }
11691
11692 em = lower_emulation(newBlock, tree, actions, intrinsic_lowered);
11693
11694
11695
11696
11697
11698 if ((Action(LOWER_INLINE_INTRINSIC) ||
11699 Action(LOWER_INL_STACK_INTRINSIC)) &&
11700 NotAction(LOWER_INTRINSIC) &&
11701 tree == em)
11702 {
11703 WN_Delete(newBlock);
11704 return tree;
11705 }
11706
11707 WN_Delete(tree);
11708
11709 if (OPCODE_is_call(WN_opcode(em)))
11710 {
11711 WN_Set_Linenum (em, srcpos);
11712 WN_INSERT_BlockLast(block, newBlock);
11713 return em;
11714 }
11715 else if (WN_is_block(em))
11716 {
11717 WN_INSERT_BlockLast(block, newBlock);
11718 return em;
11719 }
11720 else if (MTYPE_is_void(type))
11721 {
11722 if (OPCODE_is_stmt(WN_opcode(em)))
11723 {
11724 WN_INSERT_BlockLast(newBlock, em);
11725 }
11726 return newBlock;
11727 }
11728 else
11729 {
11730
11731
11732
11733
11734 Is_True((reg1 != 0), ("expected return value from intrinsic_call"));
11735 Is_True((reg2 == 0), ("cannot evaluate 2 regs into an expression"));
11736 Is_True((OPCODE_is_expression(WN_opcode(em))), ("expected expression"));
11737 {
11738 WN *replaced = NULL;
11739
11740
11741
11742
11743
11744
11745
11746
11747 replaced = replace_ldidPreg(next, reg1, em);
11748
11749 if (replaced)
11750 {
11751 Is_True(Types_are_compatible(WN_rtype(replaced),type),
11752 ("return reg mismatch type"));
11753 }
11754 return newBlock;
11755 }
11756 }
11757 }
11758
11759
11760
11761
11762
11763
11764
11765
11766
11767
11768
11769
11770
11771 WN *lower_block(WN *tree, LOWER_ACTIONS actions)
11772 {
11773 WN *out, *node, *next_node;
11774 CURRENT_STATE blockState;
11775
11776 Is_True(WN_opcode(tree) == OPC_BLOCK,
11777 ("expected BLOCK node, not %s", OPCODE_name(WN_opcode(tree))));
11778
11779 blockState = pushCurrentState(tree, actions);
11780
11781 out = WN_CreateBlock();
11782 WN_Set_Linenum (out, current_srcpos);
11783
11784 for (node = WN_first(tree); node; node = next_node)
11785 {
11786
11787
11788
11789
11790
11791
11792
11793
11794
11795
11796
11797
11798
11799
11800
11801
11802
11803
11804
11805 while (Action(LOWER_MP) && node &&
11806 ((((WN_opcode(node) == OPC_PRAGMA) || (WN_opcode(node) == OPC_XPRAGMA))
11807 && (WN_pragmas[WN_pragma(node)].users & PUSER_MP)) ||
11808 ((WN_opcode(node) == OPC_REGION) && WN_first(WN_region_pragmas(node)) &&
11809 ((WN_opcode(WN_first(WN_region_pragmas(node))) == OPC_PRAGMA) ||
11810 (WN_opcode(WN_first(WN_region_pragmas(node))) == OPC_XPRAGMA)) &&
11811 (WN_pragmas[WN_pragma(WN_first(WN_region_pragmas(node)))].users &
11812 PUSER_MP))))
11813 node = lower_mp(out, node, actions);
11814 if (node == NULL) break;
11815
11816
11817
11818
11819 next_node = WN_next(node);
11820 setCurrentState(node, actions);
11821
11822 if (OPCODE_is_stmt(WN_opcode(node)))
11823 {
11824 node = lower_stmt(out, node, actions);
11825 }
11826 else if (OPCODE_is_scf(WN_opcode(node)))
11827 {
11828 node = lower_scf(out, node, actions);
11829 }
11830 else
11831 {
11832 Fail_FmtAssertion("expected statement or SCF node, not %s",
11833 OPCODE_name(WN_opcode(tree)));
11834
11835 }
11836
11837 if (node == NULL)
11838 continue;
11839
11840 #ifdef KEY
11841 if (Action(LOWER_MADD) &&
11842 Madd_Allowed &&
11843 Roundoff_Level >= ROUNDOFF_ASSOC) {
11844 lower_madd_tree_height(out, node, actions);
11845 }
11846 #endif
11847
11848 WN_INSERT_BlockLast(out, node);
11849
11850
11851 if ( Action(LOWER_INL_STACK_INTRINSIC)
11852 && (DEBUG_Trap_Uv
11853 #ifdef KEY
11854 || DEBUG_Zero_Uv
11855 #endif
11856 )
11857 && WN_operator(node) == OPR_STID
11858 && WN_operator(WN_kid0(node)) == OPR_ALLOCA)
11859 {
11860 #ifdef KEY
11861 lower_trapuv_alloca (out, WN_kid0(node), actions,
11862 WN_st_idx(node), WN_offset(node), WN_ty(node));
11863 #else
11864 lower_trapuv_alloca (out, WN_kid0(node), actions);
11865 #endif
11866 }
11867 }
11868
11869
11870
11871
11872
11873
11874
11875
11876
11877
11878 if (NotAction(LOWER_TOP_LEVEL_ONLY))
11879 {
11880 for (node = WN_first(out); node; node = next_node)
11881 {
11882 next_node = WN_next(node);
11883
11884 if (WN_unconditional_goto(node))
11885 {
11886 for(node = next_node; node; node = next_node)
11887 {
11888 next_node = WN_next(node);
11889
11890 if (WN_operator_is(node, OPR_LABEL))
11891 break;
11892 else if (WN_operator_is(node, OPR_ALTENTRY))
11893 break;
11894 else if (WN_operator_is(node, OPR_EXC_SCOPE_BEGIN))
11895 continue;
11896 else if (WN_operator_is(node, OPR_EXC_SCOPE_END))
11897 continue;
11898 else if (WN_operator_is(node, OPR_PRAGMA))
11899 continue;
11900 else if (WN_operator_is(node, OPR_XPRAGMA))
11901 continue;
11902 else if (WN_operator_is(node, OPR_REGION_EXIT))
11903 continue;
11904 #ifdef TARG_SL2 //fork_joint
11905
11906 else if(WN_operator_is(node, OPR_FORWARD_BARRIER) ||
11907 WN_operator_is(node, OPR_BACKWARD_BARRIER))
11908 continue;
11909 #endif
11910
11911 if (OPCODE_is_stmt(WN_opcode(node)))
11912 {
11913 WN_DELETE_FromBlock(out, node);
11914 }
11915 else
11916 break;
11917 }
11918 }
11919 }
11920 }
11921
11922 WN_Delete(tree);
11923
11924 popCurrentState(blockState);
11925 return out;
11926 }
11927
11928
11929
11930
11931
11932
11933
11934
11935
11936
11937
11938 static WN *lower_speculate(WN *block, WN *tree, LOWER_ACTIONS actions)
11939 {
11940 INT32 n;
11941 BOOL speculate = TRUE;
11942
11943 if (OPT_Lower_Speculate == FALSE)
11944 return tree;
11945
11946 switch(WN_operator(tree))
11947 {
11948 case OPR_CAND:
11949 case OPR_CIOR:
11950 case OPR_CSELECT:
11951 for (n = 0; n < WN_kid_count(tree); n++)
11952 {
11953 WN_kid(tree, n) = lower_speculate(block, WN_kid(tree, n), actions);
11954 speculate &= expr_is_speculative(WN_kid(tree, n));
11955 }
11956
11957 if (speculate)
11958 {
11959 if (WN_operator_is(tree, OPR_CAND))
11960 {
11961 if (traceSpeculate) fprintf(TFile, "change CAND to LAND\n");
11962 WN *land = WN_LAND( WN_kid0(tree), WN_kid1(tree) );
11963 WN_Delete(tree);
11964 return land;
11965 }
11966 else if (WN_operator_is(tree, OPR_CIOR))
11967 {
11968 if (traceSpeculate) fprintf(TFile, "change CIOR to LIOR\n");
11969 WN *lior = WN_LIOR( WN_kid0(tree), WN_kid1(tree) );
11970 WN_Delete(tree);
11971 return lior;
11972 }
11973 else if (WN_operator_is(tree, OPR_CSELECT))
11974 {
11975 if (traceSpeculate) fprintf(TFile, "change CSELECT to SELECT\n");
11976 WN *select = WN_Select(WN_rtype(tree), WN_kid0(tree), WN_kid1(tree),
11977 WN_kid2(tree));
11978
11979 WN_Delete(tree);
11980 return select;
11981 }
11982 }
11983 break;
11984 }
11985
11986 return tree;
11987 }
11988
11989
11990
11991
11992
11993
11994
11995
11996
11997
11998 static WN *
11999 lower_conditional(WN *block, WN *tree, LABEL_IDX trueLabel,
12000 LABEL_IDX falseLabel, BOOL branchType,
12001 LOWER_ACTIONS actions)
12002 {
12003 WN *shortcircuit, *left_branch = NULL, *right_branch = NULL;
12004
12005 switch(WN_operator(tree))
12006 {
12007 case OPR_CAND:
12008
12009
12010
12011
12012 if (WN_operator_is(WN_kid0(tree), OPR_CAND) ||
12013 WN_operator_is(WN_kid0(tree), OPR_CIOR))
12014 {
12015 shortcircuit = WN_NewLabel();
12016
12017 lower_conditional(block, WN_kid0(tree), WN_label_number(shortcircuit),
12018 falseLabel, FALSE, actions);
12019 WN_INSERT_BlockLast(block, shortcircuit);
12020 }
12021 else
12022 {
12023 left_branch = WN_Falsebr(falseLabel, WN_kid0(tree));
12024 WN_Set_Linenum(left_branch, current_srcpos);
12025 WN_INSERT_BlockLast(block, left_branch);
12026 }
12027
12028
12029
12030
12031 if (WN_operator_is(WN_kid1(tree), OPR_CAND) ||
12032 WN_operator_is(WN_kid1(tree), OPR_CIOR))
12033 {
12034 lower_conditional(block, WN_kid1(tree), trueLabel, falseLabel,
12035 branchType, actions);
12036 }
12037 else {
12038 if ( branchType ) {
12039 right_branch = WN_Truebr(trueLabel, WN_kid1(tree));
12040 }
12041 else {
12042
12043 right_branch = WN_Falsebr(falseLabel, WN_kid1(tree));
12044 }
12045 WN_Set_Linenum(right_branch, current_srcpos);
12046 WN_INSERT_BlockLast(block, right_branch);
12047 }
12048 if (Cur_PU_Feedback) {
12049 Cur_PU_Feedback->FB_lower_circuit( tree, left_branch, right_branch );
12050 }
12051 return NULL;
12052
12053 case OPR_CIOR:
12054
12055
12056
12057
12058 if (WN_operator_is(WN_kid0(tree), OPR_CAND) ||
12059 WN_operator_is(WN_kid0(tree), OPR_CIOR))
12060 {
12061 shortcircuit = WN_NewLabel();
12062
12063 lower_conditional(block, WN_kid0(tree), trueLabel,
12064 WN_label_number(shortcircuit), TRUE, actions);
12065 WN_INSERT_BlockLast(block, shortcircuit);
12066 }
12067 else
12068 {
12069 left_branch = WN_Truebr(trueLabel, WN_kid0(tree));
12070 WN_Set_Linenum(left_branch, current_srcpos);
12071 WN_INSERT_BlockLast(block, left_branch);
12072 }
12073
12074
12075
12076
12077 if (WN_operator_is(WN_kid1(tree), OPR_CAND) ||
12078 WN_operator_is(WN_kid1(tree), OPR_CIOR))
12079 {
12080 lower_conditional(block, WN_kid1(tree), trueLabel, falseLabel,
12081 branchType, actions);
12082 }
12083 else {
12084 if ( branchType ) {
12085 right_branch = WN_Truebr(trueLabel, WN_kid1(tree));
12086 }
12087 else {
12088
12089 right_branch = WN_Falsebr(falseLabel, WN_kid1(tree));
12090 }
12091 WN_Set_Linenum(right_branch, current_srcpos);
12092 WN_INSERT_BlockLast(block, right_branch);
12093 }
12094 if (Cur_PU_Feedback) {
12095 Cur_PU_Feedback->FB_lower_circuit( tree, left_branch, right_branch );
12096 }
12097 return NULL;
12098
12099 default:
12100 tree = lower_expr(block, tree, actions);
12101 break;
12102 }
12103
12104 return tree;
12105 }
12106
12107 static WN *lower_branch_condition(BOOL branchType, LABEL_IDX label, WN *cond,
12108 WN **branch, LOWER_ACTIONS actions)
12109 {
12110 WN *condBlock = WN_CreateBlock();
12111
12112 #ifndef TARG_NVISA // done instead at lower_if
12113 cond = lower_speculate(condBlock, cond, actions);
12114 #endif
12115
12116 *branch = NULL;
12117
12118 switch(WN_operator(cond))
12119 {
12120 case OPR_CAND:
12121 case OPR_CIOR:
12122 {
12123 LABEL_IDX shortcircuit_lbl;
12124 shortcircuit_lbl = NewLabel();
12125
12126 if (branchType == TRUE)
12127 {
12128 cond = lower_conditional(condBlock, cond, label, shortcircuit_lbl,
12129 branchType, actions);
12130 }
12131 else
12132 {
12133 cond = lower_conditional(condBlock, cond, shortcircuit_lbl, label,
12134 branchType, actions);
12135 }
12136
12137 condBlock = lower_block(condBlock, actions);
12138 WN_INSERT_BlockLast(condBlock, WN_Label(shortcircuit_lbl));
12139 }
12140 break;
12141 default:
12142 {
12143 cond = lower_expr(condBlock, cond, actions);
12144
12145 if (branchType)
12146 *branch = WN_Truebr(label, cond);
12147 else
12148 *branch = WN_Falsebr(label, cond);
12149 WN_Set_Linenum(*branch, current_srcpos);
12150 WN_INSERT_BlockLast(condBlock, *branch);
12151 }
12152 }
12153 return condBlock;
12154 }
12155
12156 #ifdef SHORTCIRCUIT_HACK
12157
12158
12159
12160 static INT tree_has_cand_cior (WN *tree)
12161 {
12162 WN_ITER *wni;
12163 WN *wn;
12164 INT count = 0;
12165
12166 for (wni = WN_WALK_TreeIter (tree);
12167 wni != NULL;
12168 wni = WN_WALK_TreeNext (wni))
12169 {
12170 wn = WN_ITER_wn (wni);
12171
12172 if (WN_operator_is(wn, OPR_CAND) ||
12173 WN_operator_is(wn, OPR_CIOR) ||
12174 WN_operator_is(wn, OPR_CSELECT))
12175 ++count;
12176 }
12177 return count;
12178 }
12179 #endif
12180
12181
12182
12183
12184
12185
12186
12187
12188
12189
12190
12191 static WN *lower_if(WN *block, WN *tree, LOWER_ACTIONS actions)
12192 {
12193 INT cand_cior_count = 0;
12194
12195 Is_True(WN_opcode(tree) == OPC_IF,
12196 ("expected IF node, not %s", OPCODE_name(WN_opcode(tree))));
12197
12198 if (WN_Is_If_MpVersion(tree))
12199 return lower_block(lower_mp(block, tree, actions), actions);
12200
12201 #ifdef TARG_NVISA
12202
12203
12204
12205
12206
12207 if (Action(LOWER_SHORTCIRCUIT) && OPT_Lower_Speculate)
12208 {
12209 cand_cior_count = tree_has_cand_cior(WN_if_test(tree));
12210 if ((cand_cior_count > 0)
12211 && (cand_cior_count < SHORTCIRCUIT_TO_LOGICAL_LIMIT))
12212 {
12213
12214 WN_if_test(tree) = lower_speculate(NULL, WN_if_test(tree), actions);
12215 }
12216 }
12217 #endif
12218 #ifndef SHORTCIRCUIT_HACK
12219 if (Action(LOWER_IF))
12220 #else
12221 if (Action(LOWER_IF) ||
12222 (Action(LOWER_SHORTCIRCUIT) && tree_has_cand_cior(WN_if_test(tree))))
12223 #endif
12224 {
12225
12226
12227
12228
12229
12230
12231 WN *body = WN_CreateBlock();
12232 WN *wn_branch = NULL;
12233 LABEL_IDX cont_lbl;
12234 cont_lbl = NewLabel();
12235
12236 if (Action(LOWER_TOP_LEVEL_ONLY))
12237 {
12238 actions = RemoveScfAction(actions);
12239 }
12240
12241 if (WN_block_nonempty(WN_then(tree)))
12242 {
12243 if (WN_block_nonempty(WN_else(tree)))
12244 {
12245
12246
12247
12248
12249
12250
12251
12252
12253
12254 LABEL_IDX else_lbl;
12255 else_lbl = NewLabel();
12256
12257 WN *falsebr_block = lower_falsebr(else_lbl, WN_if_test(tree),
12258 &wn_branch, actions);
12259 WN_INSERT_BlockFirst(body, falsebr_block);
12260
12261 setCurrentStateBlockLast(WN_then(tree), actions);
12262 WN_INSERT_BlockLast(body, lower_block(WN_then(tree), actions));
12263 WN *wn_goto = WN_Goto(cont_lbl);
12264 WN_Set_Linenum(wn_goto, current_srcpos);
12265 WN_INSERT_BlockLast(body, wn_goto);
12266
12267 WN *wn_else_lbl = WN_Label(else_lbl);
12268 setCurrentStateBlockLast(WN_else(tree), actions);
12269 WN_Set_Linenum(wn_else_lbl, current_srcpos);
12270 WN_INSERT_BlockLast(body, wn_else_lbl);
12271
12272 setCurrentStateBlockLast(WN_else(tree), actions);
12273 WN_INSERT_BlockLast(body, lower_block(WN_else(tree), actions));
12274 WN *wn_cont_lbl = WN_Label(cont_lbl);
12275 WN_Set_Linenum(wn_cont_lbl, current_srcpos);
12276 WN_INSERT_BlockLast(body, wn_cont_lbl);
12277 }
12278 else
12279 {
12280
12281
12282
12283
12284
12285
12286 WN *falsebr_block = lower_falsebr(cont_lbl, WN_if_test(tree),
12287 &wn_branch, actions);
12288 WN_INSERT_BlockFirst(body, falsebr_block);
12289
12290 setCurrentStateBlockLast(WN_then(tree), actions);
12291 WN_INSERT_BlockLast(body, lower_block(WN_then(tree), actions));
12292 WN *wn_cont_lbl = WN_Label(cont_lbl);
12293 WN_Set_Linenum(wn_cont_lbl, current_srcpos);
12294 WN_INSERT_BlockLast(body, wn_cont_lbl);
12295 }
12296
12297 if (Cur_PU_Feedback) {
12298 Cur_PU_Feedback->FB_lower_branch( tree, wn_branch );
12299 }
12300
12301 WN_Delete(tree);
12302 return body;
12303 }
12304 else if (WN_block_nonempty(WN_else(tree)))
12305 {
12306
12307
12308
12309
12310
12311
12312 WN *truebr_block = lower_truebr(cont_lbl, WN_if_test(tree),
12313 &wn_branch, actions);
12314 WN_INSERT_BlockFirst(body, truebr_block);
12315
12316 setCurrentStateBlockLast(WN_else(tree), actions);
12317 WN_INSERT_BlockLast(body, lower_block(WN_else(tree), actions));
12318 WN *wn_cont_lbl = WN_Label(cont_lbl);
12319 WN_Set_Linenum(wn_cont_lbl, current_srcpos);
12320 WN_INSERT_BlockLast(body, wn_cont_lbl);
12321
12322 if (Cur_PU_Feedback) {
12323 Cur_PU_Feedback->FB_lower_branch( tree, wn_branch );
12324 }
12325
12326 WN_Delete(tree);
12327 return body;
12328 }
12329 else
12330 {
12331
12332
12333
12334
12335 WN *eval;
12336
12337 eval = WN_CreateExp1(OPC_EVAL, lower_expr(block, WN_if_test(tree),
12338 actions));
12339 WN_Set_Linenum (eval, current_srcpos);
12340
12341 if (Cur_PU_Feedback) {
12342 Cur_PU_Feedback->FB_lower_branch( tree, NULL );
12343 }
12344
12345 WN_DELETE_Tree(WN_then(tree));
12346 WN_DELETE_Tree(WN_else(tree));
12347 WN_Delete(tree);
12348 return eval;
12349 }
12350 }
12351 else if (NotAction(LOWER_TOP_LEVEL_ONLY))
12352 {
12353 WN_if_test(tree) = lower_expr(block, WN_if_test(tree),
12354 RemoveShortCircuitAction(actions));
12355 WN_then(tree) = lower_block(WN_then(tree), actions);
12356 WN_else(tree) = lower_block(WN_else(tree), actions);
12357 }
12358
12359 return tree;
12360 }
12361
12362 #ifdef KEY
12363 static void Substitute_Constant_Multiplicands ( WN* tree, WN* copy,
12364 WN** condition,
12365 FB_FREQ* freq,
12366 BOOL* optimized,
12367 BOOL* okay )
12368
12369
12370
12371
12372
12373
12374
12375
12376
12377
12378
12379
12380
12381
12382
12383
12384
12385
12386
12387
12388
12389
12390
12391
12392
12393
12394
12395
12396
12397 {
12398 OPERATOR opr = WN_operator( tree );
12399
12400 if (opr == OPR_DO_LOOP)
12401 Substitute_Constant_Multiplicands( WN_do_body( tree ), WN_do_body( copy ),
12402 condition, freq, optimized, okay );
12403
12404 else if (opr == OPR_BLOCK) {
12405 WN *stmt, *stmt_copy;
12406
12407 stmt = WN_first( tree );
12408 stmt_copy = WN_first( copy );
12409 for (; stmt;) {
12410 WN *next_stmt, *next_stmt_copy;
12411 next_stmt = WN_next(stmt);
12412 next_stmt_copy = WN_next( stmt_copy );
12413 Substitute_Constant_Multiplicands( stmt, stmt_copy, condition, freq,
12414 optimized, okay );
12415 if ( !*okay )
12416 return;
12417 stmt = next_stmt;
12418 stmt_copy = next_stmt_copy;
12419 }
12420 }
12421
12422 else if ( opr == OPR_CALL ) {
12423 *okay = FALSE;
12424 return;
12425 }
12426
12427 else if ( OPCODE_is_store( WN_opcode( tree ) ) )
12428 Substitute_Constant_Multiplicands( WN_kid0(tree), WN_kid0(copy),
12429 condition, freq, optimized, okay );
12430
12431 else if ( opr == OPR_MPY &&
12432 ( OPERATOR_is_load( WN_operator( WN_kid0(tree) ) ) ||
12433 OPERATOR_is_load( WN_operator( WN_kid1(tree) ) ) ) &&
12434 WN_rtype( tree ) == MTYPE_F8 ) {
12435
12436 const FB_Info_Value_FP_Bin& info =
12437 Cur_PU_Feedback->Query_value_fp_bin( tree );
12438 const float cutoff_ratio = (float)Mpy_Exe_Ratio / 100;
12439
12440 if( info.exe_counter < (float)Mpy_Exe_Counter )
12441 return;
12442
12443 if ( OPERATOR_is_load( WN_operator( WN_kid(tree,0) ) ) ) {
12444 BOOL substitute = FALSE;
12445 FB_FREQ this_freq = info.zopnd0;
12446 WN* id = WN_COPY_Tree(WN_kid(tree, 0));
12447 double val = 0.0;
12448 WN* value;
12449
12450 if ( info.uopnd0 / info.exe_counter >= cutoff_ratio ||
12451 info.zopnd0 / info.exe_counter >= cutoff_ratio )
12452 substitute = TRUE;
12453
12454 if ( info.uopnd0 > info.zopnd0 ) {
12455 this_freq = info.uopnd0;
12456 val = 1.0;
12457 }
12458
12459 if ( substitute ) {
12460 WN_Delete( WN_kid(copy,0) );
12461 WN_kid(copy, 0) = Make_Const( Host_To_Targ_Float (MTYPE_F8, val) );
12462
12463
12464 if ( *freq < this_freq )
12465 *freq = this_freq;
12466
12467
12468 value = Make_Const(Host_To_Targ_Float(MTYPE_F8,val));
12469 if ( *condition )
12470 *condition = WN_CAND( *condition, WN_EQ( MTYPE_F8, id, value ) );
12471 else
12472 *condition = WN_EQ( MTYPE_F8, id, value );
12473
12474 *optimized = TRUE;
12475 }
12476 } else
12477 Substitute_Constant_Multiplicands( WN_kid0(tree), WN_kid0(copy),
12478 condition, freq, optimized, okay );
12479 if ( !*okay )
12480 return;
12481
12482 if ( OPERATOR_is_load( WN_operator( WN_kid(tree,1) ) ) ) {
12483 BOOL substitute = FALSE;
12484 FB_FREQ this_freq = info.zopnd1;
12485 WN* id = WN_COPY_Tree(WN_kid(tree, 1));
12486 double val = 0.0;
12487 WN* value;
12488
12489 if ( info.uopnd1 / info.exe_counter >= cutoff_ratio ||
12490 info.zopnd1 / info.exe_counter >= cutoff_ratio )
12491 substitute = TRUE;
12492
12493 if ( info.uopnd1 > info.zopnd1 ) {
12494 this_freq = info.uopnd1;
12495 val = 1.0;
12496 }
12497
12498 if ( substitute ) {
12499
12500
12501 WN_Delete( WN_kid(copy,1) );
12502 WN_kid(copy, 1) = Make_Const( Host_To_Targ_Float (MTYPE_F8, val) );
12503
12504
12505 if ( *freq < this_freq )
12506 *freq = this_freq;
12507
12508
12509 value = Make_Const(Host_To_Targ_Float(MTYPE_F8,val));
12510 if ( *condition )
12511 *condition = WN_CAND( *condition, WN_EQ( MTYPE_F8, id, value ) );
12512 else
12513 *condition = WN_EQ( MTYPE_F8, id, value );
12514
12515 *optimized = TRUE;
12516 }
12517 } else
12518 Substitute_Constant_Multiplicands( WN_kid1(tree), WN_kid1(copy),
12519 condition, freq, optimized, okay );
12520 }
12521
12522 else if ( opr == OPR_LABEL ) {
12523 LABEL_IDX new_label = NewLabel();
12524 WN_label_number( copy ) = new_label;
12525 }
12526
12527 else {
12528 for (UINT kidno=0; kidno<WN_kid_count(tree); kidno++) {
12529 Substitute_Constant_Multiplicands( WN_kid(tree, kidno),
12530 WN_kid(copy, kidno),
12531 condition, freq, optimized, okay );
12532 if ( !*okay )
12533 return;
12534 }
12535 }
12536 }
12537
12538 static WN* simplify_multiply ( WN* do_loop, LOWER_ACTIONS actions )
12539
12540
12541
12542
12543
12544
12545
12546
12547
12548
12549
12550
12551
12552
12553
12554
12555
12556
12557
12558
12559
12560
12561
12562
12563 {
12564 WN* condition;
12565 WN* newblock;
12566 FB_FREQ* freq;
12567 WN* block = WN_do_body( do_loop );
12568 FB_Info_Loop info_loop;
12569 BOOL* optimized;
12570 BOOL* okay;
12571
12572 if ( !Cur_PU_Feedback )
12573 return block;
12574
12575
12576
12577
12578 if ( IEEE_Arithmetic < IEEE_INEXACT )
12579 return block;
12580
12581
12582
12583 info_loop = Cur_PU_Feedback->Query_loop( do_loop );
12584 if ( info_loop.freq_iterate < (float)Mpy_Exe_Counter )
12585 return block;
12586
12587
12588 condition = NULL;
12589 newblock = lower_copy_tree(block, actions);
12590 freq = (FB_FREQ *)malloc(sizeof(FB_FREQ));
12591 *freq = info_loop.freq_iterate;
12592 optimized = (BOOL *)malloc(sizeof(BOOL));
12593 *optimized = FALSE;
12594 okay = (BOOL *)malloc(sizeof(BOOL));
12595 *okay = TRUE;
12596
12597
12598
12599
12600 Substitute_Constant_Multiplicands( block, newblock, &condition,
12601 freq, optimized, okay );
12602
12603 if ( !*optimized || !*okay ) {
12604 WN_Delete( newblock );
12605 return block;
12606 }
12607
12608
12609 newblock = WN_Simplify_Tree( newblock );
12610
12611
12612
12613 WN* orig_block = block;
12614 block = WN_COPY_Tree( block );
12615 WN_Delete( orig_block );
12616 WN* IF = WN_CreateIf( condition, newblock, block );
12617 Cur_PU_Feedback->Annot( IF, FB_EDGE_BRANCH_TAKEN, *freq );
12618 Cur_PU_Feedback->Annot( IF, FB_EDGE_BRANCH_NOT_TAKEN,
12619 info_loop.freq_iterate - *freq );
12620 WN_Set_Linenum( newblock, current_srcpos );
12621 WN* optimized_block = WN_CreateBlock();
12622 WN_INSERT_BlockLast( optimized_block, IF );
12623 WN_Set_Linenum( optimized_block, current_srcpos );
12624
12625
12626 return optimized_block;
12627 }
12628 #endif
12629
12630
12631
12632
12633
12634
12635
12636
12637
12638
12639
12640 static WN *lower_do_loop(WN *block, WN *tree, LOWER_ACTIONS actions)
12641 {
12642 WN *loop_info;
12643
12644 Is_True(WN_opcode(tree) == OPC_DO_LOOP,
12645 ("expected DO_LOOP node, not %s", OPCODE_name(WN_opcode(tree))));
12646 if (Action(LOWER_TO_MEMLIB)) {
12647 tree = Lower_Memlib(block, tree, actions);
12648
12649 if (WN_opcode(tree) != OPC_DO_LOOP)
12650 return tree;
12651 }
12652 loop_info = WN_do_loop_info(tree);
12653 loop_nest_depth = loop_info ? WN_loop_depth(loop_info) : loop_nest_depth+1;
12654
12655 #ifdef TARG_X8664
12656 loop_info_stack[++current_loop_nest_depth] = NULL;
12657 FmtAssert( current_loop_nest_depth < MAX_LOOP_NEST_DEPTH,
12658 ("loop nest depth too deep") );
12659 if( loop_info != NULL ){
12660 loop_info_stack[current_loop_nest_depth] = WN_loop_induction( loop_info );
12661 FmtAssert( WN_has_sym( loop_info_stack[current_loop_nest_depth] ),
12662 ("loop_induction has no sym") );
12663 }
12664 #endif
12665
12666 #ifdef KEY // do this to see if the STID gets lowered to ISTORE
12667 if (NotAction(LOWER_TOP_LEVEL_ONLY))
12668 WN_start(tree) = lower_stmt(block, WN_start(tree), actions);
12669 #endif
12670 if (Action(LOWER_DO_LOOP)
12671 #ifdef KEY
12672 || WN_operator(WN_start(tree)) != OPR_STID
12673 #endif
12674 )
12675 {
12676
12677
12678
12679
12680
12681
12682
12683
12684
12685
12686 BOOL nz_trip = loop_info && WN_Loop_Nz_Trip(loop_info);
12687 WN *wn_top_branch = NULL, *wn_back_branch = NULL;
12688 WN *body = WN_CreateBlock();
12689
12690 if (Action(LOWER_TOP_LEVEL_ONLY))
12691 {
12692 actions = RemoveScfAction(actions);
12693 }
12694
12695 contains_a_loop = FALSE;
12696
12697
12698
12699
12700 if (loop_info == NULL)
12701 {
12702 WN *infoblock = WN_CreateBlock();
12703 WN *trip_count = WN_LOOP_TripCount(tree);
12704
12705
12706 if (trip_count && WN_operator_is(trip_count, OPR_INTCONST) &&
12707 WN_const_val(trip_count) > 0) {
12708 nz_trip = TRUE;
12709 }
12710 loop_info = WN_CreateLoopInfo(WN_index(tree),
12711 trip_count,
12712 0,
12713 loop_nest_depth,
12714 contains_a_loop ? 0 : WN_LOOP_INNERMOST);
12715 loop_info = lower_expr(infoblock, loop_info, actions);
12716 WN_Set_Loop_Nz_Trip(loop_info);
12717 WN_DELETE_Tree(infoblock);
12718 }
12719 else if (WN_loop_induction(loop_info) != WN_index(tree))
12720 {
12721 WN_DELETE_Tree(WN_index(tree));
12722 }
12723
12724 WN_INSERT_BlockLast(body, lower_stmt(block, WN_start(tree), actions));
12725
12726 WN *cont_lbl;
12727 if (nz_trip == FALSE)
12728 {
12729 WN *end = lower_copy_tree(WN_end(tree), actions);
12730
12731 if (Cur_PU_Feedback)
12732 Cur_PU_Feedback->FB_clone_loop_test( WN_end(tree), end, tree );
12733
12734 cont_lbl = WN_NewLabel();
12735 WN *top_branch_block = lower_falsebr(WN_label_number(cont_lbl), end,
12736 &wn_top_branch, actions);
12737 WN_INSERT_BlockLast(body, top_branch_block);
12738 }
12739
12740 setCurrentState(WN_do_body(tree), actions);
12741
12742 LABEL_IDX top_lbl_idx;
12743 top_lbl_idx = NewLabel();
12744
12745 WN *top_lbl = WN_CreateLabel(ST_IDX_ZERO, top_lbl_idx, 0, loop_info);
12746 WN_Set_Linenum(top_lbl, current_srcpos);
12747 WN_INSERT_BlockLast(body, top_lbl);
12748
12749 WN_INSERT_BlockLast(body, lower_block(WN_do_body(tree), actions));
12750
12751 setCurrentState(WN_step(tree), actions);
12752 WN_INSERT_BlockLast(body, lower_stmt(block, WN_step(tree), actions));
12753 WN *back_branch_block = lower_truebr(WN_label_number(top_lbl),
12754 WN_end(tree), &wn_back_branch,
12755 actions);
12756 WN_INSERT_BlockLast(body, back_branch_block);
12757
12758 if (nz_trip == FALSE) {
12759 WN_Set_Linenum(cont_lbl, current_srcpos);
12760 WN_INSERT_BlockLast(body, cont_lbl);
12761 }
12762
12763 if ( Cur_PU_Feedback )
12764 Cur_PU_Feedback->FB_lower_loop( tree, wn_top_branch, wn_back_branch );
12765
12766 WN_Delete(tree);
12767
12768 tree = body;
12769 }
12770 else if (NotAction(LOWER_TOP_LEVEL_ONLY))
12771 {
12772 WN_start(tree) = lower_stmt(block, WN_start(tree), actions);
12773 WN_end(tree) = lower_expr(block, WN_end(tree), actions);
12774 WN_step(tree) = lower_stmt(block, WN_step(tree), actions);
12775 #ifdef KEY
12776
12777
12778
12779
12780
12781
12782 if ( !PU_has_region(Get_Current_PU()) )
12783 if (NotAction(LOWER_FAST_EXP) )
12784 WN_do_body(tree) = simplify_multiply( tree, actions );
12785 #endif
12786 WN_do_body(tree) = lower_block(WN_do_body(tree), actions);
12787 }
12788
12789 #ifdef TARG_X8664
12790 loop_info_stack[current_loop_nest_depth--] = NULL;
12791 #endif
12792
12793 --loop_nest_depth;
12794 contains_a_loop = TRUE;
12795 return tree;
12796 }
12797
12798
12799
12800
12801
12802
12803
12804
12805
12806
12807
12808
12809
12810 static WN *lower_do_while(WN *block, WN *tree, LOWER_ACTIONS actions)
12811 {
12812 Is_True(WN_opcode(tree) == OPC_DO_WHILE,
12813 ("expected DO_WHILE node, not %s", OPCODE_name(WN_opcode(tree))));
12814
12815 ++loop_nest_depth;
12816 #ifndef SHORTCIRCUIT_HACK
12817 if (Action(LOWER_DO_WHILE))
12818 #else
12819 if (Action(LOWER_DO_WHILE) ||
12820 (Action(LOWER_SHORTCIRCUIT) && tree_has_cand_cior (WN_while_test(tree))))
12821 #endif
12822 {
12823
12824
12825
12826
12827
12828
12829 WN *body = WN_CreateBlock();
12830 WN *top_lbl = WN_NewLabel();
12831
12832 if (Action(LOWER_TOP_LEVEL_ONLY))
12833 {
12834 actions = RemoveScfAction(actions);
12835 }
12836
12837 WN_Set_Linenum(top_lbl, current_srcpos);
12838 WN_INSERT_BlockFirst(body, top_lbl);
12839 WN_INSERT_BlockLast(body, lower_block(WN_while_body(tree), actions));
12840
12841 setCurrentState(tree, actions);
12842 WN *wn_back_branch = NULL;
12843 WN *back_branch_block
12844 = lower_truebr(WN_label_number(top_lbl), WN_while_test(tree),
12845 &wn_back_branch, actions);
12846 WN_INSERT_BlockLast(body, back_branch_block);
12847
12848 if ( Cur_PU_Feedback )
12849 Cur_PU_Feedback->FB_lower_loop( tree, NULL, wn_back_branch );
12850
12851 WN_Delete(tree);
12852 tree = body;
12853 }
12854 else if (NotAction(LOWER_TOP_LEVEL_ONLY))
12855 {
12856 WN *testBlock = WN_CreateBlock();
12857
12858 WN_while_body(tree) = lower_block(WN_while_body(tree), actions);
12859
12860 WN_while_test(tree) = lower_expr(testBlock, WN_while_test(tree), actions);
12861
12862 WN_INSERT_BlockLast(WN_while_body(tree), testBlock);
12863 }
12864
12865 --loop_nest_depth;
12866 contains_a_loop = TRUE;
12867 return tree;
12868 }
12869
12870
12871
12872
12873
12874
12875
12876
12877
12878
12879
12880
12881
12882
12883
12884
12885
12886
12887
12888
12889 static WN *lower_while_do(WN *block, WN *tree, LOWER_ACTIONS actions)
12890 {
12891 Is_True(WN_opcode(tree) == OPC_WHILE_DO,
12892 ("expected WHILE_DO node, not %s", OPCODE_name(WN_opcode(tree))));
12893
12894 ++loop_nest_depth;
12895 #ifndef SHORTCIRCUIT_HACK
12896 if (Action(LOWER_WHILE_DO))
12897 #else
12898 if (Action(LOWER_WHILE_DO) ||
12899 (Action(LOWER_SHORTCIRCUIT) && tree_has_cand_cior (WN_while_test(tree))))
12900 #endif
12901 {
12902
12903
12904
12905
12906
12907
12908
12909 LABEL_IDX top_lbl, cont_lbl;
12910 top_lbl = NewLabel();
12911 cont_lbl = NewLabel();
12912
12913 WN *test = lower_copy_tree( WN_while_test(tree), actions);
12914 WN *body = WN_CreateBlock();
12915 if (Cur_PU_Feedback)
12916 Cur_PU_Feedback->FB_clone_loop_test( WN_while_test(tree), test, tree );
12917
12918 if (Action(LOWER_TOP_LEVEL_ONLY))
12919 {
12920 actions = RemoveScfAction(actions);
12921 }
12922
12923 WN *wn_top_branch = NULL;
12924 WN *top_branch_block = lower_falsebr(cont_lbl, test, &wn_top_branch,
12925 actions);
12926 WN_INSERT_BlockLast(block, top_branch_block);
12927
12928 setCurrentState(WN_while_body(tree), actions);
12929 WN *wn_top_lbl = WN_Label(top_lbl);
12930 WN_Set_Linenum(wn_top_lbl, current_srcpos);
12931 WN_INSERT_BlockLast(body, wn_top_lbl);
12932
12933 setCurrentStateBlockLast(WN_while_body(tree), actions);
12934 WN_INSERT_BlockLast(body, lower_block(WN_while_body(tree), actions));
12935
12936 setCurrentState(tree, actions);
12937 WN *wn_back_branch = NULL;
12938 WN *back_branch_block = lower_truebr(top_lbl, WN_while_test(tree),
12939 &wn_back_branch, actions);
12940 WN_INSERT_BlockLast(body, back_branch_block);
12941 WN *wn_cont_lbl = WN_Label(cont_lbl);
12942 WN_INSERT_BlockLast(body, wn_cont_lbl);
12943
12944 if ( Cur_PU_Feedback )
12945 Cur_PU_Feedback->FB_lower_loop( tree, wn_top_branch, wn_back_branch );
12946
12947 WN_Delete(tree);
12948
12949 tree = body;
12950 }
12951
12952
12953
12954
12955
12956
12957 else if (NotAction(LOWER_TOP_LEVEL_ONLY))
12958 {
12959 WN *copytestBlock;
12960 WN *testBlock = WN_CreateBlock();
12961
12962 WN_while_body(tree) = lower_block(WN_while_body(tree), actions);
12963
12964 WN_while_test(tree) = lower_expr(testBlock, WN_while_test(tree), actions);
12965 copytestBlock = lower_copy_tree(testBlock, actions);
12966
12967 if (Cur_PU_Feedback)
12968 Cur_PU_Feedback->FB_clone_loop_test( testBlock, copytestBlock, tree );
12969
12970 WN_INSERT_BlockLast(block, copytestBlock);
12971 WN_INSERT_BlockLast(WN_while_body(tree), testBlock);
12972 }
12973
12974 --loop_nest_depth;
12975 contains_a_loop = TRUE;
12976 return tree;
12977 }
12978
12979
12980
12981
12982
12983
12984
12985
12986
12987
12988
12989
12990
12991 static WN *lower_promoted_formal(PLOC ploc, ST *formalST)
12992 {
12993 WN *ldid, *cvt;
12994 TYPE_ID regType, formalType;
12995
12996 formalType = TY_mtype(Ty_Table[ST_type(formalST)]);
12997
12998 regType = Mtype_comparison(TY_mtype(Promoted_Parm_Type(formalST)));
12999
13000 if (!PLOC_on_stack(ploc))
13001 {
13002 #ifdef TARG_X8664
13003 if (Is_Target_64bit() && formalType == MTYPE_C4)
13004 formalType = regType = MTYPE_F8;
13005 #endif
13006 formalST = MTYPE_To_PREG(regType);
13007 }
13008
13009 ldid = WN_Ldid(regType, PLOC_reg(ploc), formalST, ST_type(formalST));
13010
13011 cvt = WN_Type_Conversion(ldid, formalType);
13012
13013 return cvt;
13014 }
13015
13016
13017
13018
13019
13020
13021
13022
13023
13024 static void lower_formals(WN *block, WN *formal, PLOC ploc,
13025 LOWER_ACTIONS actions)
13026 {
13027 BOOL altentry = PU_has_altentry(Get_Current_PU());
13028 ST *sym = WN_st(formal);
13029 TY_IDX formalTY = WN_type(formal);
13030
13031 if (PLOC_on_stack(ploc))
13032 {
13033
13034 if (altentry)
13035 {
13036 ST *upformal;
13037 WN *ldid, *stid;
13038
13039 upformal = Get_Altentry_UpFormal_Symbol (sym, ploc);
13040
13041 ldid = WN_Ldid(TY_mtype(Ty_Table[formalTY]), 0, upformal, formalTY);
13042
13043 stid = WN_Stid(TY_mtype(Ty_Table[formalTY]), 0, sym, formalTY, ldid);
13044
13045 stid = lower_store(block, stid, actions);
13046 WN_Set_Linenum (stid, current_srcpos);
13047 WN_INSERT_BlockLast(block, stid);
13048 }
13049 else if (ST_promote_parm(sym))
13050 {
13051 if (MTYPE_is_float(TY_mtype(Ty_Table[formalTY])))
13052 {
13053 WN *cvt;
13054 WN *stid;
13055
13056 cvt = lower_promoted_formal(ploc, sym);
13057 stid = WN_Stid(TY_mtype(Ty_Table[formalTY]), 0, sym,
13058 formalTY, cvt);
13059
13060 WN_Set_Linenum (stid, current_srcpos);
13061 WN_INSERT_BlockLast(block, stid);
13062 }
13063 }
13064 }
13065 else if (MTYPE_is_m(TY_mtype(Ty_Table[formalTY])))
13066 {
13067
13068 lower_mload_formal (block, formal, ploc, actions);
13069 }
13070 else
13071 {
13072 WN *cvt, *stid;
13073
13074 cvt = lower_promoted_formal(ploc, sym);
13075
13076 stid = WN_Stid(TY_mtype(Ty_Table[formalTY]), 0, sym, formalTY, cvt);
13077
13078 WN_Set_Linenum (stid, current_srcpos);
13079 WN_INSERT_BlockLast(block, stid);
13080 }
13081 }
13082
13083
13084
13085
13086
13087
13088
13089
13090
13091
13092
13093
13094
13095
13096
13097
13098 static PLOC lower_entry_formals(WN *block, WN *tree, LOWER_ACTIONS actions)
13099 {
13100 PLOC ploc;
13101 INT32 i, n;
13102
13103 #ifdef TARG_NVISA
13104
13105 if (ST_in_global_mem(WN_st(tree))) {
13106 PLOC_size(ploc) = 0; PLOC_offset(ploc) = 0; PLOC_reg(ploc) = 0;
13107 return ploc;
13108 }
13109 #endif
13110
13111 ploc = Setup_Input_Parameter_Locations(ST_pu_type(WN_st(tree)));
13112
13113 if (WN_opcode(tree) == OPC_ALTENTRY)
13114 {
13115 n = WN_kid_count(tree);
13116 Reset_UPFORMAL_Segment();
13117 }
13118 else
13119 {
13120 n = WN_num_formals(tree);
13121 }
13122
13123 for (i = 0; i < n; i++)
13124 {
13125 WN *formal = WN_formal(tree, i);
13126
13127 if (WN_sclass(formal) == SCLASS_FORMAL_REF)
13128 {
13129 ST *base;
13130
13131 base = Get_ST_formal_ref_base(WN_st(formal));
13132 ploc = Get_Input_Parameter_Location(ST_type(base));
13133
13134 if (NotAction(LOWER_ENTRY_FORMAL_REF))
13135 {
13136 continue;
13137 }
13138 else
13139 {
13140 formal = WN_CreateIdname(WN_idname_offset(formal), base);
13141 }
13142 }
13143 else
13144 {
13145 ploc = Get_Input_Parameter_Location(WN_type(formal));
13146
13147 if (NotAction(LOWER_ENTRY_EXIT))
13148 {
13149 continue;
13150 }
13151 }
13152 lower_formals(block, formal, ploc, actions);
13153 }
13154
13155 return ploc;
13156 }
13157
13158 static WN *
13159 Create_Mcount_Call (void)
13160 {
13161 #ifdef TARG_X8664
13162 WN* wn = WN_Create ( OPC_VCALL, 0);
13163 static ST* mcount_st = NULL;
13164
13165 if (!mcount_st) {
13166 PU_IDX pu_idx;
13167 PU& pu = New_PU (pu_idx);
13168 char mcount_name[20];
13169
13170 TY_IDX func_ty_idx;
13171 TY &func_ty = New_TY(func_ty_idx);
13172 TY_Init( func_ty, 0, KIND_FUNCTION, MTYPE_UNKNOWN, STR_IDX_ZERO );
13173 Set_TY_align( func_ty_idx, 1 );
13174 TYLIST tylist_idx;
13175 Set_TYLIST_type( New_TYLIST (tylist_idx), MTYPE_To_TY(Pointer_Mtype) );
13176 Set_TY_tylist( func_ty, tylist_idx );
13177 Set_TYLIST_type( New_TYLIST (tylist_idx), 0 );
13178
13179 Set_TY_has_prototype(func_ty_idx);
13180
13181 mcount_st = New_ST ( GLOBAL_SYMTAB );
13182 PU_Init (pu, func_ty_idx, CURRENT_SYMTAB);
13183 sprintf(mcount_name, "mcount");
13184 ST_Init (mcount_st, Save_Str(mcount_name),
13185 CLASS_FUNC, SCLASS_EXTERN,
13186 EXPORT_PREEMPTIBLE,
13187 TY_IDX(pu_idx));
13188 }
13189 WN_st_idx(wn) = ST_st_idx(mcount_st);
13190 return wn;
13191 #endif
13192
13193
13194
13195 return NULL;
13196 }
13197
13198
13199
13200
13201
13202 struct is_omp_slink
13203 {
13204 BOOL operator () (UINT32, const ST *st) const
13205 {
13206 return (strncmp (ST_name (st), "__ompv_slink_a", 14) == 0);
13207 }
13208 };
13209
13210
13211
13212
13213
13214
13215
13216
13217
13218
13219
13220
13221
13222
13223
13224
13225 static BOOL Is_Omp_Gen_Slink( ST * slink )
13226 {
13227 if( PU_mp( Get_Current_PU( )) && PU_is_nested_func( Get_Current_PU( )))
13228 {
13229
13230 ST_IDX st_idx = For_all_until( St_Table,
13231 CURRENT_SYMTAB, is_omp_slink( ));
13232 if( st_idx != 0 )
13233 return TRUE;
13234 }
13235
13236 return FALSE;
13237 }
13238
13239 #ifdef KEY // for handling taking address of nested functions
13240 struct NESTED_FUNC_TRAMPOLINE_PAIR {
13241 ST_IDX nested_func_st_idx;
13242 ST_IDX trampoline_st_idx;
13243 NESTED_FUNC_TRAMPOLINE_PAIR(void) {}
13244 NESTED_FUNC_TRAMPOLINE_PAIR(ST_IDX nested_func, ST_IDX trampoline):
13245 nested_func_st_idx(nested_func), trampoline_st_idx(trampoline) {}
13246 };
13247
13248 STACK<NESTED_FUNC_TRAMPOLINE_PAIR> nested_func_trampoline_map(Malloc_Mem_Pool);
13249
13250 static ST_IDX find_trampoline(ST_IDX func_st_idx) {
13251 INT i;
13252 for (i = 0; i < nested_func_trampoline_map.Elements(); i++) {
13253 if (nested_func_trampoline_map.Top_nth(i).nested_func_st_idx == func_st_idx)
13254 return nested_func_trampoline_map.Top_nth(i).trampoline_st_idx;
13255 }
13256 Fail_FmtAssertion("cannot find trampoline for nested function (%s)",
13257 ST_name(func_st_idx));
13258 }
13259
13260 static void generate_trampoline_symbol(ST *st) {
13261 PU &pu = Pu_Table[ST_pu(st)];
13262 if (PU_need_trampoline(pu)) {
13263 ST *tramp_st = Gen_Temp_Symbol(
13264 MTYPE_To_TY(Is_Target_64bit() ? MTYPE_C10: MTYPE_F10),
13265 ST_name(st));
13266 Set_ST_addr_saved(tramp_st);
13267 Set_ST_is_shared_auto(*tramp_st);
13268
13269 nested_func_trampoline_map.Push(
13270 NESTED_FUNC_TRAMPOLINE_PAIR(ST_st_idx(st), ST_st_idx(tramp_st)));
13271 }
13272 }
13273
13274
13275
13276
13277
13278
13279
13280
13281
13282
13283 static void allocate_trampoline_symbols(void)
13284 {
13285
13286
13287 while (! nested_func_trampoline_map.Is_Empty() &&
13288 PU_lexical_level(ST_pu(St_Table[nested_func_trampoline_map.Top().nested_func_st_idx]))
13289 >= CURRENT_SYMTAB+1)
13290 nested_func_trampoline_map.Pop();
13291
13292 if (! PU_c_lang(Get_Current_PU()))
13293 return;
13294
13295 if (PU_uplevel(Get_Current_PU())) {
13296 PU &pu = Get_Current_PU();
13297 INITO_IDX pu_inito = PU_misc_info(pu);
13298 INITV_IDX nested_fn_iv;
13299 ST_IDX st_idx;
13300 if (pu_inito != INITO_IDX_ZERO) {
13301 nested_fn_iv = INITO_val(pu_inito);
13302 do {
13303 st_idx = INITV_st(nested_fn_iv);
13304 generate_trampoline_symbol(&St_Table[st_idx]);
13305 nested_fn_iv = INITV_next(nested_fn_iv);
13306 } while (nested_fn_iv != INITV_IDX_ZERO);
13307 }
13308 }
13309 }
13310
13311 BOOL PU_has_trampoline = FALSE;
13312
13313
13314
13315
13316
13317
13318
13319
13320
13321
13322 static void generate_trampoline_code(WN *block)
13323 {
13324 INT i;
13325 NESTED_FUNC_TRAMPOLINE_PAIR cur;
13326 for (i = 0; i < nested_func_trampoline_map.Elements(); i++) {
13327 cur = nested_func_trampoline_map.Top_nth(i);
13328 if (PU_lexical_level(ST_pu(St_Table[cur.nested_func_st_idx])) != CURRENT_SYMTAB+1)
13329 break;
13330
13331
13332 WN *stid, *link;
13333 if (Is_Target_64bit()) {
13334 stid = WN_CreateStid(OPC_I2STID, 0, cur.trampoline_st_idx,
13335 MTYPE_To_TY(MTYPE_I2), WN_Intconst(MTYPE_I4, -17599));
13336 WN_INSERT_BlockFirst(block, stid);
13337 stid = WN_CreateStid(OPC_I4STID, 2, cur.trampoline_st_idx,
13338 MTYPE_To_TY(MTYPE_I4),
13339 WN_Lda(Pointer_Mtype, 0, &St_Table[cur.nested_func_st_idx]));
13340 WN_INSERT_BlockFirst(block, stid);
13341 stid = WN_CreateStid(OPC_I2STID, 6, cur.trampoline_st_idx,
13342 MTYPE_To_TY(MTYPE_I2), WN_Intconst(MTYPE_I4, -17847));
13343 WN_INSERT_BlockFirst(block, stid);
13344 link = WN_LdidPreg(Pointer_Mtype, Frame_Pointer_Preg_Offset);
13345 stid = WN_CreateStid(OPC_U8STID, 8, cur.trampoline_st_idx,
13346 MTYPE_To_TY(Pointer_Mtype), link);
13347 WN_INSERT_BlockFirst(block, stid);
13348 stid = WN_CreateStid(OPC_I2STID, 16, cur.trampoline_st_idx,
13349 MTYPE_To_TY(MTYPE_I2), WN_Intconst(MTYPE_I4, -183));
13350 WN_INSERT_BlockFirst(block, stid);
13351 stid = WN_CreateStid(OPC_I1STID, 18, cur.trampoline_st_idx,
13352 MTYPE_To_TY(MTYPE_I1), WN_Intconst(MTYPE_I4, -29));
13353 WN_INSERT_BlockFirst(block, stid);
13354 }
13355 else {
13356 stid = WN_CreateStid(OPC_I1STID, 0, cur.trampoline_st_idx,
13357 MTYPE_To_TY(MTYPE_I1), WN_Intconst(MTYPE_I4, -71));
13358 WN_INSERT_BlockFirst(block, stid);
13359 link = WN_LdidPreg(Pointer_Mtype, Frame_Pointer_Preg_Offset);
13360 stid = WN_CreateStid(OPC_U4STID, 1, cur.trampoline_st_idx,
13361 MTYPE_To_TY(Pointer_Mtype), link);
13362 WN_INSERT_BlockFirst(block, stid);
13363 stid = WN_CreateStid(OPC_I1STID, 5, cur.trampoline_st_idx,
13364 MTYPE_To_TY(MTYPE_I1), WN_Intconst(MTYPE_I4, -23));
13365 WN_INSERT_BlockFirst(block, stid);
13366 stid = WN_CreateStid(OPC_U4STID, 6, cur.trampoline_st_idx,
13367 MTYPE_To_TY(Pointer_Mtype),
13368 WN_Sub(Pointer_Mtype,
13369 WN_Lda(Pointer_Mtype, 0, &St_Table[cur.nested_func_st_idx]),
13370 WN_Lda(Pointer_Mtype, 10, &St_Table[cur.trampoline_st_idx])));
13371 WN_INSERT_BlockFirst(block, stid);
13372 }
13373
13374 PU_has_trampoline = TRUE;
13375 }
13376 }
13377 #endif
13378
13379
13380
13381
13382
13383
13384
13385
13386
13387
13388
13389
13390
13391
13392
13393
13394
13395
13396
13397
13398
13399
13400
13401 static WN *lower_entry(WN *tree, LOWER_ACTIONS actions)
13402 {
13403 PLOC ploc;
13404 WN *block;
13405
13406 Is_True(((WN_opcode(tree) == OPC_FUNC_ENTRY)
13407 || (WN_opcode(tree) == OPC_ALTENTRY)),
13408 ("expected ENTRY/ALTENTRY node, not %s",
13409 OPCODE_name(WN_opcode(tree))));
13410
13411 if (WHIRL_Return_Val_On && Action(LOWER_RETURN_VAL) &&
13412 WN_operator(tree) == OPR_FUNC_ENTRY)
13413 {
13414 ST_IDX func_stidx = WN_st_idx(tree);
13415 PU_IDX puidx = ST_pu(St_Table[func_stidx]);
13416 TY_IDX prototype = PU_prototype(Pu_Table[puidx]);
13417 RETURN_INFO return_info = Get_Return_Info(TY_ret_type(prototype),
13418 Complex_Not_Simulated
13419 #ifdef TARG_X8664
13420 , PU_ff2c_abi(Pu_Table[puidx])
13421 #endif
13422 );
13423 if (RETURN_INFO_return_via_first_arg(return_info)) {
13424 ST *return_st = Gen_Temp_Symbol(
13425 Make_Pointer_Type(TY_ret_type(prototype), FALSE),
13426 Index_To_Str(Save_Str2(".return.",
13427 ST_name(func_stidx))));
13428 Set_ST_sclass(return_st, SCLASS_FORMAL);
13429 Set_ST_is_value_parm(return_st);
13430 WN *idname = WN_CreateIdname(0, return_st);
13431
13432 WN *n_tree = WN_CreateEntry(WN_num_formals(tree)+1, func_stidx,
13433 WN_func_body(tree), WN_func_pragmas(tree),
13434 WN_func_varrefs(tree));
13435 WN_Set_Linenum(n_tree, WN_Get_Linenum(tree));
13436 WN_set_map_id(n_tree, WN_map_id(tree));
13437 WN_kid0(n_tree) = idname;
13438 for (INT32 i = 0; i < WN_kid_count(tree); i++)
13439 WN_kid(n_tree, i+1) = WN_kid(tree, i);
13440
13441 if (RID_map != WN_MAP_UNDEFINED) {
13442 RID *rid = (RID *)WN_MAP_Get(RID_map, tree);
13443 if (RID_rwn(rid) == tree)
13444 RID_rwn(rid) = n_tree;
13445 }
13446 WN_Delete(tree);
13447 tree = n_tree;
13448 #ifdef KEY
13449
13450 Set_PU_Info_tree_ptr (Current_PU_Info, tree);
13451 #endif
13452 }
13453 }
13454
13455 setCurrentState(tree, actions);
13456 block = WN_CreateBlock();
13457
13458 if (Action(LOWER_ENTRY_EXIT))
13459 {
13460 ploc = lower_entry_formals(block, tree, actions);
13461
13462 if (TY_is_varargs(Ty_Table[PU_prototype(Pu_Table[ST_pu(WN_st(tree))])]))
13463 {
13464
13465
13466
13467
13468 TYPE_ID type = Def_Int_Mtype;
13469
13470 #ifdef TARG_X8664
13471 INT num_vararg_xmms = 0;
13472 ST *xmm_save_temp_st;
13473
13474
13475 if( Is_Target_64bit() ){
13476 ploc = Get_Vararg_Input_Parameter_Location (ploc);
13477
13478 } else
13479 #endif
13480 if (PLOC_is_nonempty(ploc) && !PLOC_on_stack(ploc)) {
13481
13482 ploc = Get_Vararg_Input_Parameter_Location (ploc);
13483 }
13484
13485 while (!PLOC_on_stack(ploc))
13486 {
13487
13488
13489
13490 WN *wn;
13491 ST *st;
13492
13493 #ifdef TARG_X8664
13494 if (Preg_Offset_Is_Float(PLOC_reg(ploc))) {
13495 if (num_vararg_xmms == 0)
13496 xmm_save_temp_st = Get_Vararg_Symbol (ploc);
13497 num_vararg_xmms++;
13498
13499 ploc = Get_Vararg_Input_Parameter_Location (ploc);
13500 continue;
13501 }
13502 #endif
13503
13504 wn = WN_Ldid (type, PLOC_reg(ploc), Int_Preg, ST_type(Int_Preg));
13505
13506
13507
13508 st = Get_Vararg_Symbol (ploc);
13509
13510 wn = WN_Stid (type, 0, st, ST_type(st), wn);
13511 WN_Set_Linenum (wn, current_srcpos);
13512 WN_INSERT_BlockLast(block, wn);
13513
13514 ploc = Get_Vararg_Input_Parameter_Location (ploc);
13515 }
13516
13517 #ifdef TARG_X8664
13518 if (num_vararg_xmms) {
13519 WN *ikids[3];
13520 WN *wn;
13521 wn = WN_Ldid(MTYPE_I4, RAX, Int_Preg, ST_type(Int_Preg));
13522 ikids[0] = WN_CreateParm(MTYPE_I4, wn, MTYPE_To_TY(MTYPE_I4),
13523 WN_PARM_BY_VALUE);
13524 wn = WN_Intconst(MTYPE_I4, num_vararg_xmms);
13525 ikids[1] = WN_CreateParm(MTYPE_I4, wn, MTYPE_To_TY(MTYPE_I4),
13526 WN_PARM_BY_VALUE);
13527 wn = WN_Lda(Pointer_type, 0, xmm_save_temp_st);
13528 ikids[2] = WN_CreateParm(Pointer_type, wn, MTYPE_To_TY(Pointer_type),
13529 WN_PARM_BY_VALUE);
13530 wn = WN_Create(OPR_INTRINSIC_CALL, MTYPE_V, MTYPE_V, 3);
13531 WN_intrinsic(wn) = INTRN_SAVE_XMMS;
13532 WN_kid0(wn) = ikids[0];
13533 WN_kid1(wn) = ikids[1];
13534 WN_kid2(wn) = ikids[2];
13535 WN_Set_Linenum (wn, current_srcpos);
13536 WN_INSERT_BlockLast(block, wn);
13537 }
13538 #endif
13539 }
13540
13541
13542
13543
13544 {
13545 WN *trapuvBlock = WN_CreateBlock();
13546
13547 trapuvBlock = lower_trapuv(trapuvBlock, tree, actions);
13548
13549 trapuvBlock= lower_block(trapuvBlock, actions);
13550
13551 WN_INSERT_BlockLast(block, trapuvBlock);
13552 }
13553
13554 #if defined(TARG_X8664)
13555
13556
13557
13558 if (OPT_Malloc_Alg >= 1 &&
13559
13560
13561 (OPT_Malloc_Alg_Set || Is_Target_64bit() || Is_Target_EM64T()) &&
13562 (!strcmp(Cur_PU_Name, "main") ||
13563 !strcmp(Cur_PU_Name, "MAIN__"))) {
13564 WN *mallocBlock = WN_CreateBlock();
13565 mallocBlock = lower_malloc_alg(mallocBlock, tree, actions);
13566 mallocBlock = lower_block(mallocBlock, actions);
13567 WN_INSERT_BlockLast(block, mallocBlock);
13568 }
13569 #endif
13570 }
13571 else if (Action(LOWER_ENTRY_FORMAL_REF))
13572 {
13573 ploc = lower_entry_formals(block, tree, actions);
13574 }
13575
13576 #if !defined(TARG_IA32) && !defined(TARG_X8664)
13577 if (Action(LOWER_SPLIT_SYM_ADDRS))
13578 #else
13579
13580
13581
13582 if (Action(LOWER_SLINK_SAVE))
13583 #endif
13584 {
13585
13586
13587
13588 ST *slink = Find_Slink_Symbol(CURRENT_SYMTAB);
13589 if (slink)
13590 {
13591 if( Is_Omp_Gen_Slink( slink ))
13592 {
13593
13594
13595
13596 WN *ld, *wn;
13597 #if defined(TARG_IA32) || defined(TARG_X8664)
13598 if (Is_Target_32bit()) {
13599 WN *formal = WN_formal(current_function, 1);
13600 ld = WN_Ldid(Pointer_type, 0, WN_st(formal), WN_type(formal));
13601 }
13602 else
13603 #endif
13604 ld = WN_LdidPreg( Pointer_type, First_Int_Preg_Param_Offset+1 );
13605
13606 wn = WN_Stid( Pointer_type, 0, slink, ST_type( slink ), ld );
13607
13608 WN_Set_Linenum( wn, current_srcpos );
13609 WN_INSERT_BlockFirst( block, wn );
13610 }
13611 else
13612 {
13613 WN *ld, *wn;
13614
13615 ld = WN_LdidPreg(Pointer_type, Static_Link_Preg_Offset);
13616
13617 wn = WN_Stid (Pointer_type, 0, slink, ST_type(slink), ld);
13618
13619 WN_Set_Linenum (wn, current_srcpos);
13620 WN_INSERT_BlockFirst(block, wn);
13621 }
13622 }
13623 #ifdef KEY
13624 if (PU_has_nonlocal_goto_label(Get_Current_PU())) {
13625
13626 ST *fpsave_sym = Create_FPSave_Symbol();
13627 WN *fpld = WN_LdidPreg(Pointer_type, Frame_Pointer_Preg_Offset);
13628 WN *fpsave = WN_Stid(Pointer_type, 0, fpsave_sym, ST_type(fpsave_sym),
13629 fpld);
13630 WN_Set_Linenum (fpsave, current_srcpos);
13631 WN_INSERT_BlockFirst(block, fpsave);
13632
13633
13634 ST *spsave_sym = Create_SPSave_Symbol();
13635 WN *spld = WN_LdidPreg(Pointer_type, Stack_Pointer_Preg_Offset);
13636 WN *spsave = WN_Stid(Pointer_type, 0, spsave_sym, ST_type(spsave_sym),
13637 spld);
13638 WN_Set_Linenum (spsave, current_srcpos);
13639 WN_INSERT_BlockFirst(block, spsave);
13640 }
13641 #endif
13642 }
13643
13644 #ifdef TARG_SL
13645 if (Action(LOWER_RETURN_VAL) && (WN_operator(tree) == OPR_FUNC_ENTRY) && (DEBUG_Stack_Check & STACK_FUNC_CHECK)) {
13646 char * PU_name = ST_name(&St_Table[PU_Info_proc_sym(Current_PU_Info)]);
13647 if (strcmp(PU_name, "__stackcheck") != 0) {
13648 TY_IDX ty = Make_Function_Type(MTYPE_To_TY(MTYPE_V ));
13649 ST *st = Gen_Intrinsic_Function(ty, "__stackcheck" );
13650 Clear_PU_no_side_effects(Pu_Table[ST_pu(st)]);
13651 Clear_PU_is_pure(Pu_Table[ST_pu(st)]);
13652 Set_PU_no_delete(Pu_Table[ST_pu(st)]);
13653 WN *wn_call = WN_Call(MTYPE_V, MTYPE_V, 0, st );
13654 WN_Set_Call_Default_Flags(wn_call);
13655 WN_Set_Linenum (wn_call, current_srcpos);
13656 WN_INSERT_BlockLast(block, wn_call);
13657 }
13658 }
13659 #endif
13660
13661 if (WN_opcode(tree) == OPC_FUNC_ENTRY)
13662 {
13663
13664 if (WN_func_pragmas(tree) && Action(LOWER_MP)) {
13665 WN *wn;
13666 for (wn = WN_first(WN_func_pragmas(tree)); wn; wn = WN_next(wn)) {
13667 if (((WN_opcode(wn) == OPC_PRAGMA) || (WN_opcode(wn) == OPC_XPRAGMA))
13668 && (WN_pragmas[WN_pragma(wn)].users & PUSER_MP)) {
13669 (void) lower_mp(NULL, wn, actions);
13670 }
13671 }
13672 }
13673
13674 if (Call_Mcount && Action(LOWER_ENTRY_EXIT)) {
13675 WN *profcall = Create_Mcount_Call ();
13676 if (profcall) {
13677 WN_Set_Linenum (profcall, current_srcpos);
13678 WN_INSERT_BlockLast(block, profcall);
13679 }
13680 }
13681
13682 #ifdef KEY
13683 if (Action(LOWER_RETURN_VAL))
13684 allocate_trampoline_symbols();
13685 #endif
13686
13687 WN_INSERT_BlockFirst(WN_func_body(tree), block);
13688
13689
13690 WN_func_body(tree) = lower_block(WN_func_body(tree), actions);
13691 #ifdef KEY
13692 if (Action(LOWER_TO_CG)) {
13693 block = WN_CreateBlock();
13694 generate_trampoline_code(block);
13695 WN_INSERT_BlockFirst(WN_func_body(tree), block);
13696 }
13697 #endif
13698 return tree;
13699 }
13700 else
13701 {
13702 block = lower_block(block, actions);
13703 WN_INSERT_BlockFirst(block, tree);
13704 }
13705 return block;
13706 }
13707
13708 #ifdef LOW_LANDING_PAD
13709
13710 static WN *lower_landing_pad_entry(WN *tree)
13711 {
13712 WN * block = WN_CreateBlock();
13713 WN_INSERT_BlockAfter (block, NULL, tree);
13714
13715 ST_IDX exc_ptr_param = TCON_uval (INITV_tc_val (INITO_val (PU_misc_info (Get_Current_PU()))));
13716 ST exc_ptr_st = St_Table[exc_ptr_param];
13717
13718 #ifdef TARG_X8664
13719 WN *exc_ptr_rax = WN_LdidPreg (Pointer_Mtype, RAX);
13720 #elif defined(TARG_IA64)
13721 WN *exc_ptr_rax = WN_LdidPreg (Pointer_Mtype, 15);
13722 #elif defined(TARG_MIPS)
13723
13724 WN *exc_ptr_rax = WN_LdidPreg (Pointer_Mtype, 4);
13725 #else
13726 #error ("TARG_IA64 not defined!")
13727 #endif
13728
13729 WN *exc_ptr_stid = WN_Stid (Pointer_Mtype, 0, &exc_ptr_st,
13730 ST_type(exc_ptr_st), exc_ptr_rax);
13731
13732 ST_IDX filter_param = TCON_uval (INITV_tc_val (INITV_next (INITO_val (PU_misc_info (Get_Current_PU())))));
13733 ST filter_st = St_Table[filter_param];
13734
13735 #ifdef TARG_X8664
13736 WN *filter_rdx = WN_LdidPreg (Is_Target_64bit() ? MTYPE_U8 : MTYPE_U4, RDX);
13737 #elif defined(TARG_IA64)
13738 WN *filter_rdx = WN_LdidPreg (Is_Target_64bit() ? MTYPE_U8 : MTYPE_U4, 16);
13739 #elif defined(TARG_MIPS)
13740
13741 WN *filter_rdx = WN_LdidPreg (Is_Target_64bit() ? MTYPE_U8 : MTYPE_U4, 5);
13742 #else
13743 #error ("TARG_IA64 not defined!")
13744 #endif
13745
13746 WN *filter_stid = WN_Stid (Is_Target_64bit() ? MTYPE_U8 : MTYPE_U4, 0, &filter_st,
13747 ST_type(filter_st), filter_rdx);
13748
13749
13750 WN_Set_Linenum(exc_ptr_stid, current_srcpos);
13751 WN_INSERT_BlockLast (block, exc_ptr_stid);
13752 WN_Set_Linenum(filter_stid, current_srcpos);
13753 WN_INSERT_BlockLast (block, filter_stid);
13754 return block;
13755 }
13756 #endif // LOW_LANDING_PAD
13757
13758
13759
13760
13761
13762
13763
13764
13765
13766
13767
13768 static WN *lower_region(WN *tree, LOWER_ACTIONS actions)
13769 {
13770 Is_True(WN_opcode(WN_region_body(tree)) == OPC_BLOCK,
13771 ("kid of REGION should be OPC_BLOCK, not %s",
13772 OPCODE_name(WN_opcode(WN_region_body(tree)))));
13773
13774 setCurrentState(tree, actions);
13775 if (current_function == NULL) {
13776
13777 current_function = PU_Info_tree_ptr(Current_PU_Info);
13778 }
13779
13780 if (Action(LOWER_REGION))
13781 {
13782 RID *rid = REGION_get_rid( tree );
13783
13784 Is_True(rid, ("expected valid region id"));
13785
13786 max_region++;
13787
13788
13789
13790
13791
13792 if (RID_lowered(rid) == (LOWER_ACTIONS) NULL)
13793 {
13794 RID_lowered(rid) = actions;
13795 }
13796 else
13797 {
13798 actions ^= (RID_lowered(rid) & (LOWER_CALL | LOWER_ENTRY_EXIT));
13799 }
13800
13801 if (actions)
13802 {
13803 WN_region_body(tree) = lower_block(WN_region_body(tree),
13804 actions | LOWER_REGION);
13805 }
13806 }
13807 else
13808 {
13809 WN_region_body(tree) = lower_block(WN_region_body(tree), actions);
13810 }
13811
13812 return tree;
13813 }
13814
13815 WN *lower_scf_non_recursive(WN *block, WN *tree, LOWER_ACTIONS actions)
13816 {
13817 return lower_scf(block,tree,actions | LOWER_TOP_LEVEL_ONLY);
13818 }
13819
13820
13821
13822
13823
13824
13825
13826
13827
13828
13829
13830 static WN *lower_scf(WN *block, WN *tree, LOWER_ACTIONS actions)
13831 {
13832 CURRENT_STATE scfState = pushCurrentState(tree, actions);
13833
13834 switch (WN_opcode(tree))
13835 {
13836 case OPC_DO_WHILE:
13837 block = lower_do_while(block, tree, actions);
13838 break;
13839
13840 case OPC_WHILE_DO:
13841 block = lower_while_do(block, tree, actions);
13842 break;
13843
13844 case OPC_DO_LOOP:
13845 block = lower_do_loop(block, tree, actions);
13846 break;
13847
13848 case OPC_IF:
13849 block = lower_if(block, tree, actions);
13850 break;
13851
13852 case OPC_BLOCK:
13853 block = lower_block(tree, actions);
13854 break;
13855
13856 case OPC_REGION:
13857 block = lower_region(tree, actions);
13858 break;
13859 }
13860
13861 popCurrentState(scfState);
13862 return block;
13863 }
13864
13865
13866
13867
13868
13869
13870
13871
13872
13873
13874 static WN *lower_trapuv(WN *block, WN *tree, LOWER_ACTIONS actions)
13875 {
13876 if ( DEBUG_Trap_Uv == FALSE
13877 #ifdef KEY
13878 && DEBUG_Zero_Uv == FALSE
13879 #endif
13880 )
13881 return block;
13882
13883 {
13884 ST *st;
13885 ST *slink = Find_Slink_Symbol(CURRENT_SYMTAB);
13886
13887 INT32 i;
13888 FOREACH_SYMBOL(CURRENT_SYMTAB, st, i)
13889 {
13890 TY_IDX type;
13891 TYPE_ID btype;
13892 INT32 size;
13893
13894 if (ST_class(st) != CLASS_VAR)
13895 continue;
13896
13897 if (ST_sclass(st) != SCLASS_AUTO)
13898 continue;
13899
13900 if (Has_Base_Block(st)) {
13901 #ifdef KEY
13902
13903 char *name = ST_name(st);
13904 char *basename = ST_name(ST_base(st));
13905 char *buf = (char *) alloca(strlen(name) + 10);
13906 strcpy(buf, name);
13907 strcat(buf + strlen(name), ".BLOCK");
13908 if (strcmp(basename, buf))
13909 #endif
13910 continue;
13911 }
13912
13913 if (ST_is_uplevelTemp(st) || st == slink)
13914 continue;
13915
13916 if (ST_is_not_used(st))
13917 continue;
13918 if (Is_Allocated(st))
13919 continue;
13920
13921 type = ST_type(st);
13922 btype = TY_mtype(Ty_Table[type]);
13923 size = TY_size(type);
13924
13925 Is_True(ST_pu_defined(st), ("trapuv auto or temp not ST_pu_defined"));
13926
13927 switch(TY_kind(type))
13928 {
13929 case KIND_SCALAR:
13930 case KIND_POINTER:
13931 case KIND_FUNCTION:
13932 {
13933 WN *con, *stid;
13934
13935 Is_True((MTYPE_RegisterSize(btype) == size),
13936 ("bad size for scalar/pointer"));;
13937
13938 #ifdef KEY
13939 if (DEBUG_Zero_Uv) {
13940 #if defined(TARG_X8664)
13941 if (MTYPE_is_vector(btype)) {
13942 con = Make_Const(Create_Simd_Const(btype,
13943 Host_To_Targ(MTYPE_I4, 0)));
13944 } else {
13945 #endif
13946 if (MTYPE_is_integral(btype)) {
13947 con = WN_Intconst(size < 4 ?
13948 Mtype_TransferSign(btype, MTYPE_I4) : btype,
13949 0);
13950 } else {
13951 con = WN_Floatconst(btype, 0.0);
13952 }
13953 #if defined(TARG_X8664)
13954 }
13955 #endif
13956 } else
13957 #endif
13958 con = WN_UVConst(btype);
13959
13960
13961 #ifdef KEY
13962
13963
13964 if (btype == MTYPE_FQ) {
13965 TYPE_ID ty = MTYPE_U8;
13966 TCON c = ST_tcon_val(WN_st(con));
13967 WN *intconst = WN_Intconst(ty, TCON_k0(c));
13968 stid = WN_Stid(ty, 0, st, type, intconst);
13969 #ifdef TARG_MIPS
13970 WN_Set_Linenum(stid, WN_Get_Linenum(tree));
13971 WN_INSERT_BlockLast(block, stid);
13972 intconst = WN_Intconst(ty, TCON_k0(c));
13973 stid = WN_Stid(ty, 8, st, type, intconst);
13974 #endif
13975
13976 }
13977 else if (!MTYPE_is_integral(btype) && !MTYPE_is_vector(btype)) {
13978 Is_True(size == 4 || size == 8,
13979 ("lower_trapuv: unexpected type size"));
13980 TYPE_ID ty = (size == 8) ? MTYPE_U8 : MTYPE_U4;
13981 TCON c = ST_tcon_val(WN_st(con));
13982 WN *intconst = WN_Intconst(ty, TCON_k0(c));
13983 stid = WN_Stid(ty, 0, st, type, intconst);
13984 }
13985 else
13986 #endif
13987 stid = WN_Stid(btype, 0, st, type, con);
13988 WN_Set_Linenum(stid, WN_Get_Linenum(tree));
13989 WN_INSERT_BlockLast(block, stid);
13990 }
13991 break;
13992
13993 case KIND_ARRAY:
13994 case KIND_STRUCT:
13995 {
13996
13997
13998
13999
14000
14001
14002
14003
14004
14005
14006
14007
14008
14009
14010
14011
14012
14013
14014
14015
14016
14017 TY_IDX ptype = Make_Pointer_Type(type);
14018 WN *conUV4 = NULL;
14019 INT32 todo = size;
14020 INT32 offset = 0;
14021 UINT32 ncon;
14022 TYPE_ID q;
14023
14024 for (q= Max_Uint_Mtype; q!=MTYPE_UNKNOWN; q= Mtype_prev_alignment(q))
14025 {
14026 WN *con, *lda, *num, *store;
14027 INT32 qSize = MTYPE_RegisterSize(q);
14028 INT32 qBits = MTYPE_size_reg(q);
14029 INT32 nMoves = todo / qSize;
14030 INT32 residue = todo % qSize;
14031
14032 if (q >= MTYPE_U4)
14033 {
14034 if (nMoves)
14035 {
14036 #ifdef KEY
14037 if (DEBUG_Zero_Uv) {
14038 con = WN_Intconst(q, 0);
14039 } else if (TY_kind(type) == KIND_ARRAY) {
14040
14041 TY_IDX etype_idx = Ty_Table[type].Etype();
14042 if (TY_mtype(etype_idx) == MTYPE_F8 ||
14043 TY_mtype(etype_idx) == MTYPE_C8) {
14044 con = WN_UVConst(MTYPE_U8);
14045 } else {
14046 con = WN_UVConst(MTYPE_U4);
14047
14048
14049 Is_True(WN_operator(con) == OPR_INTCONST,
14050 ("lower_trapuv: not an INTCONST WN"));
14051 if (q > MTYPE_U4) {
14052 UINT64 val = WN_const_val(con);
14053 con = WN_Intconst(q, (val << 32) | val );
14054 }
14055 }
14056 } else
14057 #endif
14058 con = WN_UVConst(q);
14059
14060 if ( DEBUG_Trap_Uv_Rjustify )
14061 {
14062 con = WN_RotateIntconst(con, residue*8);
14063 }
14064
14065 lda = WN_Lda(Pointer_type, 0, st);
14066 num = WN_Intconst(MTYPE_I4, nMoves * qSize);
14067 #ifdef KEY
14068
14069
14070
14071 TY_IDX byte_ptype = Make_Pointer_Type(MTYPE_To_TY(MTYPE_U1));
14072 store = WN_CreateMstore(offset, byte_ptype, con, lda, num);
14073 #else
14074
14075 store = WN_CreateMstore(offset, ptype, con, lda, num);
14076 #endif
14077
14078 WN_Set_Linenum(store, WN_Get_Linenum(tree));
14079 WN_INSERT_BlockLast(block, store);
14080
14081 todo -= (nMoves * qSize);
14082 offset += (nMoves * qSize);
14083 }
14084 }
14085 else
14086 {
14087
14088
14089
14090 if (todo > 0)
14091 {
14092 if (conUV4==NULL)
14093 {
14094 #ifdef KEY
14095 if (DEBUG_Zero_Uv)
14096 conUV4 = WN_Intconst(MTYPE_U4, 0);
14097 else
14098 #endif
14099 conUV4 = WN_UVConst(MTYPE_U4);
14100 ncon = WN_const_val(conUV4);
14101 }
14102 if (nMoves)
14103 {
14104 if ( DEBUG_Trap_Uv_Rjustify )
14105 {
14106 con = WN_Intconst(MTYPE_U4, ncon>>(todo*8 - qBits));
14107 }
14108 else
14109 {
14110 con = WN_Intconst(MTYPE_U4,
14111 ncon>>(MTYPE_size_reg(MTYPE_U4)-qBits));
14112 ncon <<= qBits;
14113 }
14114
14115 store = WN_Stid(q, offset, st, type, con);
14116 WN_Set_Linenum(store, WN_Get_Linenum(tree));
14117 WN_INSERT_BlockLast(block, store);
14118
14119 todo -= (nMoves * qSize);
14120 offset += (nMoves * qSize);
14121 }
14122 }
14123 }
14124 }
14125 if (conUV4)
14126 WN_Delete(conUV4);
14127
14128 }
14129 break;
14130 }
14131 }
14132 }
14133 return block;
14134 }
14135
14136 #if defined(KEY) && !(defined(TARG_SL) || defined(TARG_NVISA))
14137
14138
14139
14140
14141
14142
14143
14144 static WN *
14145 lower_malloc_alg(WN *block, WN *tree, LOWER_ACTIONS actions)
14146 {
14147 WN *call;
14148 TY_IDX ty = Make_Function_Type(MTYPE_To_TY(MTYPE_V));
14149 ST *st = Gen_Intrinsic_Function(ty, "__pathscale_malloc_alg");
14150
14151 Set_PU_no_side_effects(Pu_Table[ST_pu(st)]);
14152 Set_PU_is_pure(Pu_Table[ST_pu(st)]);
14153
14154 call = WN_Call(MTYPE_V, MTYPE_V, 1, st);
14155 switch(OPT_Malloc_Alg) {
14156 case 1:
14157 WN_kid0(call) = WN_CreateParm(MTYPE_I4, WN_Intconst(MTYPE_I4, 1),
14158 MTYPE_To_TY(MTYPE_I4), WN_PARM_BY_VALUE);
14159 break;
14160 case 2:
14161 WN_kid0(call) = WN_CreateParm(MTYPE_I4, WN_Intconst(MTYPE_I4, 2),
14162 MTYPE_To_TY(MTYPE_I4), WN_PARM_BY_VALUE);
14163 break;
14164 case 3:
14165 WN_kid0(call) = WN_CreateParm(MTYPE_I4, WN_Intconst(MTYPE_I4, 3),
14166 MTYPE_To_TY(MTYPE_I4), WN_PARM_BY_VALUE);
14167 break;
14168 default:
14169 FmtAssert(0, ("Lower_Malloc_Alg: -OPT:malloc_alg should be less than or equal to 3!"));
14170 break;
14171 }
14172
14173 WN_Set_Linenum(call, current_srcpos);
14174 call = lower_call(block, call, actions);
14175 WN_INSERT_BlockLast(block, call);
14176
14177 return block;
14178 }
14179 #endif
14180
14181 static void lower_actions_fprintf(FILE *f, LOWER_ACTIONS actions)
14182 {
14183 LOWER_ACTIONS i = 1;
14184
14185 while (actions)
14186 {
14187 if (Action(i))
14188 {
14189 fprintf(f, "%s ", LOWER_ACTIONS_name(i));
14190 actions = actions ^ i;
14191 }
14192 i <<= 1;
14193 }
14194 fprintf(f, "\n");
14195 }
14196
14197
14198
14199
14200
14201
14202
14203
14204
14205 const char * LOWER_ACTIONS_name(LOWER_ACTIONS actions)
14206 {
14207 if ((actions-1) & actions)
14208 {
14209 DevWarn("LOWER_ACTION_name(0x%llx): expected only one flag at a time",
14210 actions);
14211 }
14212
14213 switch(actions)
14214 {
14215 case LOWER_NULL: return "LOWER_NULL";
14216 case LOWER_DO_LOOP: return "LOWER_DO_LOOP";
14217 case LOWER_DO_WHILE: return "LOWER_DO_WHILE";
14218 case LOWER_WHILE_DO: return "LOWER_WHILE_DO";
14219 case LOWER_IF: return "LOWER_IF";
14220 case LOWER_COMPLEX: return "LOWER_COMPLEX";
14221 case LOWER_ARRAY: return "LOWER_ARRAY";
14222 case LOWER_SPLIT_CONST_OFFSETS: return "LOWER_SPLIT_CONST_OFFSETS";
14223 case LOWER_ENTRY_EXIT: return "LOWER_ENTRY_EXIT";
14224 case LOWER_CALL: return "LOWER_CALL";
14225 case LOWER_SPLIT_SYM_ADDRS: return "LOWER_SPLIT_SYM_ADDRS";
14226 case LOWER_IO_STATEMENT: return "LOWER_IO_STATEMENT";
14227 case LOWER_MSTORE: return "LOWER_MSTORE";
14228 case LOWER_CVT: return "LOWER_CVT";
14229 case LOWER_MP: return "LOWER_MP";
14230 case LOWER_8X_ARRAY: return "LOWER_8X_ARRAY";
14231 case LOWER_INTRINSIC: return "LOWER_INTRINSIC";
14232 case LOWER_INLINE_INTRINSIC: return "LOWER_INLINE_INTRINSIC";
14233 case LOWER_INL_STACK_INTRINSIC: return "LOWER_INL_STACK_INTRINSIC";
14234 case LOWER_REGION: return "LOWER_REGION";
14235 case LOWER_QUAD: return "LOWER_QUAD";
14236 case LOWER_COMPGOTO: return "LOWER_COMPGOTO";
14237 case LOWER_MADD: return "LOWER_MADD";
14238 case LOWER_TOP_LEVEL_ONLY: return "LOWER_TOP_LEVEL_ONLY";
14239 case LOWER_PREFETCH_MAPS: return "LOWER_PREFETCH_MAPS";
14240 case LOWER_ALIAS_MAPS: return "LOWER_ALIAS_MAPS";
14241 case LOWER_DEPGRAPH_MAPS: return "LOWER_DEPGRAPH_MAPS";
14242 case LOWER_PARITY_MAPS: return "LOWER_PARITY_MAPS";
14243
14244 case LOWER_FREQUENCY_MAPS: return "LOWER_FREQUENCY_MAPS";
14245 case LOWER_PICCALL: return "LOWER_PICCALL";
14246 case LOWER_BASE_INDEX: return "LOWER_BASE_INDEX";
14247 case LOWER_TO_CG: return "LOWER_TO_CG";
14248 case LOWER_ASSERT: return "LOWER_ASSERT";
14249 case LOWER_FORMAL_REF: return "LOWER_FORMAL_REF";
14250 case LOWER_UPLEVEL: return "LOWER_UPLEVEL";
14251 case LOWER_ENTRY_FORMAL_REF: return "LOWER_ENTRY_FORMAL_REF";
14252 case LOWER_SHORTCIRCUIT: return "LOWER_SHORTCIRCUIT";
14253 case LOWER_TREEHEIGHT: return "LOWER_TREEHEIGHT";
14254 case LOWER_RETURN_VAL: return "LOWER_RETURN_VAL";
14255 case LOWER_MLDID_MSTID: return "LOWER_MLDID_MSTID";
14256 case LOWER_BIT_FIELD_ID: return "LOWER_BIT_FIELD_ID";
14257 case LOWER_BITS_OP: return "LOWER_BITS_OP";
14258 case LOWER_TO_MEMLIB: return "LOWER_TO_MEMLIB";
14259 default: return "<unrecognized>";
14260 }
14261 }
14262
14263 static const char * MSTORE_ACTIONS_name(MSTORE_ACTIONS actions)
14264 {
14265 switch(actions)
14266 {
14267 case MSTORE_aggregate: return "scalar moves ";
14268 case MSTORE_loop: return "generate loop ";
14269 case MSTORE_intrinsic_bzero: return "intrinsic bzero ";
14270 case MSTORE_intrinsic_memset: return "intrinsic memset";
14271 case MSTORE_intrinsic_memcpy: return "intrinsic memcpy";
14272 default: return "<unrecognized>";
14273 }
14274 }
14275
14276
14277 void WN_Lower_Checkdump(const char *msg, WN *tree, LOWER_ACTIONS actions)
14278 {
14279 traceAlignment = Get_Trace(TP_LOWER, 0x004);
14280 traceSplitSymOff = Get_Trace(TP_LOWER, 0x010);
14281 traceIO = Get_Trace(TP_LOWER, 0x020);
14282 traceSpeculate = Get_Trace(TP_LOWER, 0x040);
14283 traceTreeHeight = Get_Trace(TP_LOWER, 0x080);
14284 traceMload = Get_Trace(TP_LOWER, 0x100);
14285
14286
14287 if (Get_Trace(TP_LOWER, 0x008))
14288 {
14289 enable_tree_freq_display();
14290 }
14291
14292 if (Get_Trace(TKIND_IR, TP_LOWER))
14293 {
14294 fputs(DBar, TFile);
14295 fprintf(TFile, "WN_Lower: \"%s\"\n", msg);
14296 if (actions)
14297 {
14298 fprintf(TFile, "flags are:\n");
14299 lower_actions_fprintf(TFile, actions);
14300 }
14301 fdump_tree(TFile, tree);
14302 fputs(DBar, TFile);
14303 }
14304
14305 if (Get_Trace(TP_LOWER, 0x001))
14306 {
14307 IR_dump_map_info = TRUE;
14308
14309 fprintf(TFile, "WN_Lower: LNO DEP GRAPH\n");
14310 LNOPrintDepGraph(TFile);
14311 }
14312 if (Get_Trace(TP_LOWER, 0x002))
14313 {
14314 IR_dump_map_info = TRUE;
14315
14316 fprintf(TFile, "WN_Lower: WOPT ALIAS INFO\n");
14317 fdump_dep_tree(TFile, tree, alias_manager);
14318 }
14319
14320 if (Get_Trace(TKIND_SYMTAB,TP_LOWER)) {
14321 fprintf(TFile,"\n\n========== Symbol tables after Lowering ==========\n");
14322 Print_symtab (TFile, GLOBAL_SYMTAB);
14323 Print_symtab (TFile, CURRENT_SYMTAB);
14324 }
14325
14326
14327
14328
14329 if (Action(LOWER_SPLIT_SYM_ADDRS))
14330 {
14331 if (Enable_WN_Simp && WN_Simp_Fold_ILOAD)
14332 {
14333 DevWarn("disabling option WN_Simp_Fold_ILOAD"
14334 " while lowering action LOWER_SPLIT_SYM_ADDRS");
14335 WN_Simp_Fold_ILOAD = FALSE;
14336 }
14337 }
14338
14339
14340
14341
14342 {
14343 WN *pragma= NULL;
14344
14345 traceWoptFinishedOpt= FALSE;
14346
14347 switch(WN_operator(tree))
14348 {
14349 case OPR_FUNC_ENTRY:
14350 pragma= WN_func_pragmas(tree);
14351 break;
14352 case OPR_REGION:
14353 pragma= WN_region_pragmas(tree);
14354 break;
14355 }
14356 if (pragma)
14357 {
14358 WN *wn;
14359 for(wn= WN_first(pragma); wn; wn= WN_next(wn))
14360 {
14361 if (WN_pragma(wn) == WN_PRAGMA_WOPT_FINISHED_OPT)
14362 traceWoptFinishedOpt= TRUE;
14363 }
14364 }
14365 }
14366 }
14367
14368
14369
14370
14371
14372
14373
14374
14375
14376
14377
14378
14379
14380
14381
14382 static LOWER_ACTIONS lower_actions(WN *pu, LOWER_ACTIONS actions)
14383 {
14384 if (OPT_Lower_Treeheight && Action(LOWER_TO_CG))
14385 actions |= LOWER_TREEHEIGHT;
14386
14387 if (Action(LOWER_TO_CG))
14388 {
14389
14390
14391
14392 actions |= lowering_actions ^ (LOWER_ENTRY_EXIT |
14393 LOWER_ENTRY_FORMAL_REF |
14394 LOWER_FORMAL_REF |
14395 #if !defined(TARG_SL) // move to below since need to be called multiple timers >= -O2
14396 LOWER_UPLEVEL |
14397 #endif
14398 #if !defined(TARG_IA32) && !defined(TARG_X8664)
14399 LOWER_SPLIT_SYM_ADDRS |
14400 #else
14401 LOWER_SLINK_SAVE |
14402 #endif
14403 #ifdef TARG_MIPS // need LOWER_SPLIT_CONST_OFFSETS for correctness in -O0 compiles
14404 LOWER_SPLIT_CONST_OFFSETS |
14405 #endif
14406 LOWER_CALL |
14407 LOWER_MLDID_MSTID |
14408 LOWER_RETURN_VAL);
14409
14410 #ifdef TARG_MIPS // need LOWER_SPLIT_CONST_OFFSETS for correctness in -O0 compiles
14411 actions &= ~LOWER_BASE_INDEX;
14412 #else
14413
14414
14415
14416
14417
14418
14419 actions &= ~(LOWER_BASE_INDEX | LOWER_SPLIT_CONST_OFFSETS);
14420 #endif
14421
14422
14423
14424
14425 actions |= LOWER_SCF |
14426 LOWER_ARRAY |
14427 LOWER_MP |
14428 LOWER_IO_STATEMENT |
14429 LOWER_MSTORE |
14430 #ifndef TARG_SL
14431 LOWER_CVT |
14432 #endif
14433 LOWER_COMPGOTO |
14434 LOWER_COMPLEX |
14435 #ifndef TARG_X8664
14436 LOWER_QUAD |
14437 #endif
14438 LOWER_MADD |
14439 LOWER_INTRINSIC |
14440 LOWER_ASSERT |
14441 LOWER_PICCALL |
14442 LOWER_ALL_MAPS |
14443 LOWER_SHORTCIRCUIT |
14444 LOWER_INL_STACK_INTRINSIC |
14445 LOWER_INLINE_INTRINSIC |
14446 #ifdef KEY
14447 LOWER_UPLEVEL |
14448 #endif
14449 LOWER_BIT_FIELD_ID;
14450
14451
14452
14453 save_Div_Split_Allowed = Div_Split_Allowed;
14454
14455 Div_Split_Allowed = FALSE;;
14456 }
14457 if (WN_opcode(pu) == OPC_FUNC_ENTRY)
14458 {
14459 lowering_actions |= actions;
14460 }
14461
14462 if (Action(LOWER_BITS_OP))
14463 actions |= LOWER_BIT_FIELD_ID;
14464
14465 current_actions = actions;
14466
14467 lower_maps_init(actions);
14468
14469 setCurrentState(pu, actions);
14470
14471 return actions;
14472 }
14473
14474
14475
14476
14477
14478
14479
14480
14481
14482
14483
14484 void Lower_Init(void)
14485 {
14486 static CURRENT_STATE current_state_NULL;
14487
14488
14489
14490 lowering_parity_map = WN_MAP32_Create(MEM_pu_pool_ptr);
14491 wn_derivation_map = WN_MAP_Create (MEM_pu_pool_ptr);
14492
14493 WN_MAP_Set_dont_copy(lowering_parity_map, TRUE);
14494 WN_MAP_Set_dont_copy(wn_derivation_map, TRUE);
14495
14496 lowering_actions = 0;
14497 current_state = current_state_NULL;
14498
14499
14500 nested_map_index++;
14501 FmtAssert(0 <= nested_map_index && nested_map_index < NESTED_MAP_ARRAY_SIZE,
14502 ("Lower_Init: Index into parity map array is out of range"));
14503 parity_map_array[nested_map_index] = lowering_parity_map;
14504 derivation_map_array[nested_map_index] = wn_derivation_map;
14505 }
14506
14507 void Lowering_Finalize(void)
14508 {
14509
14510 WN_MAP_Delete(lowering_parity_map);
14511
14512
14513 WN_MAP_Delete(wn_derivation_map);
14514
14515 nested_map_index--;
14516 if (nested_map_index >= 0) {
14517
14518 lowering_parity_map = parity_map_array[nested_map_index];
14519
14520 wn_derivation_map = derivation_map_array[nested_map_index];
14521 }
14522 else {
14523
14524 lowering_parity_map = WN_MAP_UNDEFINED;
14525
14526 wn_derivation_map = WN_MAP_UNDEFINED;
14527 }
14528 }
14529
14530
14531
14532
14533 static void lower_end(WN *tree, LOWER_ACTIONS actions)
14534 {
14535 lower_maps_reset(actions);
14536
14537 if (Action(LOWER_TO_CG))
14538 {
14539 Div_Split_Allowed = save_Div_Split_Allowed;
14540 }
14541
14542 popCurrentState(current_state);
14543 }
14544
14545 #ifdef TARG_X8664
14546
14547
14548
14549
14550
14551 static BOOL test_vcast_complex_types_stmt_expr(WN* tree)
14552 {
14553 OPCODE opcode = WN_opcode(tree);
14554 OPERATOR opr = WN_operator(tree);
14555
14556 if (OPCODE_is_compare(opcode) ||
14557 opr == OPR_PAIR ||
14558 opr == OPR_CONST ||
14559 (opr == OPR_INTRINSIC_OP &&
14560 (WN_intrinsic(tree) != INTRN_C8CONJG ||
14561 !Is_Target_64bit())) ||
14562 opr == OPR_CVT ||
14563 opr == OPR_DIV ||
14564 opr == OPR_SQRT ||
14565 opr == OPR_FIRSTPART ||
14566 opr == OPR_SECONDPART ||
14567 (!OPCODE_is_expression(opcode) &&
14568 !OPCODE_is_load(opcode) &&
14569 !OPCODE_is_store(opcode)))
14570 return FALSE;
14571
14572 if ((opr == OPR_LDID || opr == OPR_STID) && WN_st(tree) &&
14573 ST_class(WN_st(tree)) == CLASS_PREG &&
14574 (WN_rtype(tree) == MTYPE_C8 ||
14575 WN_desc(tree) == MTYPE_C8))
14576 return FALSE;
14577
14578 for (UINT kidno=0; kidno<WN_kid_count(tree); kidno++)
14579 if (!test_vcast_complex_types_stmt_expr(WN_kid(tree,kidno)))
14580 return FALSE;
14581
14582 return TRUE;
14583 }
14584
14585 static void vcast_complex_types_stmt_expr(WN* tree, WN* parent, INT kid)
14586 {
14587 OPCODE opcode = WN_opcode(tree);
14588 OPERATOR opr = WN_operator(tree);
14589
14590 for (UINT kidno=0; kidno<WN_kid_count(tree); kidno++)
14591 vcast_complex_types_stmt_expr(WN_kid(tree,kidno), tree, kidno);
14592
14593 if (OPCODE_rtype(opcode) == MTYPE_C8)
14594 WN_set_rtype(tree, MTYPE_V16C8);
14595 if (OPCODE_desc(opcode) == MTYPE_C8)
14596 WN_set_desc(tree, MTYPE_V16C8);
14597
14598 if (opr == OPR_MPY && WN_rtype(tree) == MTYPE_V16C8) {
14599 WN* kids[3];
14600 WN* wn;
14601 if (WN_operator(WN_kid0(tree)) == OPR_LDID) {
14602 kids[0] = WN_COPY_Tree(WN_kid0(tree));
14603 kids[1] = WN_CreateExp1(OPC_V16C8V16C8SHUFFLE,
14604 WN_COPY_Tree(WN_kid0(tree)));
14605 kids[2] = WN_kid1(tree);
14606 } else {
14607 kids[0] = WN_COPY_Tree(WN_kid1(tree));
14608 kids[1] = WN_CreateExp1(OPC_V16C8V16C8SHUFFLE,
14609 WN_COPY_Tree(WN_kid1(tree)));
14610 kids[2] = WN_kid0(tree);
14611 }
14612 WN_offset(kids[1]) = 0;
14613
14614 kids[0] = WN_CreateParm (MTYPE_V16C8, kids[0],
14615 Be_Type_Tbl(MTYPE_V16C8),
14616 WN_PARM_BY_VALUE);
14617 kids[1] = WN_CreateParm (MTYPE_V16C8, kids[1],
14618 Be_Type_Tbl(MTYPE_V16C8),
14619 WN_PARM_BY_VALUE);
14620 kids[2] = WN_CreateParm (MTYPE_V16C8, kids[2],
14621 Be_Type_Tbl(MTYPE_V16C8),
14622 WN_PARM_BY_VALUE);
14623 wn = WN_Create_Intrinsic(OPCODE_make_op(OPR_INTRINSIC_OP,
14624 MTYPE_V16C8, MTYPE_V),
14625 INTRN_V16C8MPY_ADDSUB, 3, kids);
14626 WN_kid(parent, kid) = wn;
14627 }
14628
14629 else if (opr == OPR_INTRINSIC_OP) {
14630 FmtAssert(WN_intrinsic(tree) == INTRN_C8CONJG, ("NYI"));
14631 WN_intrinsic(tree) = INTRN_V16C8CONJG;
14632 }
14633
14634 return;
14635 }
14636
14637 static void vcast_complex_types(WN* tree)
14638 {
14639 OPCODE opcode = WN_opcode(tree);
14640 OPERATOR opr = WN_operator(tree);
14641
14642 if (opcode == OPC_BLOCK) {
14643 for (WN* stmt=WN_first(tree); stmt;) {
14644 WN* next_stmt=WN_next(stmt);
14645 if (!OPCODE_is_call(WN_opcode(stmt))) {
14646 if (!OPCODE_is_scf(WN_opcode(stmt))) {
14647 if (test_vcast_complex_types_stmt_expr(stmt))
14648 vcast_complex_types_stmt_expr(stmt, tree, 0);
14649 } else
14650 vcast_complex_types(stmt);
14651 }
14652 stmt=next_stmt;
14653 }
14654 return;
14655 }
14656 for (UINT kidno=0; kidno<WN_kid_count(tree); kidno++)
14657 vcast_complex_types(WN_kid(tree,kidno));
14658 return;
14659 }
14660 #endif
14661
14662
14663
14664
14665
14666
14667
14668
14669
14670 WN *WN_Lower(WN *tree, LOWER_ACTIONS actions, struct ALIAS_MANAGER *alias,
14671 const char *msg)
14672 {
14673 #ifdef BACK_END
14674 Start_Timer(T_Lower_CU);
14675 #endif
14676 alias_manager = alias;
14677 loop_nest_depth = 0;
14678
14679 #ifdef TARG_X8664
14680 current_loop_nest_depth = 0;
14681 bzero( loop_info_stack, sizeof(loop_info_stack) );
14682 #endif
14683
14684
14685
14686 if (WN_operator(tree) == OPR_FUNC_ENTRY &&
14687 ST_asm_function_st(*WN_st(tree))) {
14688 return tree;
14689 }
14690
14691 actions = lower_actions(tree, actions);
14692
14693 #ifdef TARG_X8664
14694 if (Is_Target_SSE3() && Vcast_Complex &&
14695 Action(LOWER_COMPLEX) &&
14696 WN_operator(tree) == OPR_FUNC_ENTRY)
14697 vcast_complex_types(tree);
14698 #endif
14699
14700 if (Action(LOWER_MP)) {
14701
14702
14703
14704
14705 LowerMP_PU_Init ();
14706 }
14707
14708 WN_Lower_Checkdump(msg, tree, actions);
14709
14710 if (WN_opcode(tree) == OPC_FUNC_ENTRY)
14711 {
14712 tree = lower_entry(tree, actions);
14713 }
14714 else if (OPCODE_is_scf(WN_opcode(tree)))
14715 {
14716 tree = lower_scf(NULL, tree, actions);
14717 }
14718 else if (OPCODE_is_stmt(WN_opcode(tree)))
14719 {
14720 tree = lower_stmt(NULL, tree, actions);
14721 }
14722 else if (OPCODE_is_expression(WN_opcode(tree)))
14723 {
14724 tree = lower_expr(NULL, tree, actions);
14725 }
14726
14727 lower_end(tree, actions);
14728
14729 WN_Lower_Checkdump("After lowering", tree, 0);
14730
14731 #ifdef BACK_END
14732 Stop_Timer(T_Lower_CU);
14733 #endif
14734
14735 #ifdef TARG_X8664
14736 FmtAssert( current_loop_nest_depth == 0, ("loop nest depth is not 0") );
14737 #endif
14738
14739 WN_verifier(tree);
14740
14741 return tree;
14742 }
14743
14744
14745
14746 static WN *Transform_To_Memset(WN *dst, INT32 offset, TY_IDX dstTY, WN *src, WN *size)
14747 {
14748 WN *call, *parms[3];
14749
14750 if (offset && WN_offset(dst) != offset)
14751 dst = WN_Add(Pointer_type, dst, WN_Intconst(Pointer_type, offset));
14752
14753 parms[0]= WN_CreateParm(Pointer_type,
14754 dst,
14755 dstTY ? dstTY : MTYPE_To_TY(WN_rtype(dst)),
14756 WN_PARM_BY_VALUE);
14757
14758
14759
14760
14761
14762 parms[1]= WN_CreateParm(MTYPE_I4,
14763 src,
14764 MTYPE_To_TY(MTYPE_I4),
14765 WN_PARM_BY_VALUE);
14766
14767 parms[2]= WN_CreateParm(WN_rtype(size),
14768 WN_COPY_Tree(size),
14769 MTYPE_To_TY(WN_rtype(size)),
14770 WN_PARM_BY_VALUE);
14771
14772 call= WN_Generate_Intrinsic_Call(NULL, INTRN_MEMSET, 3, parms);
14773
14774 return call;
14775 }
14776
14777
14778 extern WN * Transform_To_Memcpy(WN *dst, WN *src, INT32 offset, TY_IDX dstTY, TY_IDX srcTY, WN *size)
14779 {
14780 WN *call, *parms[3];
14781
14782 if (offset)
14783 {
14784 if (WN_offset(src) != offset)
14785 src = WN_Add(Pointer_type, src, WN_Intconst(Pointer_type, offset));
14786 if (WN_offset(dst) != offset)
14787 dst = WN_Add(Pointer_type, dst, WN_Intconst(Pointer_type, offset));
14788 }
14789
14790 parms[0]= WN_CreateParm(Pointer_type,
14791 dst,
14792 dstTY ? dstTY : MTYPE_To_TY(WN_rtype(dst)),
14793 WN_PARM_BY_VALUE);
14794
14795 parms[1]= WN_CreateParm(Pointer_type,
14796 src,
14797 srcTY ? srcTY : MTYPE_To_TY(WN_rtype(src)),
14798 WN_PARM_BY_VALUE);
14799
14800
14801 parms[2]= WN_CreateParm(WN_rtype(size),
14802 WN_COPY_Tree(size),
14803 MTYPE_To_TY(WN_rtype(size)),
14804 WN_PARM_BY_VALUE);
14805
14806
14807 call= WN_Generate_Intrinsic_Call(NULL, INTRN_MEMCPY, 3, parms);
14808 return call;
14809
14810 }
14811
14812 static inode_type *Insert_Inode(struct inode *list, struct inode *node)
14813 {
14814 struct inode *current = list;
14815 struct inode *prev = NULL;
14816 INT offset = node->start_offset;
14817
14818 if (list==NULL) {
14819 return node;
14820 }
14821 while (current) {
14822 if (offset <= current->start_offset)
14823 break;
14824 prev = current;
14825 current = current->next;
14826 }
14827
14828
14829 node->next = current;
14830
14831 if (prev == NULL) {
14832 return node;
14833 }
14834 else {
14835 prev->next = node;
14836 return list;
14837 }
14838 }
14839
14840
14841
14842
14843 static WN *Get_LDID(WN *block,WN *wn, BOOL &is_iload)
14844 {
14845 is_iload = FALSE;
14846
14847 WN *return_wn = NULL;
14848 if (WN_operator(wn) == OPR_LDID) {
14849 if (WN_class(wn) == CLASS_PREG) {
14850 return NULL;
14851 }
14852 else
14853 return wn;
14854 }
14855 else if (WN_operator(wn) == OPR_ILOAD && WN_operator(WN_kid0(wn)) == OPR_LDID) {
14856 is_iload = TRUE;
14857 return WN_kid0(wn);
14858 }
14859 else return NULL;
14860 }
14861
14862 static BOOL Check_If_Merged(WN *tree, WN **deleted_wn, INT bound_num)
14863 {
14864 INT pp = 0;
14865 if (bound_num == 0) return FALSE;
14866 while (pp < bound_num) {
14867 if (deleted_wn[pp] == tree)
14868 return TRUE;
14869 pp++;
14870 }
14871 return FALSE;
14872 }
14873
14874
14875
14876
14877
14878
14879
14880
14881
14882
14883
14884 static WN *Lower_Mistore_Memlib(WN *block, WN *tree, LOWER_ACTIONS actions)
14885 {
14886 TY_IDX pty_idx = WN_ty(tree);
14887 TY_IDX dstTY, srcTY;
14888 TY_IDX ty_idx = TY_pointed(pty_idx);
14889 WN *store_base, *load_base ;
14890 WN *load_pp, *store_pp;
14891 struct inode *one_node, *istore_list = NULL;
14892 struct inode *prev_head, *head_node, *last_node;
14893 WN *stmt = tree;
14894 INT size, end_offset, total_size, total_num = 0;
14895 INT i;
14896 INT64 const_val;
14897 WN *return_block = WN_CreateBlock();
14898 BOOL is_const = FALSE;
14899 BOOL st_iload, ld_iload, pp_iload;
14900
14901 static INT delete_num = 0;
14902 static INT bound_num = 0;
14903 static WN *deleted_wn[DELETED_MAX];
14904 static WN *delete_base = NULL;
14905
14906
14907 if (!OPT_Lower_To_Memlib) return tree;
14908
14909 Is_True(WN_operator(tree) == OPR_ISTORE,
14910 ("expected mistore node, not %s", OPCODE_name(WN_opcode(tree))));
14911
14912 Is_True(TY_kind(pty_idx) == KIND_POINTER,
14913 ("type specified in MISTORE not pointer"));
14914
14915 if (delete_num && Check_If_Merged(tree, deleted_wn, bound_num)) {
14916 delete_num--;
14917 return NULL;
14918 }
14919
14920
14921 if (WN_operator_is(WN_kid0(tree), OPR_INTCONST)) {
14922 return tree;
14923 }
14924 else load_base = Get_LDID(block, WN_kid0(tree), ld_iload);
14925
14926 store_base = Get_LDID(block, WN_kid1(tree), st_iload);
14927
14928
14929 if (store_base == NULL || (!is_const && load_base==NULL))
14930 return tree;
14931
14932 if (delete_num) {
14933 store_pp = Get_LDID(block, delete_base, pp_iload);
14934 Is_True(store_pp, ("Expecting non-null saved deleted base "));
14935 if (WN_st(store_pp) != WN_st(store_base))
14936 DevWarn("Inconsistent base in Mistore_Memlib");
14937 return tree;
14938 }
14939
14940 if (OPT_Enable_Lower_To_Memlib_Limit != -1 &&
14941 cur_memlib_idx >= OPT_Enable_Lower_To_Memlib_Limit)
14942 return tree;
14943 cur_memlib_idx ++;
14944
14945
14946 Is_True(delete_num == 0, ("Some unclear deleted WN"));
14947 delete_num = 0;
14948 bound_num = 0;
14949 delete_base = NULL;
14950
14951
14952 #ifdef TARG_IA64
14953 while (stmt && WN_operator(stmt)!= OPR_CALL) {
14954 #else
14955 while (stmt && ! OPERATOR_is_endsbb(WN_operator(stmt)) &&
14956 WN_operator(stmt) != OPR_LABEL) {
14957 #endif
14958
14959 if (WN_operator(stmt) != OPR_ISTORE) {
14960 stmt = WN_next(stmt);
14961 continue;
14962 }
14963
14964 pty_idx = WN_ty(stmt);
14965 ty_idx = TY_pointed(pty_idx);
14966 if (WN_field_id (stmt) != 0)
14967 ty_idx = get_field_type (ty_idx, WN_field_id (stmt));
14968 size = TY_size(Ty_Table[ty_idx]);
14969
14970 if (size == 0)
14971 DevWarn ("Type in MISTORE cannot be zero size");
14972
14973 total_num++;
14974
14975
14976 if (is_const) {
14977 if (!WN_operator_is(WN_kid0(stmt), OPR_INTCONST)
14978 || const_val != WN_const_val(WN_kid0(stmt))) {
14979 stmt = WN_next(stmt);
14980
14981 return tree;
14982 }
14983
14984 }
14985 else {
14986 load_pp = Get_LDID(block, WN_kid0(stmt), pp_iload);
14987 if (pp_iload != ld_iload) return tree;
14988 }
14989
14990 store_pp = Get_LDID(block, WN_kid1(stmt), pp_iload);
14991
14992 if (store_pp == NULL || pp_iload != st_iload || (!is_const && load_pp == NULL)) {
14993 stmt = WN_next(stmt);
14994 continue;
14995 }
14996
14997 if (WN_st(store_pp) != WN_st(store_base) ||
14998 (!is_const && WN_st(load_pp) != WN_st(load_base))) {
14999 stmt = WN_next(stmt);
15000 continue;
15001 }
15002
15003 if (!is_const && WN_store_offset(stmt) != WN_offset(load_pp)) {
15004 stmt = WN_next(stmt);
15005 continue;
15006 }
15007
15008
15009
15010 one_node = (struct inode *) alloca(sizeof(struct inode));
15011 one_node->wn = stmt;
15012 one_node->start_offset= WN_store_offset(stmt);
15013 one_node->length = size;
15014 one_node->next = NULL;
15015 istore_list = Insert_Inode(istore_list, one_node);
15016 stmt = WN_next(stmt);
15017 }
15018
15019
15020 total_num = 0;
15021 total_size = 0;
15022 end_offset = WN_store_offset(tree);
15023 head_node = istore_list;
15024 one_node = istore_list;
15025
15026
15027 while (one_node) {
15028
15029
15030 if (one_node->start_offset != end_offset)
15031 break;
15032 else last_node = one_node;
15033
15034 total_size += one_node->length;
15035 end_offset = one_node->start_offset + one_node->length;
15036
15037 total_num++;
15038 #ifdef KEY
15039 if (total_num >= DELETED_MAX) break;
15040 #else
15041 if (total_num > DELETED_MAX) break;
15042 #endif
15043 one_node = one_node->next;
15044 }
15045
15046 prev_head = head_node;
15047 head_node = one_node;
15048
15049
15050
15051
15052 WN * wn_intrinsic = NULL;
15053
15054 if (total_size >= MEMLIB_STRUCT_BYTES && total_num >= MEMLIB_NUM_STORE) {
15055
15056 if (traceMemlib) DevWarn("Original of Struct MEMLIB call \n");
15057
15058 store_base = WN_kid1(tree);
15059
15060
15061 if (!TY_is_pointer(WN_ty(store_base))) {
15062 store_base = WN_CreateLda(OPR_LDA, Pointer_Mtype, MTYPE_V, WN_store_offset(tree),
15063 Make_Pointer_Type(WN_ty(tree)), WN_st_idx(tree));
15064 DevWarn("After make pointer ...\n");
15065 }
15066
15067 dstTY = TY_pointed(Ty_Table[WN_ty(store_base)]);
15068
15069 if (is_const) {
15070 wn_intrinsic = Transform_To_Memset(WN_COPY_Tree(store_base), WN_store_offset(tree),
15071 TY_pointer(dstTY), WN_kid0(tree), WN_CreateIntconst(OPC_I4INTCONST, total_size));
15072 }
15073 else {
15074
15075 load_base = WN_kid0(tree);
15076
15077 if (!TY_is_pointer(Ty_Table[WN_ty(load_base)])) {
15078 load_base = WN_CreateLda(OPR_LDA, Pointer_Mtype, MTYPE_V, WN_offset(tree),
15079 Make_Pointer_Type(WN_ty(load_base)), WN_st_idx(load_base));
15080 }
15081 srcTY = TY_pointed(Ty_Table[WN_ty(load_base)]);
15082
15083 wn_intrinsic = Transform_To_Memcpy(WN_COPY_Tree(store_base), WN_COPY_Tree(load_base), WN_store_offset(tree), TY_pointer(dstTY), TY_pointer(srcTY), WN_CreateIntconst(OPC_I4INTCONST, total_size) );
15084
15085 }
15086
15087
15088
15089
15090 i = 0;
15091 prev_head = istore_list;
15092
15093 while (prev_head != NULL && i < total_num) {
15094 i++;
15095 deleted_wn[delete_num++] = prev_head->wn;
15096 if (delete_num == DELETED_MAX) DevWarn("Overflow in deleted_wn\n");
15097 prev_head = prev_head->next;
15098 }
15099 bound_num = delete_num;
15100 delete_num--;
15101 delete_base = store_base;
15102
15103
15104
15105 if (traceMemlib) DevWarn("TRANSFORMED MEMCPY (%s: %d) of: Struct (%d bytes of %d istore)\n", Src_File_Name, Srcpos_To_Line(current_srcpos), total_size, total_num);
15106
15107
15108 #ifdef KEY // bug 11360
15109 if (Action(LOWER_CALL))
15110 wn_intrinsic = lower_call(return_block, wn_intrinsic, actions);
15111 #endif
15112 WN_INSERT_BlockLast(return_block, wn_intrinsic);
15113 return return_block;
15114 }
15115 else return tree;
15116
15117 }
15118
15119 #ifdef KEY
15120
15121
15122 static BOOL Repetitive_byte_vals(INT64 const_val, INT nbytes)
15123 {
15124 unsigned char bval = const_val;
15125 if (nbytes-- == 0)
15126 return FALSE;
15127 while (nbytes--) {
15128 const_val >>= 8;
15129 if (bval != (const_val & 0xff))
15130 return FALSE;
15131 }
15132 return TRUE;
15133 }
15134 #endif
15135
15136 static WN *Lower_STID_Memlib(WN *block, WN *tree, LOWER_ACTIONS actions)
15137 {
15138 struct inode *one_node, *stid_list = NULL;
15139 struct inode *prev_head, *head_node, *last_node;
15140 INT size, end_offset, total_size, total_num = 0;
15141 INT i;
15142 INT64 const_val;
15143 BOOL is_const = FALSE;
15144 WN *return_block = WN_CreateBlock();
15145 WN *stmt = tree;
15146 WN *store_base;
15147 WN *load_pp, *store_pp;
15148 TY_IDX dstTY;
15149 static WN *deleted_wn[DELETED_MAX];
15150 static INT delete_num = 0;
15151 static INT delete_bound = 0;
15152 static WN * delete_stid = NULL;
15153
15154
15155 if (!OPT_Lower_To_Memlib) return tree;
15156
15157 Is_True(WN_operator(tree) == OPR_STID,
15158 ("expected STID node, not %s", OPCODE_name(WN_opcode(tree))));
15159
15160 if (Check_If_Merged(tree, deleted_wn, delete_bound)){
15161 delete_num--;
15162 return NULL;
15163 }
15164
15165 if (delete_num) {
15166 Is_True(delete_stid, ("Expecting non-null saved deleted STID"));
15167 if (WN_st(stmt) != WN_st(delete_stid))
15168 DevWarn("Inconsistent base in STID_Memlib");
15169 return tree;
15170 }
15171
15172
15173 delete_num = 0;
15174 delete_bound = 0;
15175 delete_stid = NULL;
15176
15177 #ifdef KEY
15178
15179
15180 if (WN_st(tree) == SP_Sym &&
15181 WN_store_offset(tree) >= 0)
15182 return tree;
15183 #endif
15184
15185 if (WN_operator_is(WN_kid0(tree), OPR_INTCONST)) {
15186 const_val = WN_const_val(WN_kid0(tree));
15187 }
15188 else return tree;
15189
15190 if (OPT_Enable_Lower_To_Memlib_Limit != -1 &&
15191 cur_memlib_idx >= OPT_Enable_Lower_To_Memlib_Limit)
15192 return tree;
15193 cur_memlib_idx ++;
15194
15195
15196 #ifdef TARG_IA64
15197 while (stmt && WN_operator(stmt)!= OPR_CALL) {
15198 #else
15199 while (stmt && ! OPERATOR_is_endsbb(WN_operator(stmt)) &&
15200 WN_operator(stmt) != OPR_LABEL) {
15201 #endif
15202
15203
15204 if (WN_operator(stmt) != OPR_STID) {
15205 stmt = WN_next(stmt);
15206 continue;
15207 }
15208
15209
15210
15211
15212
15213 size = MTYPE_byte_size(OPCODE_desc(WN_opcode(stmt)));
15214
15215 total_num++;
15216
15217 if (
15218 #ifdef KEY
15219 !Repetitive_byte_vals(const_val, size) ||
15220 #endif
15221 !WN_operator_is(WN_kid0(stmt), OPR_INTCONST)
15222 || const_val != WN_const_val(WN_kid0(stmt))) {
15223 stmt = WN_next(stmt);
15224 continue;
15225
15226 }
15227
15228
15229 if (WN_st(stmt) != WN_st(tree)) {
15230 stmt = WN_next(stmt);
15231 continue;
15232
15233 }
15234
15235 one_node = (struct inode *) alloca(sizeof(struct inode));
15236 one_node->wn = stmt;
15237 one_node->start_offset= WN_store_offset(stmt);
15238 one_node->length = size;
15239 one_node->next = NULL;
15240 stid_list = Insert_Inode(stid_list, one_node);
15241 stmt = WN_next(stmt);
15242 }
15243
15244
15245 total_num = 0;
15246 total_size = 0;
15247 end_offset = WN_store_offset(tree);
15248 head_node = stid_list;
15249 one_node = stid_list;
15250
15251 while (one_node) {
15252
15253 if (one_node->start_offset != end_offset)
15254 break;
15255 else last_node = one_node;
15256
15257 total_size += one_node->length;
15258 end_offset = one_node->start_offset + one_node->length;
15259 total_num++;
15260 #ifdef KEY
15261 if (total_num >= DELETED_MAX) break;
15262 #else
15263 if (total_num >DELETED_MAX) break;
15264 #endif
15265 one_node = one_node->next;
15266 }
15267
15268 prev_head = head_node;
15269 head_node = one_node;
15270
15271 WN * wn_intrinsic = NULL;
15272
15273
15274 if (total_size >= MEMLIB_STRUCT_BYTES && total_num >= MEMLIB_NUM_STORE) {
15275
15276 DevWarn("Original before Struct MEMLIB_set \n");
15277
15278 store_base = WN_CreateLda(OPR_LDA, Pointer_Mtype, MTYPE_V,
15279 WN_store_offset(tree),
15280 Make_Pointer_Type(WN_ty(tree)), WN_st_idx(tree));
15281
15282 wn_intrinsic = Transform_To_Memset(WN_COPY_Tree(store_base),
15283 WN_offset(tree),
15284 TY_pointer(dstTY),
15285 WN_CreateIntconst(OPC_I4INTCONST, const_val & 0xff),
15286 WN_CreateIntconst(OPC_I4INTCONST, total_size) );
15287
15288
15289 DevWarn("TRANSFORMED MEMSET (%s: %d): STID (%d bytes of %d stids \n", Src_File_Name, Srcpos_To_Line(current_srcpos), total_size, total_num);
15290
15291
15292
15293
15294 i = 0;
15295 prev_head = stid_list;
15296
15297 while (prev_head != NULL && i < total_num) {
15298 i++;
15299 deleted_wn[delete_num++] = prev_head->wn;
15300 if (delete_num == DELETED_MAX) DevWarn("Overflow \n");
15301 prev_head = prev_head->next;
15302 }
15303
15304 delete_bound = delete_num;
15305 delete_num--;
15306 delete_stid = tree;
15307
15308 #ifdef KEY // bug 11360
15309 if (Action(LOWER_CALL))
15310 wn_intrinsic = lower_call(return_block, wn_intrinsic, actions);
15311 #endif
15312 WN_INSERT_BlockLast(return_block, wn_intrinsic);
15313 return return_block;
15314 }
15315 else return tree;
15316
15317 }
15318
15319
15320 static int Find_Nums_Induction(WN *exp, WN *ind)
15321 {
15322 int total = 0;
15323
15324 if (OPCODE_is_leaf(WN_opcode(exp))) {
15325
15326 if (WN_operator(exp)==OPR_LDID && WN_same_id(exp,ind))
15327 return 1;
15328 else return 0;
15329 }
15330 else {
15331 for (int i=0; i< WN_kid_count(exp); i++)
15332 total = total + Find_Nums_Induction(WN_kid(exp,i), ind);
15333
15334 return total;
15335 }
15336 }
15337 static WN * Locate_Ind_Path(WN *exp, WN *ind, int &numMpy)
15338 {
15339 int save_num;
15340 WN *wn = NULL;
15341 WN *tmp;
15342 if (exp == NULL) return NULL;
15343 if (WN_operator(exp) == OPR_LDID && WN_same_id(exp,ind)) {
15344
15345 return exp;
15346 }
15347
15348 if (WN_operator(exp) == OPR_MPY || WN_operator(exp) == OPR_DIV) numMpy++;
15349 else if (WN_operator(exp) != OPR_ADD &&
15350 WN_operator(exp) != OPR_CVT &&
15351 WN_operator(exp) != OPR_INTCONST)
15352 return NULL;
15353
15354
15355 save_num = numMpy;
15356 for (int i=0; i< WN_kid_count(exp); i++) {
15357 numMpy = save_num;
15358 tmp = Locate_Ind_Path(WN_kid(exp,i), ind, numMpy);
15359 if (tmp)
15360 wn = tmp;
15361 }
15362
15363 return wn;
15364 }
15365
15366
15367 static BOOL Valid_Induction_In_Addr(WN *exp, WN *ind, int msize)
15368 {
15369 WN *wn_mult = NULL;
15370 int numMpy;
15371
15372
15373 if (WN_operator(exp)==OPR_ILOAD)
15374 return FALSE;
15375
15376 if (WN_operator(exp)==OPR_MPY || WN_operator(exp) == OPR_DIV ) {
15377 numMpy = 1;
15378
15379 if (Locate_Ind_Path(WN_kid0(exp), ind, numMpy)) {
15380 if (numMpy > 1)
15381 return FALSE;
15382 else wn_mult = WN_kid1(exp);
15383 }
15384 else {
15385 numMpy = 1;
15386 if (Locate_Ind_Path(WN_kid1(exp), ind, numMpy)) {
15387 if (numMpy > 1)
15388 return FALSE;
15389 else
15390 wn_mult = WN_kid0(exp);
15391 }
15392 else
15393 #ifdef TARG_IA64
15394 return TRUE;
15395 #else
15396 return FALSE;
15397 #endif
15398 }
15399
15400
15401 while (WN_operator(wn_mult) == OPR_CVT) wn_mult = WN_kid0(wn_mult);
15402 if (WN_operator_is(wn_mult, OPR_INTCONST) && WN_const_val(wn_mult)== msize)
15403 return TRUE;
15404 else
15405 return FALSE;
15406
15407
15408 }
15409 else if (WN_operator(exp) != OPR_ADD && WN_operator(exp) != OPR_CVT &&
15410 ! OPERATOR_is_leaf(WN_operator(exp)))
15411 return FALSE;
15412
15413
15414
15415
15416 for (int i=0; i< WN_kid_count(exp); i++)
15417 if (!Valid_Induction_In_Addr(WN_kid(exp,i), ind, msize))
15418 return FALSE;
15419
15420 return TRUE;
15421
15422 }
15423
15424 static BOOL Valid_Induction_For_Array(WN *exp, WN *ind)
15425 {
15426 WN *wn = NULL;
15427 int i;
15428 int number;
15429
15430
15431 if (WN_operator_is(exp, OPR_ILOAD) || WN_operator_is(exp, OPR_LDA))
15432 return FALSE;
15433
15434 if (WN_operator(exp)==OPR_MPY || WN_operator(exp) == OPR_DIV) {
15435
15436 for (i=0; i< WN_kid_count(exp); i++)
15437 number = 1;
15438 if (Locate_Ind_Path(WN_kid(exp,i), ind, number) && number > 1)
15439 return FALSE;
15440 return TRUE;
15441 }
15442 else {
15443 for (int i=0; i< WN_kid_count(exp); i++)
15444 if (!Valid_Induction_For_Array(WN_kid(exp,i), ind))
15445 return FALSE;
15446
15447 return TRUE;
15448 }
15449 }
15450
15451 static BOOL Any_Indirect_Load(WN *exp)
15452 {
15453 INT i, total = 0;
15454
15455 if (WN_operator_is(exp, OPR_ILOAD))
15456 return TRUE;
15457
15458 if (OPCODE_is_leaf(WN_opcode(exp)))
15459 return FALSE;
15460
15461 for (i=0; i< WN_kid_count(exp); i++)
15462 if (Any_Indirect_Load(WN_kid(exp,i))) return TRUE;
15463
15464 return FALSE;
15465 }
15466
15467 static BOOL Valid_Array_Addr(WN *wn, WN *ind, int bytenum)
15468 {
15469 Is_True(WN_operator(wn)==OPR_ARRAY, ("Expecting an ARRAY"));
15470
15471 if (WN_num_dim(wn) != 1)
15472 return FALSE;
15473 else if (WN_element_size(wn) != bytenum)
15474 return FALSE;
15475 else if (Find_Nums_Induction(WN_kid2(wn), ind) != 1)
15476 return FALSE;
15477 else if (Any_Indirect_Load(WN_kid0(wn)))
15478 return FALSE;
15479 else
15480 return Valid_Induction_For_Array(WN_kid2(wn), ind) &&
15481 Any_Indirect_Load(WN_kid0(wn));
15482 }
15483
15484
15485
15486 static BOOL Is_Invaried_Value(WN *expr, WN *ind)
15487 {
15488 if (WN_operator_is(expr, OPR_INTCONST)) return TRUE;
15489
15490
15491 if (WN_operator_is(expr, OPR_ILOAD) || WN_operator_is(expr, OPR_LDA))
15492 return FALSE;
15493
15494 if (WN_operator_is(expr, OPR_LDID)){
15495 if (WN_same_id(expr, ind))
15496 return FALSE;
15497 else
15498 return TRUE;
15499 }
15500
15501 else {
15502 for (int i=0; i< WN_kid_count(expr); i++)
15503 if (!Is_Invaried_Value(WN_kid(expr,i), ind))
15504 return FALSE;
15505
15506 return TRUE;
15507 }
15508
15509 }
15510
15511
15512
15513
15514
15515
15516 static MEMLIB_ACTIONS Memlib_Filter(WN *stmt)
15517 {
15518 switch(WN_operator(stmt)) {
15519 case OPR_ISTORE:
15520 case OPR_DO_LOOP: return CONT_OPT;
15521
15522 case OPR_PREFETCH:
15523 case OPR_PREFETCHX: return IGNORE;
15524
15525 default: return ABORT_OPT;
15526 }
15527 }
15528
15529 static BOOL Is_Preceding_Subtract(WN *addr_exp, WN *ind)
15530 {
15531 WN *wn = NULL;
15532 INT i, num = 0;
15533
15534 if (WN_operator(addr_exp) == OPR_ARRAY)
15535 return Is_Preceding_Subtract(WN_kid2(addr_exp), ind);
15536
15537
15538 if (WN_operator(addr_exp)==OPR_SUB) {
15539
15540 if (Locate_Ind_Path(WN_kid1(addr_exp), ind, num))
15541 return TRUE;
15542 else return FALSE;
15543 }
15544 else {
15545 for (i=0; i< WN_kid_count(addr_exp); i++)
15546 if (Is_Preceding_Subtract(WN_kid(addr_exp,i), ind)) return TRUE;
15547
15548 return FALSE;
15549 }
15550
15551 }
15552
15553 static WN *Start_Addr_To_Transform(WN *block, WN* addr_wn, TY_IDX &desc_idx)
15554 {
15555 WN * target_addr = NULL;
15556
15557 if (WN_operator(addr_wn) == OPR_ARRAY) {
15558
15559 desc_idx = Make_Pointer_Type(desc_idx);
15560 target_addr = lower_expr(block,addr_wn, LOWER_ARRAY);
15561 return target_addr;
15562 }
15563 else {
15564 desc_idx = WN_ty(addr_wn);
15565 return addr_wn;
15566 }
15567 }
15568
15569 static BOOL Valid_Addr_Expr(WN *addr, WN *ind, int bsize)
15570 {
15571 Is_True (WN_operator(addr) != OPR_ARRAY, ("Should not have any ARRAY"));
15572
15573
15574
15575
15576 if (Find_Nums_Induction(addr, ind) != 1)
15577 return FALSE;
15578 else if (Any_Indirect_Load(addr))
15579 return FALSE;
15580 else return Valid_Induction_In_Addr(addr, ind, bsize);
15581
15582 }
15583 static WN *Find_Pointer(WN *wn, BOOL is_array)
15584 {
15585 INT i;
15586 WN *return_wn = NULL;
15587
15588 if (OPCODE_is_leaf(WN_opcode(wn))) {
15589
15590
15591 if (WN_operator_is(wn, OPR_LDID) && (is_array||TY_is_pointer(WN_ty(wn)))
15592 || WN_operator_is(wn, OPR_LDA)) {
15593 return wn;
15594 }
15595 else return NULL;
15596
15597 }
15598
15599 for (i=0; i< WN_kid_count(wn); i++) {
15600 return_wn = Find_Pointer(WN_kid(wn,i), is_array);
15601 if (return_wn) return return_wn;
15602 }
15603 return NULL;
15604 }
15605
15606 static BOOL Memlib_Two_Aliased(WN *wn1, WN *wn2, INT bsize)
15607 {
15608 WN *base1;
15609 WN *base2;
15610
15611 if (WN_operator_is(wn1, OPR_ARRAY) && WN_operator_is(wn2, OPR_ARRAY)) {
15612 base1 = Find_Pointer(WN_kid0(wn1), 1);
15613 base2 = Find_Pointer(WN_kid0(wn2), 1);
15614
15615 }
15616 else {
15617 base1 = Find_Pointer(wn1, 0);
15618 base2 = Find_Pointer(wn2, 0);
15619 }
15620
15621 if (!base1 || !base2)
15622 return TRUE;
15623
15624 if (base1 && base2)
15625 return lower_is_aliased(base1, base2, bsize);
15626 else return TRUE;
15627 }
15628
15629
15630 static INT Find_Ind_Var(WN *index_wn, WN *inds[], INT upper)
15631 {
15632 INT i, num, idx = -1;
15633 BOOL found = FALSE;
15634
15635 for (i = 0; i < upper; i++) {
15636 if ((num = Find_Nums_Induction(index_wn, inds[i])) > 1)
15637 return -1;
15638 else if (num == 1) {
15639 if (found) return -1;
15640 idx = i;
15641 found =TRUE;
15642 }
15643 }
15644 return idx;
15645 }
15646
15647
15648
15649
15650 static WN *Memset_MD_Array(WN *block, WN *tree, LOWER_ACTIONS actions)
15651 {
15652 INT num_stmt, mbyte_stmt, loop_level = 0;
15653 INT total_size = 1;
15654 INT trips[MEMLIB_MAX_NUM];
15655 OPCODE ub_compare;
15656 TY_IDX desc_idx;
15657 WN *ind_vars[MEMLIB_MAX_NUM];
15658 WN *stmt, *body = WN_do_body(tree);
15659 WN *load_value_wn, *store_addr_wn, *target_addr;
15660 WN *loop_indvar, *trip_count;
15661 WN *lower_bound, *upper_bound;
15662 WN *enclosing_for, *current_wn = tree;
15663 WN *loop_info;
15664 WN *return_block = WN_CreateBlock();
15665
15666 Is_True(WN_opcode(tree) == OPC_DO_LOOP,
15667 ("expected DO_LOOP node, not %s", OPCODE_name(WN_opcode(tree))));
15668
15669 while (WN_opcode(current_wn) == OPC_DO_LOOP) {
15670 loop_info = WN_do_loop_info(current_wn);
15671 if (loop_info == NULL) {
15672 if (traceMemlib) DevWarn("NULL loop info in Lower_Memlib: MD_array");
15673 return tree;
15674 }
15675 loop_indvar = WN_loop_induction(loop_info);
15676 if ( !loop_indvar )
15677 return tree;
15678 lower_bound = WN_LOOP_LowerBound(current_wn);
15679 if ( !lower_bound )
15680 return tree;
15681 upper_bound = WN_LOOP_UpperBound(current_wn, &ub_compare);
15682 if ( !upper_bound )
15683 return tree;
15684 trip_count = WN_LOOP_TripCount(current_wn);
15685 if ( !trip_count )
15686 return tree;
15687
15688 if (!WN_operator_is(trip_count, OPR_INTCONST))
15689 return tree;
15690 else trips[loop_level] = WN_const_val(trip_count);
15691 ind_vars[loop_level] = loop_indvar;
15692 loop_level++;
15693
15694
15695 if (WN_const_val(lower_bound) !=0) {
15696 DevWarn("Memlib: mult-dim: lower bound is not 0");
15697 return tree;
15698 }
15699
15700 num_stmt = 0;
15701 body = WN_do_body(current_wn);
15702
15703
15704 for (stmt=WN_first(body); stmt; stmt=WN_next(stmt)) {
15705 if (Memlib_Filter(stmt)==ABORT_OPT) return tree;
15706 else if (Memlib_Filter(stmt)== IGNORE ) continue;
15707
15708 Is_True(WN_opcode(tree) == OPC_DO_LOOP || WN_operator(tree) == OPR_ISTORE,
15709 ("expected DO_LOOP node, not %s", OPCODE_name(WN_opcode(tree))));
15710
15711 if (++num_stmt > 1)
15712 return tree;
15713
15714 enclosing_for = current_wn;
15715 current_wn = stmt;
15716 }
15717 }
15718
15719
15720 if (WN_operator(current_wn) != OPR_ISTORE) {
15721 DevWarn("Memlib: mult-dim: is not an ISTORE");
15722 return tree;
15723 }
15724
15725 mbyte_stmt = MTYPE_byte_size(OPCODE_desc(WN_opcode(current_wn)));
15726 load_value_wn = WN_kid0(current_wn);
15727 target_addr = WN_kid1(current_wn);
15728 store_addr_wn = WN_kid1(current_wn);
15729
15730
15731 if (!(WN_operator_is(load_value_wn, OPR_INTCONST) &&
15732 (WN_const_val(load_value_wn)==0 || WN_const_val(load_value_wn)==-1))
15733 && mbyte_stmt != 1) {
15734 DevWarn("Memlib: multi-dim memset: size is not 1");
15735 return tree;
15736 }
15737
15738 if (!Is_Invaried_Value(load_value_wn, loop_indvar)) {
15739 DevWarn("Memlib: multi-dim memset: not constant");
15740 return tree;
15741 }
15742
15743 #ifdef KEY // bug 13219: things fall apart without this check
15744 if (! WN_operator_is(store_addr_wn, OPR_ARRAY))
15745 return tree;
15746 #endif
15747
15748
15749 INT num_dim = 0;
15750 INT indx;
15751 while (WN_operator_is(store_addr_wn, OPR_ARRAY)) {
15752 num_dim++;
15753 indx = Find_Ind_Var(WN_kid2(store_addr_wn), ind_vars, loop_level);
15754 if (!WN_operator_is(WN_kid1(store_addr_wn), OPR_INTCONST) ||
15755 trips[indx] != WN_const_val(WN_kid1(store_addr_wn))) {
15756 return tree;
15757 }
15758 if (Is_Preceding_Subtract(WN_kid2(store_addr_wn), ind_vars[indx])) {
15759 DevWarn("Memlib: mult-dim: preceding minus of indunction");
15760 return tree;
15761 }
15762 total_size *= trips[indx];
15763 store_addr_wn = WN_kid0(store_addr_wn);
15764 }
15765
15766
15767 desc_idx = WN_ty(current_wn);
15768 target_addr = Start_Addr_To_Transform(block, WN_COPY_Tree(target_addr), desc_idx);
15769 WN *call = Transform_To_Memset(target_addr, 0, desc_idx, WN_COPY_Tree(load_value_wn), WN_CreateIntconst (OPC_I4INTCONST, total_size));
15770 DevWarn("TRANSFORMED MEMSET (%s: %d): mult-dim", Src_File_Name, Srcpos_To_Line(current_srcpos));
15771
15772
15773
15774 if (call) {
15775 WN_Delete(current_wn);
15776 #ifdef KEY // bug 11360
15777 if (Action(LOWER_CALL))
15778 call = lower_call(return_block, call, actions);
15779 #endif
15780 WN_INSERT_BlockLast(return_block, call);
15781 }
15782 else
15783 WN_INSERT_BlockLast(return_block, tree);
15784
15785 return return_block;
15786 }
15787
15788
15789
15790
15791
15792
15793
15794
15795
15796
15797
15798 static WN *Lower_Memlib(WN *block, WN *tree, LOWER_ACTIONS actions)
15799 {
15800 WN *loop_info;
15801 WN *length_wn, *ind_init_val = NULL;
15802 WN *load_value_wn, *store_addr_wn, *load_addr_wn, *load_wn;
15803 WN *target_addr, *source_addr;
15804 WN *stmt, *body = WN_do_body(tree);
15805 WN *return_block = WN_CreateBlock();
15806 TY_IDX desc_idx, source_idx;
15807 OPCODE ub_compare;
15808 BOOL target_minus_ind, source_minus_ind;
15809 BOOL opt_qualified;
15810 INT i, elm_size, mbyte_stmt, istore_num = 0;
15811 INT freq_count;
15812
15813 Is_True(WN_opcode(tree)==OPC_DO_LOOP,
15814 ("expected DO_LOOP node, not %s", OPCODE_name(WN_opcode(tree))));
15815
15816 if (!OPT_Lower_To_Memlib) return tree;
15817
15818
15819 if (Cur_PU_Feedback)
15820 freq_count = (INT) Cur_PU_Feedback->Query(tree, FB_EDGE_LOOP_ITERATE).Value();
15821
15822 loop_info = WN_do_loop_info(tree);
15823 if (loop_info == NULL) {
15824 if (traceMemlib) DevWarn("NULL loop info in Lower_Memlib");
15825 return tree;
15826 }
15827
15828 WN *loop_indvar = WN_loop_induction(loop_info);
15829 if ( !loop_indvar )
15830 return tree;
15831 BOOL is_incr;
15832 WN *loop_stride = WN_LOOP_Increment(tree, &is_incr);
15833 if (!loop_stride || is_incr == FALSE ||
15834 !WN_operator_is(loop_stride, OPR_INTCONST) ||
15835 WN_const_val(loop_stride) != 1)
15836 return tree;
15837 WN *upper_bound = WN_LOOP_UpperBound(tree, &ub_compare, TRUE);
15838 if ( !upper_bound )
15839 return tree;
15840 WN *trip_count = WN_LOOP_TripCount(tree, TRUE);
15841 if ( !trip_count )
15842 return tree;
15843 WN *lower_bound = WN_LOOP_LowerBound(tree);
15844 if ( !lower_bound )
15845 return tree;
15846
15847 Is_True(WN_opcode(loop_indvar), ("expected a non-NULL loop induction"));
15848
15849
15850 if (!Cur_PU_Feedback && !WN_operator_is(trip_count, OPR_INTCONST))
15851 return tree;
15852
15853
15854 if (WN_operator_is(trip_count, OPR_INTCONST)) {
15855 if (!Cur_PU_Feedback)
15856 freq_count = WN_const_val(trip_count);
15857 else if (WN_const_val(trip_count) != freq_count) {
15858 freq_count = WN_const_val(trip_count);
15859 DevWarn("Inconsistent constant trip count and feedback");
15860 }
15861 }
15862
15863
15864
15865 if (freq_count < MEMLIB_THRESHOLD_BYTES ||
15866 (freq_count < MEMLIB_THRESHOLD_BYTES * 2 && freq_count % 8 != 0))
15867 return tree;
15868
15869
15870
15871 istore_num = 0;
15872 opt_qualified = TRUE;
15873 for (stmt=WN_first(body); stmt; stmt=WN_next(stmt)) {
15874 if (Memlib_Filter(stmt)==ABORT_OPT) return tree;
15875 else if (Memlib_Filter(stmt)== IGNORE ) continue;
15876
15877 Is_True(Memlib_Filter(stmt)== CONT_OPT, ("Memlib: expect CONT_OPT"));
15878
15879
15880 if (WN_operator_is(stmt, OPR_DO_LOOP)) {
15881 WN *return_wn = Memset_MD_Array(block,tree,actions);
15882 if (! WN_operator_is(return_wn, OPR_DO_LOOP))
15883 return return_wn;
15884 }
15885
15886
15887 if (MTYPE_is_float(WN_desc(stmt)))
15888 return tree;
15889
15890 load_value_wn = WN_kid0(stmt);
15891 if (WN_operator(load_value_wn) == OPR_PAREN)
15892 load_value_wn = WN_kid0(load_value_wn);
15893 store_addr_wn = WN_kid1(stmt);
15894
15895 mbyte_stmt = MTYPE_byte_size(OPCODE_desc(WN_opcode(stmt)));
15896
15897 if (!(WN_operator_is(load_value_wn, OPR_INTCONST) && WN_const_val(load_value_wn)==0) &&
15898 !(WN_operator_is(load_value_wn, OPR_INTCONST) && WN_const_val(load_value_wn)==-1) &&
15899 mbyte_stmt != 1) {
15900 opt_qualified = FALSE;
15901 break;
15902 }
15903
15904 if (!Is_Invaried_Value(load_value_wn, loop_indvar)) {
15905 opt_qualified = FALSE;
15906 break;
15907 }
15908
15909
15910 if (WN_operator(store_addr_wn) == OPR_ARRAY)
15911 store_addr_wn = lower_expr(block, WN_COPY_Tree(store_addr_wn), LOWER_ARRAY);
15912
15913
15914 if (!Valid_Addr_Expr(store_addr_wn, loop_indvar, mbyte_stmt))
15915 return tree;
15916 ++istore_num;
15917
15918 }
15919
15920
15921 if (opt_qualified) {
15922 if (OPT_Enable_Lower_To_Memlib_Limit != -1 &&
15923 cur_memlib_idx >= OPT_Enable_Lower_To_Memlib_Limit)
15924 return tree;
15925 cur_memlib_idx ++;
15926
15927 BOOL prev_sign, current_sign;
15928
15929 istore_num = 0;
15930
15931 for (stmt=WN_first(body); stmt; stmt=WN_next(stmt)) {
15932 if (Memlib_Filter(stmt)==ABORT_OPT) return tree;
15933 else if (Memlib_Filter(stmt)== IGNORE ) continue;
15934
15935 #ifdef KEY // bug 8604
15936 mbyte_stmt = MTYPE_byte_size(OPCODE_desc(WN_opcode(stmt)));
15937 #endif
15938 Is_True(mbyte_stmt > 0,
15939 ("expected positive size not %d", MTYPE_byte_size(OPCODE_desc(WN_opcode(stmt)))));
15940
15941 if (traceMemlib) DevWarn("Original STMT");
15942
15943 load_value_wn = WN_kid0(stmt);
15944 store_addr_wn = WN_kid1(stmt);
15945
15946
15947 if ( mbyte_stmt > 1) {
15948 if (WN_intrinsic(trip_count) >= INTRN_I4DIVFLOOR &&
15949 WN_intrinsic(trip_count) <= INTRN_U8DIVCEIL &&
15950 WN_operator(WN_kid0(WN_kid1(trip_count))) == OPR_INTCONST &&
15951 WN_const_val(WN_kid0(WN_kid1(trip_count))) == mbyte_stmt)
15952 length_wn = WN_COPY_Tree(WN_kid0(WN_kid0(trip_count)));
15953 else{
15954 OPCODE mpyopcode = OPCODE_make_op(OPR_MPY, WN_rtype(store_addr_wn),MTYPE_V);
15955 length_wn = WN_CreateExp2( mpyopcode, WN_COPY_Tree(trip_count), WN_CreateIntconst (OPC_U4INTCONST, mbyte_stmt));
15956 }
15957
15958 }
15959 else length_wn = trip_count;
15960
15961
15962
15963 if(Action(LOWER_ARRAY))
15964 length_wn = lower_expr(block, WN_COPY_Tree(length_wn), LOWER_ARRAY);
15965
15966 desc_idx = WN_ty(stmt);
15967
15968 if (WN_operator(store_addr_wn) == OPR_ARRAY)
15969 store_addr_wn = Start_Addr_To_Transform(block, WN_COPY_Tree(store_addr_wn), desc_idx);
15970
15971
15972
15973 if ( (current_sign = Is_Preceding_Subtract(store_addr_wn, loop_indvar))) {
15974
15975 #ifndef KEY
15976 Is_True(trip_count != NULL, ("Memlib: expecting non-null trip count"));
15977 OPCODE mpyopcode = OPCODE_make_op(OPR_SUB, WN_rtype(trip_count),MTYPE_V);
15978 WN *sub_wn = WN_CreateExp2(mpyopcode, WN_COPY_Tree(trip_count), WN_CreateIntconst(OPC_I4INTCONST, 1));
15979
15980 ind_init_val = WN_CreateStid(OPCODE_make_op(OPR_STID, MTYPE_V,TY_mtype(ST_type(WN_st(loop_indvar)))), WN_idname_offset(loop_indvar), WN_st(loop_indvar), Be_Type_Tbl(MTYPE_I4), sub_wn, 0);
15981
15982 #else
15983
15984 ind_init_val = WN_CreateStid(OPCODE_make_op(OPR_STID, MTYPE_V,
15985 TY_mtype(ST_type(WN_st(loop_indvar)))),
15986 WN_idname_offset(loop_indvar), WN_st(loop_indvar),
15987 Be_Type_Tbl(MTYPE_I4), WN_COPY_Tree(upper_bound), 0);
15988 #endif
15989 } else if (lower_bound != NULL)
15990
15991 ind_init_val = WN_CreateStid(OPCODE_make_op(OPR_STID, MTYPE_V, TY_mtype(ST_type(WN_st(loop_indvar)))), WN_idname_offset(loop_indvar), WN_st(loop_indvar), Be_Type_Tbl(MTYPE_I4), WN_COPY_Tree(lower_bound), 0);
15992
15993
15994
15995 if (ind_init_val) {
15996 DevWarn("Initial induction variable");
15997 WN_INSERT_BlockLast(return_block, ind_init_val);
15998 }
15999
16000 WN *call = Transform_To_Memset(store_addr_wn,0, desc_idx, load_value_wn, length_wn);
16001
16002 DevWarn("TRANSFORMED MEMSET Memlib (%s, %d) of %d\n", Src_File_Name, Srcpos_To_Line(current_srcpos), freq_count);
16003
16004 if (call) {
16005 WN_Delete(stmt);
16006 #ifdef KEY // bug 11360
16007 if (Action(LOWER_CALL))
16008 call = lower_call(return_block, call, actions);
16009 #endif
16010 WN_INSERT_BlockLast(return_block, call);
16011 }
16012 else {
16013 WN_INSERT_BlockLast(return_block, tree);
16014 break;
16015 }
16016 }
16017 return return_block;
16018 }
16019
16020
16021
16022 istore_num = 0;
16023 for (stmt=WN_first(body); stmt; stmt=WN_next(stmt)) {
16024 if (Memlib_Filter(stmt)==ABORT_OPT) return tree;
16025 else if (Memlib_Filter(stmt)==IGNORE) continue;
16026
16027 if (++istore_num > 1)
16028 return tree;
16029
16030
16031 if (WN_operator(WN_kid0(stmt))!=OPR_ILOAD &&
16032 !(WN_operator(WN_kid0(stmt)) == OPR_PAREN &&
16033 WN_operator(WN_kid0(WN_kid0(stmt))) == OPR_ILOAD))
16034 return tree;
16035
16036 if (WN_operator(WN_kid0(stmt)) == OPR_ILOAD)
16037 load_wn = WN_kid0(stmt);
16038 else
16039 load_wn = WN_kid0(WN_kid0(stmt));
16040
16041 load_addr_wn = WN_kid0(load_wn);
16042 store_addr_wn = WN_kid1(stmt);
16043
16044 if (MTYPE_byte_size(WN_desc(load_wn)) != MTYPE_byte_size(WN_desc(stmt))) {
16045 if (traceMemlib) DevWarn(" Memlib no match on size for memmove \n");
16046 return tree;
16047 }
16048
16049 mbyte_stmt = MTYPE_byte_size(OPCODE_desc(WN_opcode(stmt)));
16050
16051 if (WN_operator(store_addr_wn) == OPR_ARRAY)
16052 store_addr_wn = lower_expr(block, WN_COPY_Tree(store_addr_wn), LOWER_ARRAY);
16053 if (WN_operator(load_addr_wn) == OPR_ARRAY)
16054 load_addr_wn = lower_expr(block, WN_COPY_Tree(load_addr_wn), LOWER_ARRAY);
16055
16056
16057 if (!Valid_Addr_Expr(store_addr_wn, loop_indvar, mbyte_stmt) ||
16058 !Valid_Addr_Expr(load_addr_wn, loop_indvar, mbyte_stmt)) {
16059 return tree;
16060 }
16061
16062
16063 }
16064
16065 if (OPT_Enable_Lower_To_Memlib_Limit != -1 &&
16066 cur_memlib_idx >= OPT_Enable_Lower_To_Memlib_Limit)
16067 return tree;
16068 cur_memlib_idx ++;
16069
16070 for (stmt=WN_first(body); stmt; stmt=WN_next(stmt)) {
16071 if (Memlib_Filter(stmt)==ABORT_OPT)
16072 return tree;
16073 else if (Memlib_Filter(stmt)==IGNORE)
16074 continue;
16075
16076
16077
16078 if (Cur_PU_Feedback && Cur_PU_Feedback->Query(tree, FB_EDGE_LOOP_ITERATE).Value() < MMCOPY_MULT * MEMLIB_THRESHOLD_BYTES ||
16079 WN_operator_is(trip_count, OPR_INTCONST) && WN_const_val(trip_count) < MMCOPY_MULT * MEMLIB_THRESHOLD_BYTES)
16080 return tree;
16081
16082 if (traceMemlib) DevWarn("Original STMT \n");
16083
16084 if (WN_operator(WN_kid0(stmt)) == OPR_ILOAD)
16085 load_wn = WN_kid0(stmt);
16086 else
16087 load_wn = WN_kid0(WN_kid0(stmt));
16088 load_addr_wn = WN_kid0(load_wn);
16089 store_addr_wn = WN_kid1(stmt);
16090 mbyte_stmt = MTYPE_byte_size(OPCODE_desc(WN_opcode(stmt)));
16091
16092
16093
16094
16095
16096
16097
16098
16099 if (Memlib_Two_Aliased(store_addr_wn, load_addr_wn, mbyte_stmt)) {
16100 if (traceMemlib) DevWarn("Memlib: aliased addresses");
16101 return tree;
16102 }
16103
16104
16105 if ( mbyte_stmt > 1) {
16106 if (WN_intrinsic(trip_count) >= INTRN_I4DIVFLOOR &&
16107 WN_intrinsic(trip_count) <= INTRN_U8DIVCEIL &&
16108 WN_operator(WN_kid0(WN_kid1(trip_count))) == OPR_INTCONST &&
16109 WN_const_val(WN_kid0(WN_kid1(trip_count))) == mbyte_stmt)
16110 length_wn = WN_COPY_Tree(WN_kid0(WN_kid0(trip_count)));
16111 else{
16112 OPCODE mpyopcode = OPCODE_make_op(OPR_MPY, WN_rtype(trip_count),MTYPE_V);
16113 length_wn = WN_CreateExp2( mpyopcode, WN_COPY_Tree(trip_count), WN_CreateIntconst ( OPC_I4INTCONST, MTYPE_byte_size(OPCODE_desc(WN_opcode(stmt))) ) );
16114 }
16115 }
16116 else length_wn = trip_count;
16117
16118 if(Action(LOWER_ARRAY))
16119 length_wn = lower_expr(block, WN_COPY_Tree(length_wn), LOWER_ARRAY);
16120
16121 desc_idx = WN_ty(stmt);
16122 source_idx = WN_ty(stmt);
16123
16124 if (WN_operator(store_addr_wn) == OPR_ARRAY)
16125 store_addr_wn = Start_Addr_To_Transform(block, WN_COPY_Tree(store_addr_wn), desc_idx);
16126 if (WN_operator(load_addr_wn) == OPR_ARRAY)
16127 load_addr_wn = Start_Addr_To_Transform(block, WN_COPY_Tree(load_addr_wn), source_idx);
16128
16129 target_minus_ind = Is_Preceding_Subtract(store_addr_wn, loop_indvar);
16130 source_minus_ind = Is_Preceding_Subtract(load_addr_wn, loop_indvar);
16131
16132
16133 if (traceMemlib && target_minus_ind != source_minus_ind) {
16134 DevWarn("Inconsistent preceding sign for induction");
16135 return tree;
16136 }
16137
16138
16139
16140 if (target_minus_ind) {
16141 Is_True(trip_count != NULL, ("Memlib: expecting non-null upperbound"));
16142 OPCODE mpyopcode = OPCODE_make_op(OPR_SUB, WN_rtype(trip_count),MTYPE_V);
16143 WN *sub_wn = WN_CreateExp2(mpyopcode, WN_COPY_Tree(trip_count), WN_CreateIntconst(OPC_I4INTCONST, 1));
16144
16145 ind_init_val = WN_CreateStid(OPCODE_make_op(OPR_STID, MTYPE_V, TY_mtype(ST_type(WN_st(loop_indvar)))), WN_idname_offset(loop_indvar), WN_st(loop_indvar), Be_Type_Tbl(MTYPE_I4), sub_wn, 0);
16146
16147 } else
16148
16149 ind_init_val = WN_CreateStid(OPCODE_make_op(OPR_STID, MTYPE_V, TY_mtype(ST_type(WN_st(loop_indvar)))), WN_idname_offset(loop_indvar), WN_st(loop_indvar), Be_Type_Tbl(MTYPE_I4), lower_bound, 0);
16150
16151 if (ind_init_val) {
16152 DevWarn("Initial induction variable");
16153 WN_INSERT_BlockLast(return_block, ind_init_val);
16154 }
16155
16156 WN * wn_intrinsic = Transform_To_Memcpy(store_addr_wn, load_addr_wn, 0, desc_idx, source_idx, length_wn);
16157
16158 DevWarn("TRANSFORMED MEMCPY (%s: %d) of %d\n", Src_File_Name, Srcpos_To_Line(current_srcpos), freq_count);
16159
16160
16161 if (wn_intrinsic) {
16162 #ifdef KEY // bug 11360
16163 if (Action(LOWER_CALL))
16164 wn_intrinsic = lower_call(return_block, wn_intrinsic, actions);
16165 #endif
16166 WN_INSERT_BlockLast(return_block, wn_intrinsic);
16167 WN_Delete(stmt);
16168 }
16169 else
16170 WN_INSERT_BlockLast(return_block, tree);
16171
16172 }
16173
16174 return return_block;
16175 }
16176