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 #ifdef USE_PCH
00039 #include "be_com_pch.h"
00040 #endif
00041 #pragma hdrstop
00042 #include <isam.h>
00043 #include <alloca.h>
00044 #include <sys/signal.h>
00045 #include <elf.h>
00046 #include <map>
00047
00048 #if defined(__GNUC__) && (__GNUC__ == 3)
00049 # define USING_HASH_SET 1
00050 # include <ext/hash_set>
00051 using namespace __gnu_cxx;
00052 #elif defined(__sgi) && !defined(__GNUC__)
00053 # define USING_HASH_SET 1
00054 # include <hash_set>
00055 #else
00056 # include <set>
00057 #endif
00058
00059 #include "defs.h"
00060 #include "config.h"
00061 #include "config_asm.h"
00062 #include "config_debug.h"
00063 #include "config_opt.h"
00064 #include "config_targ2.h"
00065 #include "errors.h"
00066 #include "erglob.h"
00067 #include "tracing.h"
00068 #include "glob.h"
00069 #include "timing.h"
00070 #include "stab.h"
00071 #include "strtab.h"
00072 #include "util.h"
00073 #include "wn.h"
00074 #include "wn_util.h"
00075 #include "stblock.h"
00076 #include "data_layout.h"
00077 #include "ir_reader.h"
00078 #include "targ_sim.h"
00079 #include "targ_const.h"
00080 #include "const.h"
00081 #include "ttype.h"
00082 #include "wio.h"
00083 #include "wn_mp.h"
00084 #include "wn_pragmas.h"
00085 #include "wn_simp.h"
00086 #include "opt_alias_interface.h"
00087 #include "wn_lower.h"
00088 #include "region_util.h"
00089 #include "wutil.h"
00090 #include "wn_map.h"
00091 #include "wn_fio.h"
00092 #include "wn_trap.h"
00093 #include "pu_info.h"
00094 #include "w2op.h"
00095 #include "be_symtab.h"
00096 #include "betarget.h"
00097 #include "be_util.h"
00098 #include "opt_cvtl_rule.h"
00099 #include "fb_whirl.h"
00100 #include "intrn_info.h"
00101 #include "upc_symtab_utils.h"
00102 #include "upc_wn_util.h"
00103
00104
00105 #define SHORTCIRCUIT_HACK 1
00106
00107
00108 #include "pragma_weak.h"
00109
00110
00111
00112
00113
00114 extern PREG_NUM AssignExpr(WN *, WN *, TYPE_ID);
00115
00116 extern BOOL lower_is_aliased(WN *, WN *, INT64 size, BOOL defalt);
00117
00118 extern INT32 compute_copy_alignment(TY_IDX, TY_IDX, INT32 offset);
00119
00120 extern TYPE_ID compute_copy_quantum(INT32 );
00121
00122 extern WN *WN_I1const(TYPE_ID, INT64 con);
00123
00124
00125
00126
00127 extern INT32 MinStructCopyLoopSize;
00128 extern INT32 MinStructCopyMemIntrSize;
00129
00130
00131
00132
00133
00134 extern WN *emulate(WN *, WN *);
00135
00136 extern WN *intrinsic_runtime(WN *, WN *);
00137
00138 extern WN *make_pointer_to_node(WN *, WN *);
00139
00140 extern char *INTR_intrinsic_name( WN *);
00141
00142 extern void fdump_dep_tree(FILE *, WN *, struct ALIAS_MANAGER *);
00143
00144 extern void InitParityMaps(void);
00145
00146 extern "C" void LNOPreserveMapPair(WN *, WN *, WN *);
00147
00148 extern "C" void LNOPruneMapsUsingParity(void);
00149
00150 extern "C" void LNOPrintDepGraph(FILE *);
00151
00152 extern void enable_tree_freq_display(void);
00153
00154 extern TYPE_ID INTR_return_mtype(INTRINSIC id);
00155
00156 extern BE_ST_TAB Be_st_tab;
00157
00158
00159
00160
00161
00162
00163
00164 static WN *lower_scf(WN *, WN *, LOWER_ACTIONS);
00165 static WN *lower_expr(WN *, WN *, LOWER_ACTIONS);
00166 static WN *lower_store(WN *, WN *, LOWER_ACTIONS);
00167 static WN *lower_call(WN *, WN *, LOWER_ACTIONS);
00168 static WN *lower_intrinsic(WN *, WN *, LOWER_ACTIONS);
00169 static WN *lower_intrinsic_call(WN *, WN *, LOWER_ACTIONS);
00170 static WN *lower_intrinsic_op(WN *, WN *, LOWER_ACTIONS);
00171 static WN *lower_if(WN *, WN *, LOWER_ACTIONS);
00172 static WN *lower_stmt(WN *, WN *, LOWER_ACTIONS);
00173 static WN *lower_entry(WN *, LOWER_ACTIONS);
00174 static WN *lower_eval(WN *, WN *, LOWER_ACTIONS);
00175 static WN *lower_copy_tree(WN *, LOWER_ACTIONS);
00176 static WN *lower_emulation(WN *, WN *, LOWER_ACTIONS, BOOL &intrinsic_lowered);
00177 static WN *lower_mstore(WN *, WN *, LOWER_ACTIONS);
00178 static WN *lower_nary_madd(WN *, WN *, LOWER_ACTIONS);
00179 static WN *lower_madd(WN *, WN *, LOWER_ACTIONS);
00180 static WN *lower_assert(WN *, WN *, LOWER_ACTIONS);
00181 static WN *lower_trapuv(WN *, WN *, LOWER_ACTIONS);
00182 static WN *lower_base_reference(WN *, ST *, INT64, LOWER_ACTIONS);
00183 static WN *lower_base_register(WN *, ST *, INT64, LOWER_ACTIONS);
00184 static WN *lower_dereference(WN *, INT64, ST *, PREG_NUM, LOWER_ACTIONS);
00185 static WN *lower_split_sym_addrs(WN *, INT64, LOWER_ACTIONS);
00186 static WN *improve_Malignment(WN *, WN *, WN *, INT64);
00187 static WN *lower_branch(WN *, WN *, LOWER_ACTIONS);
00188 static WN *lower_branch_condition(BOOL, LABEL_IDX, WN *, WN **, LOWER_ACTIONS);
00189 static WN *lower_conditional(WN *, WN *, LABEL_IDX, LABEL_IDX, BOOL,
00190 LOWER_ACTIONS);
00191 static WN *lower_tree_height(WN *, WN *, LOWER_ACTIONS);
00192
00193
00194 static TY_IDX coerceTY(TY_IDX, TYPE_ID);
00195 static ST *coerceST(const ST *, TYPE_ID);
00196 static ST *coerceST(const ST &, TYPE_ID);
00197 static WN_OFFSET coerceOFFSET(WN *, TYPE_ID, WN_OFFSET);
00198
00199
00200 static WN *lower_mload(WN *, WN *, LOWER_ACTIONS);
00201 static void lower_mload_formal(WN *, WN *, PLOC, LOWER_ACTIONS);
00202 static void lower_mload_actual (WN *, WN *, PLOC, LOWER_ACTIONS);
00203 static void lower_complex_emulation(WN *, WN *, LOWER_ACTIONS, WN **, WN **);
00204 static void lower_complex_expr(WN *, WN *, LOWER_ACTIONS, WN **, WN **);
00205
00206
00207 static void lower_copy_maps(WN *, WN *, LOWER_ACTIONS);
00208 static void lower_tree_copy_maps(WN *, WN *, LOWER_ACTIONS);
00209
00210 static INT32 compute_alignment(WN *, INT64);
00211 static TYPE_ID compute_next_copy_quantum(TYPE_ID , INT32);
00212
00213 static WN* lower_TLD(WN*, WN*, LOWER_ACTIONS);
00214 static WN* lower_TLD_lda(WN*, WN*, LOWER_ACTIONS);
00215
00216 static TY_IDX struct_addr_ty(WN* tree);
00217 static int find_field_from_offset(TY_IDX ty, unsigned int offset);
00218
00219
00220
00221
00222
00223 static INT max_region;
00224 static char *current_preg_name;
00225 static UINT16 loop_nest_depth;
00226 static BOOL contains_a_loop;
00227 static struct ALIAS_MANAGER *alias_manager;
00228 #define PARITY_MAP_ARRAY_SIZE 32
00229 static WN_MAP parity_map_array[PARITY_MAP_ARRAY_SIZE];
00230 static WN_MAP lowering_parity_map = 0;
00231 static INT32 parity_map_index = -1;
00232 static LOWER_ACTIONS lowering_actions= 0;
00233 static BOOL save_Div_Split_Allowed ;
00234
00235 static BOOL traceIO = FALSE;
00236 static BOOL traceSpeculate = FALSE;
00237 static BOOL traceAlignment = FALSE;
00238 static BOOL traceTreeHeight = FALSE;
00239 static BOOL traceSplitSymOff = FALSE;
00240 static BOOL traceWoptFinishedOpt = FALSE;
00241 static BOOL traceMload = FALSE;
00242
00243
00244 typedef struct CURRENT_STATE
00245 {
00246 SRCPOS srcpos;
00247 WN *stmt;
00248 WN *function;
00249 LOWER_ACTIONS actions;
00250 } CURRENT_STATE, *CURRENT_STATEp;
00251
00252 CURRENT_STATE current_state;
00253
00254 #define current_srcpos current_state.srcpos
00255 #define current_stmt current_state.stmt
00256 #define current_actions current_state.actions
00257 #define current_function current_state.function
00258
00259 typedef enum MSTORE_ACTIONS
00260 {
00261 MSTORE_aggregate,
00262 MSTORE_loop,
00263 MSTORE_intrinsic_bzero,
00264 MSTORE_intrinsic_memset,
00265 MSTORE_intrinsic_bcopy
00266 } MSTORE_ACTIONS;
00267
00268 static const char * MSTORE_ACTIONS_name(MSTORE_ACTIONS);
00269
00270 static TYPE_ID Promoted_Mtype[MTYPE_LAST + 1] = {
00271 MTYPE_UNKNOWN,
00272 MTYPE_UNKNOWN,
00273 MTYPE_I4,
00274 MTYPE_I4,
00275 MTYPE_I4,
00276 MTYPE_I8,
00277 MTYPE_U4,
00278 MTYPE_U4,
00279 MTYPE_U4,
00280 MTYPE_U8,
00281 MTYPE_F4,
00282 MTYPE_F8,
00283 MTYPE_UNKNOWN,
00284 MTYPE_UNKNOWN,
00285 MTYPE_UNKNOWN,
00286 MTYPE_FQ,
00287 MTYPE_M,
00288 MTYPE_C4,
00289 MTYPE_C8,
00290 MTYPE_CQ,
00291 MTYPE_V
00292 };
00293
00294
00295
00296
00297
00298
00299 #define OPCODE_is_intrinsic(op) \
00300 ((OPCODE_operator((op)) == OPR_INTRINSIC_CALL) || \
00301 (OPCODE_operator((op)) == OPR_INTRINSIC_OP))
00302
00303 #define Action(x) (actions & (x))
00304 #define NotAction(x) (Action(x)==0)
00305 #define RemoveScfAction(x) (x & ~(LOWER_SCF))
00306 #define RemoveShortCircuitAction(x) (x & ~(LOWER_SHORTCIRCUIT))
00307
00308
00309 #define WN_has_alias_info(x) (OPCODE_is_load(WN_opcode(x)) || \
00310 OPCODE_is_store(WN_opcode(x)) || \
00311 WN_operator_is(x, OPR_PARM))
00312 #define WN_has_offset(x) (OPCODE_has_offset(WN_opcode(x)))
00313
00314 #define WN_nary_intrinsic(x) (WN_operator_is(x, OPR_INTRINSIC_OP) && \
00315 ((WN_intrinsic(x)== INTRN_NARY_ADD) || \
00316 (WN_intrinsic(x)== INTRN_NARY_MPY)))
00317 #define WN_nary_add(x) (WN_operator_is(x, OPR_INTRINSIC_OP) && \
00318 (WN_intrinsic(x)== INTRN_NARY_ADD))
00319 #define WN_nary_mpy(x) (WN_operator_is(x, OPR_INTRINSIC_OP) && \
00320 (WN_intrinsic(x)== INTRN_NARY_MPY))
00321
00322 #define WN_is_block(x) (WN_opcode(x) == OPC_BLOCK)
00323
00324 #define INTRN_is_nary(x) (((x)==INTRN_NARY_ADD) || ((x)==INTRN_NARY_MPY))
00325
00326 #define WN_is_commutative(x) (WN_opcode(x) == OPCODE_commutative_op(WN_opcode(x)))
00327
00328 #define TY_is_pointer(x) (TY_kind(x) == KIND_POINTER)
00329
00330 #define lower_truebr(l,c,b,a) lower_branch_condition(TRUE,l,c,b,a)
00331 #define lower_falsebr(l,c,b,a) lower_branch_condition(FALSE,l,c,b,a)
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346 #define mem_offset_hi(offset) ((offset) & ~0x7fff)
00347 #define mem_offset_lo(offset) ((offset) & 0x7fff)
00348
00349 #define mem_offset_must_be_split(offset) \
00350 (!(-32768 <= (offset) && (offset) < 32768))
00351
00352 #define mem_offset_2GB(offset) \
00353 (!(INT32_MIN <= offset && offset <= INT32_MAX))
00354
00355 #define PIC_SHARED (Gen_PIC_Shared || Gen_PIC_Call_Shared)
00356 #define PIC_NONSHARED (!PIC_SHARED)
00357
00358 #define ABS(x) (((x)<0) ? -(x) : (x))
00359 #define IS_POWER_OF_2(val) ((val != 0) && ((val & (val-1)) == 0))
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373 UINT32 compute_offset_alignment(INT32 offset, UINT32 align)
00374 {
00375 UINT32 m = ABS(offset);
00376 UINT32 n = align;
00377 while (n != 0) {
00378 INT32 new_n = m % n;
00379 m = n;
00380 n = new_n;
00381 }
00382 return m;
00383 }
00384
00385
00386
00387
00388
00389
00390
00391
00392 extern WN *WN_I1const(TYPE_ID type, INT64 con)
00393 {
00394
00395
00396 INT64 n= con & 0xff;
00397 INT64 maxAlign= MTYPE_alignment(Max_Uint_Mtype);
00398
00399 if (con)
00400 {
00401 INT64 i;
00402 for(i=1; i<maxAlign; i++)
00403 {
00404 n |= (n << 8);
00405 }
00406 }
00407
00408 return WN_Intconst(Mtype_AlignmentClass(maxAlign,
00409 MTYPE_type_class(type)), n);
00410 }
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420 static void setCurrentState(WN *tree, LOWER_ACTIONS actions)
00421 {
00422 if (tree) {
00423 current_stmt = tree;
00424 current_srcpos = WN_Get_Linenum(tree);
00425 current_actions = actions;
00426
00427 if (WN_opcode(tree) == OPC_FUNC_ENTRY)
00428 current_function = tree;
00429 }
00430 }
00431
00432 static void setCurrentStateBlockFirst(WN *tree, LOWER_ACTIONS actions)
00433 {
00434 Is_True(WN_opcode(tree) == OPC_BLOCK, ("expected BLOCK node"));
00435
00436 setCurrentState(WN_first(tree), actions);
00437 }
00438
00439 static void setCurrentStateBlockLast(WN *tree, LOWER_ACTIONS actions)
00440 {
00441 Is_True(WN_opcode(tree) == OPC_BLOCK, ("expected BLOCK node"));
00442
00443 setCurrentState(WN_last(tree), actions);
00444 }
00445
00446
00447 static CURRENT_STATE pushCurrentState(WN *tree, LOWER_ACTIONS actions)
00448 {
00449 CURRENT_STATE saveState = current_state;
00450
00451 setCurrentState(tree, actions);
00452
00453 return saveState;
00454 }
00455
00456 static void popCurrentState(CURRENT_STATE state)
00457 {
00458 current_state = state;
00459 }
00460
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472 static BOOL foldConstOffset(WN *con, INT64 offset)
00473 {
00474 if (WN_operator_is(con, OPR_INTCONST))
00475 {
00476 INT64 sum= offset + WN_const_val(con);
00477
00478 if (INT32_MIN <= sum && sum <= INT32_MAX)
00479 return TRUE;
00480 }
00481 return FALSE;
00482 }
00483
00484 static BOOL foldLdaOffset(WN *lda, INT64 offset)
00485 {
00486 if (WN_operator_is(lda, OPR_LDA))
00487 {
00488 INT64 sum= offset + WN_lda_offset(lda);
00489
00490 Is_True((WN_class(lda) != CLASS_PREG), ("lda class is PREG!!!"));
00491
00492 if (INT32_MIN <= sum && sum <= INT32_MAX)
00493 {
00494 ST *sym= WN_st(lda);
00495
00496
00497
00498
00499
00500
00501 if (ST_class(sym) == CLASS_BLOCK && STB_size(sym) < sum)
00502 return FALSE;
00503
00504 return TRUE;
00505 }
00506 }
00507 return FALSE;
00508 }
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527 static WN_OFFSET coerceOFFSET(WN *tree, TYPE_ID realTY, WN_OFFSET offset)
00528 {
00529
00530 switch (WN_operator(tree))
00531 {
00532 case OPR_ILOAD:
00533 case OPR_ILOADX:
00534 case OPR_ISTORE:
00535 case OPR_ISTOREX:
00536 return offset + MTYPE_RegisterSize(realTY);
00537
00538 case OPR_LDID:
00539 case OPR_STID:
00540 if (WN_class(tree) == CLASS_PREG)
00541 {
00542
00543
00544
00545
00546
00547 if (Preg_Is_Dedicated(offset) && offset == Float_Preg_Min_Offset)
00548 {
00549 return Float_Preg_Min_Offset + 2;
00550 }
00551 else
00552 {
00553 return offset + Preg_Increment(realTY);
00554 }
00555 }
00556 return offset + MTYPE_RegisterSize(realTY);
00557 }
00558 Fail_FmtAssertion("unexpected complex op (%s)",
00559 OPCODE_name(WN_opcode(tree)));
00560
00561 }
00562
00563
00564
00565
00566
00567
00568 static void rename_preg(char *f, char *preg_class)
00569 {
00570 static char name[41];
00571
00572 name[0] = '\0';
00573
00574 strncat(name, f, 30);
00575
00576 if (preg_class)
00577 {
00578 strncat(name, preg_class, 10);
00579 }
00580 current_preg_name = name;
00581 }
00582
00583 static void rename_reset(void)
00584 {
00585 current_preg_name = NULL;
00586 }
00587
00588
00589 static void WN_Set_Flags(WN *src, WN *dst)
00590 {
00591 if (OPCODE_has_flags(WN_opcode(src)))
00592 {
00593 Is_True(OPCODE_has_flags(WN_opcode(dst)), ("expected wn with flags"));
00594 WN_set_flag(dst, WN_flag(src));
00595 }
00596 }
00597
00598 extern void WN_annotate_intrinsic_flags(INTRINSIC id, ST *sym)
00599 {
00600 if (INTRN_is_pure(id)) {
00601 Set_PU_is_pure(Get_Current_PU());
00602 }
00603 if (INTRN_has_no_side_effects(id)) {
00604 Set_PU_no_side_effects(Get_Current_PU());
00605 }
00606 }
00607
00608 extern void WN_annotate_call_flags(WN *call, ST *sym)
00609 {
00610 WN_Set_Call_Default_Flags(call);
00611
00612 if (PU_no_side_effects(Pu_Table[ST_pu(sym)]))
00613 {
00614 WN_Reset_Call_Non_Data_Mod(call);
00615 WN_Reset_Call_Non_Parm_Mod(call);
00616 WN_Reset_Call_Parm_Mod(call);
00617
00618 }
00619 if (PU_is_pure(Pu_Table[ST_pu(sym)]))
00620 {
00621 WN_Reset_Call_Non_Data_Mod(call);
00622 WN_Reset_Call_Non_Parm_Mod(call);
00623 WN_Reset_Call_Parm_Mod(call);
00624
00625 WN_Reset_Call_Non_Data_Ref(call);
00626 WN_Reset_Call_Non_Parm_Ref(call);
00627 }
00628 }
00629
00630
00631
00632
00633
00634
00635
00636 static LABEL_IDX NewLabel(void)
00637 {
00638 LABEL_IDX label;
00639 LABEL& lab = New_LABEL(CURRENT_SYMTAB, label);
00640
00641 char *name = (char *) alloca (strlen(".L..") + 8 + 8 + 1);
00642 sprintf(name, ".L%s%d%s%d", Label_Name_Separator, Current_PU_Count(),
00643 Label_Name_Separator, label);
00644 LABEL_Init (lab, Save_Str(name), LKIND_DEFAULT);
00645 return label;
00646 }
00647
00648 static WN *WN_Label(LABEL_IDX l)
00649 {
00650 WN *label = WN_CreateLabel(ST_IDX_ZERO, l, 0, NULL);
00651 WN_Set_Linenum(label, current_srcpos);
00652 return label;
00653 }
00654
00655 static WN *WN_NewLabel(void)
00656 {
00657 LABEL_IDX label;
00658 label = NewLabel();
00659 return WN_Label(label);
00660 }
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670 static WN *WN_Falsebr(LABEL_IDX label, WN *cond)
00671 {
00672 WN *branch = WN_CreateFalsebr(label, cond);
00673 WN_Set_Linenum(branch, current_srcpos);
00674 return branch;
00675 }
00676
00677 static WN *WN_Truebr(LABEL_IDX label, WN *cond)
00678 {
00679 WN *branch = WN_CreateTruebr(label, cond);
00680 WN_Set_Linenum(branch, current_srcpos);
00681 return branch;
00682 }
00683
00684 static WN *WN_Goto(LABEL_IDX label)
00685 {
00686 WN *branch = WN_CreateGoto((ST_IDX) 0, label);
00687 WN_Set_Linenum(branch, current_srcpos);
00688 return branch;
00689 }
00690
00691 static BOOL expr_is_speculative(WN *tree)
00692 {
00693 if (OPT_Lower_Speculate)
00694 {
00695 BOOL speculate;
00696
00697 speculate = WN_Expr_Can_Be_Speculative(tree, alias_manager);
00698 if (traceSpeculate && speculate)
00699 {
00700 DevWarn("WN_lower: found speculative expression: line %d",
00701 Srcpos_To_Line(current_srcpos));
00702 }
00703 return speculate;
00704 }
00705 return FALSE;
00706 }
00707
00708
00709
00710
00711
00712
00713
00714
00715 static WN *WN_Nary(WN *tree, WN *x0, WN *x1, WN *x2, WN *x3)
00716 {
00717 TYPE_ID type = WN_rtype(tree);
00718 OPCODE op;
00719 INTRINSIC id;
00720
00721 op = OPCODE_make_op (OPR_INTRINSIC_OP, type, MTYPE_V);
00722
00723
00724
00725 switch(WN_operator(tree))
00726 {
00727 case OPR_ADD:
00728 case OPR_SUB:
00729 id = INTRN_NARY_ADD;
00730 break;
00731 case OPR_MPY:
00732 id = INTRN_NARY_MPY;
00733 break;
00734 default:
00735 Is_True(FALSE,("unexpected nary op"));
00736 }
00737
00738 {
00739 WN *args[4], **kids;
00740 INT16 i, n, argN;
00741
00742
00743
00744
00745 n= argN = 0;
00746 if (x0)
00747 args[n++] = x0;
00748 if (x1)
00749 args[n++] = x1;
00750 if (x2)
00751 args[n++] = x2;
00752 if (x3)
00753 args[n++] = x3;
00754
00755 for(i=0; i<n; i++)
00756 {
00757 WN *wn = (WN *) args[i];
00758
00759 if (WN_opcode(wn) == op && WN_intrinsic(wn) == id)
00760 argN += WN_kid_count(wn);
00761 else
00762 argN++;
00763 }
00764
00765 kids = (WN **) alloca(argN * sizeof(WN *));
00766
00767 for(i= argN= 0; i<n; i++)
00768 {
00769 WN *wn = args[i];
00770
00771 if (WN_opcode(wn) == op && WN_intrinsic(wn) == id)
00772 {
00773 INT16 j;
00774
00775 for(j=0; j< WN_kid_count(wn); j++)
00776 kids[argN++] = WN_kid(wn, j);
00777
00778 WN_Delete(wn);
00779 }
00780 else
00781 {
00782 kids[argN++] = wn;
00783 }
00784 }
00785
00786 WN_Delete(tree);
00787 tree = WN_Create_Intrinsic(op, id, argN, kids);
00788 }
00789 return tree;
00790 }
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800
00801
00802
00803
00804
00805
00806 extern WN *WN_ExprToNaryType(WN *tree, TYPE_ID type, INT count)
00807 {
00808 WN *l, *r;
00809
00810 if (count > 16) {
00811 Lmt_DevWarn(1,("WN_ExprToNaryType more than 16 deep, so stop"));
00812 return tree;
00813 }
00814 switch(WN_operator(tree))
00815 {
00816 case OPR_ADD:
00817 case OPR_MPY:
00818 l = WN_kid0(tree);
00819 r = WN_kid1(tree);
00820
00821 if ((WN_opcode(tree) == WN_opcode(l)) &&
00822 (WN_opcode(tree) == WN_opcode(r)))
00823 {
00824 WN_kid0(l) = WN_ExprToNaryType(WN_kid0(l), type, count+1);
00825 WN_kid1(l) = WN_ExprToNaryType(WN_kid1(l), type, count+1);
00826 WN_kid0(r) = WN_ExprToNaryType(WN_kid0(r), type, count+1);
00827 WN_kid1(r) = WN_ExprToNaryType(WN_kid1(r), type, count+1);
00828
00829 tree = WN_Nary(tree, WN_kid0(l), WN_kid1(l), WN_kid0(r), WN_kid1(r));
00830 WN_Delete(l);
00831 WN_Delete(r);
00832 }
00833 else if (WN_opcode(tree) == WN_opcode(l))
00834 {
00835 WN_kid0(l) = WN_ExprToNaryType(WN_kid0(l), type, count+1);
00836 WN_kid1(l) = WN_ExprToNaryType(WN_kid1(l), type, count+1);
00837
00838 tree = WN_Nary(tree, WN_kid0(l), WN_kid1(l), r, NULL);
00839 WN_Delete(l);
00840 }
00841 else if (WN_opcode(tree) == WN_opcode(r))
00842 {
00843 WN_kid0(r) = WN_ExprToNaryType(WN_kid0(r), type, count+1);
00844 WN_kid1(r) = WN_ExprToNaryType(WN_kid1(r), type, count+1);
00845
00846 tree = WN_Nary(tree, WN_kid0(r), WN_kid1(r), l, NULL);
00847 WN_Delete(r);
00848 }
00849 break;
00850
00851 case OPR_SUB:
00852 {
00853 l = WN_kid0(tree);
00854 r = WN_kid1(tree);
00855
00856 if (WN_operator_is(l, OPR_ADD))
00857 {
00858 TYPE_ID rtype = WN_rtype(tree);
00859
00860 WN *neg = WN_Neg(rtype, r);
00861
00862 WN_kid0(l) = WN_ExprToNaryType(WN_kid0(l), type, count+1);
00863 WN_kid1(l) = WN_ExprToNaryType(WN_kid1(l), type, count+1);
00864
00865 tree = WN_Nary(tree, WN_kid0(l), WN_kid1(l), neg, NULL);
00866 WN_Delete(l);
00867 }
00868 }
00869 break;
00870 }
00871 return tree;
00872 }
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884 extern WN *WN_NaryToExpr(WN *tree)
00885 {
00886 if (WN_nary_intrinsic(tree))
00887 {
00888 INT16 i;
00889 WN *wn = WN_kid0(tree);
00890 INTRINSIC id = (INTRINSIC) WN_intrinsic(tree);
00891 TYPE_ID rtype = WN_rtype(tree);
00892 INT num_parms = WN_kid_count(tree);
00893
00894 for (i = 1; i < num_parms; i++)
00895 {
00896 WN *actual = WN_kid(tree, i);
00897
00898 actual = WN_NaryToExpr(actual);
00899
00900 switch(id)
00901 {
00902 case INTRN_NARY_ADD:
00903 if (WN_operator_is(actual, OPR_NEG))
00904 {
00905 wn = WN_Sub(rtype, wn, WN_kid0(actual));
00906 WN_Delete(actual);
00907 }
00908 else
00909 {
00910 wn = WN_Add(rtype, wn, actual);
00911 }
00912 break;
00913 case INTRN_NARY_MPY:
00914 wn = WN_Mpy(rtype, wn, actual);
00915 break;
00916 }
00917 }
00918 return wn;
00919 }
00920
00921 return tree;
00922 }
00923
00924
00925
00926
00927
00928
00929
00930
00931
00932
00933
00934
00935 static WN *WN_NaryDelete(WN *tree, INT32 n)
00936 {
00937 INT32 i;
00938 INT32 num_kids= WN_kid_count(tree);
00939
00940 Is_True((n<num_kids),("cannot delete nth kid"));
00941 Is_True(WN_nary_intrinsic(tree),("expected nary op"));
00942
00943 for(i=n+1; i<num_kids; i++)
00944 {
00945 WN_actual(tree, i-1) = WN_actual(tree, i);
00946 }
00947 WN_set_kid_count(tree, WN_kid_count(tree)-1);
00948
00949 return tree;
00950 }
00951
00952
00953
00954
00955
00956
00957
00958
00959 extern INT64 lower_offset(WN *tree, INT64 offset)
00960 {
00961 if (WN_has_offset(tree))
00962 {
00963 switch(WN_operator(tree))
00964 {
00965 case OPR_LDA:
00966 offset += WN_lda_offset(tree);
00967 break;
00968 case OPR_MSTORE:
00969 case OPR_ISTORE:
00970 case OPR_ISTOREX:
00971 offset += WN_store_offset(tree);
00972 break;
00973 case OPR_STID:
00974 if (WN_class(tree) != CLASS_PREG)
00975 offset += WN_store_offset(tree);
00976 break;
00977 case OPR_LDID:
00978 if (WN_class(tree) != CLASS_PREG)
00979 offset += WN_load_offset(tree);
00980 break;
00981 case OPR_MLOAD:
00982 case OPR_ILOAD:
00983 case OPR_ILOADX:
00984 offset += WN_load_offset(tree);
00985 break;
00986 }
00987 }
00988 return offset;
00989 }
00990
00991
00992
00993
00994
00995
00996
00997
00998
00999 extern TY_IDX compute_alignment_type(WN *tree, TY_IDX type, INT64 offset)
01000 {
01001 INT32 newAlign;
01002
01003 newAlign= compute_alignment(tree, lower_offset(tree, 0));
01004
01005 newAlign= compute_offset_alignment(offset, newAlign);
01006
01007 if (TY_align(type) != newAlign)
01008 Set_TY_align(type, newAlign);
01009
01010 return type;
01011 }
01012
01013 static INT32 compute_alignment(WN *tree, INT64 offset)
01014 {
01015 WN *addr;
01016 TY_IDX type;
01017 INT32 align, align0, align1;
01018
01019 switch(WN_operator(tree))
01020 {
01021 case OPR_MSTORE:
01022 type = TY_pointed(Ty_Table[WN_ty(tree)]);
01023 addr = WN_kid1(tree);
01024
01025 if (WN_has_sym(addr) && WN_ty(addr))
01026 {
01027 return compute_alignment(addr, offset+WN_lda_offset(addr));
01028 }
01029 align = TY_align(type);
01030 break;
01031
01032 case OPR_MLOAD:
01033 type = TY_pointed(Ty_Table[WN_ty(tree)]);
01034 addr = WN_kid0(tree);
01035
01036 if (WN_has_sym(addr) && WN_ty(addr))
01037 {
01038 return compute_alignment(addr, offset+WN_lda_offset(addr));
01039 }
01040 align = TY_align(type);
01041 break;
01042
01043 case OPR_ILOAD:
01044 case OPR_ILOADX:
01045 case OPR_LDA:
01046 case OPR_LDID:
01047 type = WN_ty(tree);
01048 if (TY_is_pointer(Ty_Table[type]))
01049 {
01050 type = TY_pointed(Ty_Table[type]);
01051 }
01052 else
01053 {
01054 return 1;
01055 }
01056 align = TY_align(type);
01057 break;
01058
01059 case OPR_ARRAY:
01060 align= compute_alignment(WN_array_base(tree), offset);
01061 offset= WN_element_size(tree);
01062 break;
01063
01064 case OPR_ADD:
01065 case OPR_SUB:
01066 align0= compute_alignment(WN_kid0(tree), 0);
01067 align1= compute_alignment(WN_kid1(tree), 0);
01068 align= MIN(align0, align1);
01069 break;
01070
01071 case OPR_INTCONST:
01072 offset= WN_const_val(tree);
01073 align= MTYPE_alignment(Max_Uint_Mtype);
01074 break;
01075
01076 default:
01077 if (traceAlignment)
01078 {
01079 DevWarn("compute_alignment(): unrecognized WN returning alignment of 1");
01080 }
01081 return 1;
01082 }
01083
01084 align= compute_offset_alignment(offset, MAX(1, align));
01085
01086 if (WN_has_sym(tree))
01087 {
01088 INT32 newAlign = align;
01089 ST *sym = WN_st(tree);
01090
01091 if (WN_operator_is(tree, OPR_LDA))
01092 {
01093 newAlign= ST_alignment(sym);
01094 }
01095 else if (WN_operator_is(tree, OPR_LDID) &&
01096 ST_type(sym) &&
01097 TY_is_pointer(Ty_Table[ST_type(sym)]))
01098 {
01099 newAlign = TY_align( TY_pointed(Ty_Table[ST_type(sym)]));
01100 }
01101
01102 align = compute_offset_alignment(offset, MAX(newAlign, align));
01103 }
01104 return align;
01105 }
01106
01107
01108
01109
01110
01111
01112
01113
01114
01115 extern BOOL lower_is_aliased(WN *wn1, WN *wn2, INT64 size)
01116 {
01117 if (alias_manager &&
01118 Valid_alias(alias_manager, wn1) &&
01119 Valid_alias(alias_manager, wn2) &&
01120 (Aliased(alias_manager, wn1, wn2) == NOT_ALIASED))
01121 {
01122 return FALSE;
01123 }
01124
01125 if (WN_operator_is(wn1, OPR_LDA) && WN_operator_is(wn2, OPR_LDA)) {
01126 ST *sym1 = WN_st(wn1);
01127 ST *sym2 = WN_st(wn2);
01128 ST *base1, *base2;
01129 INT64 newoffset1, newoffset2;
01130
01131 if (sym1 != sym2) return FALSE;
01132
01133 Base_Symbol_And_Offset_For_Addressing(
01134 sym1, WN_lda_offset(wn1), &base1, &newoffset1);
01135 Base_Symbol_And_Offset_For_Addressing(
01136 sym2, WN_lda_offset(wn2), &base2, &newoffset2);
01137
01138 if (ABS(newoffset1 - newoffset2) >= size) return FALSE;
01139 }
01140
01141 return TRUE;
01142 }
01143
01144
01145
01146
01147
01148
01149
01150
01151
01152
01153
01154 static void lower_tree_copy_maps(WN *tree, WN *dup, LOWER_ACTIONS actions)
01155 {
01156 if (tree == NULL)
01157 {
01158 Is_True((dup == NULL),("inconsistency while copying trees"));
01159 }
01160 Is_True((WN_opcode(tree) == WN_opcode(dup)),
01161 ("inconsistency while copying trees"));
01162
01163 if (WN_has_map_id(tree) && WN_has_alias_info(tree))
01164 {
01165 lower_copy_maps(tree, dup, actions);
01166 }
01167
01168 if (WN_opcode(tree) == OPC_BLOCK)
01169 {
01170 WN *treeStmt = WN_first(tree);
01171 WN *dupStmt = WN_first(dup);
01172
01173 while(treeStmt)
01174 {
01175 lower_tree_copy_maps(treeStmt, dupStmt, actions);
01176 treeStmt = WN_next(treeStmt);
01177 dupStmt = WN_next(dupStmt);
01178 }
01179 }
01180 else
01181 {
01182 INT n;
01183 for(n = 0; n < WN_kid_count(tree); n++)
01184 {
01185 if (WN_kid(tree, n))
01186 {
01187 lower_tree_copy_maps(WN_kid(tree,n), WN_kid(dup,n), actions);
01188 }
01189 }
01190 }
01191 }
01192
01193 static WN *lower_copy_tree(WN *tree, LOWER_ACTIONS actions)
01194 {
01195 WN *dup;
01196
01197 dup = WN_COPY_Tree(tree);
01198
01199 lower_tree_copy_maps(tree, dup, actions);
01200
01201 return dup;
01202 }
01203
01204
01205
01206
01207
01208
01209
01210
01211
01212
01213
01214
01215
01216
01217
01218
01219
01220
01221
01222
01223 static PREG_NUM AssignPregExprPos(WN *block, WN *tree, TY_IDX ty,
01224 SRCPOS srcpos, LOWER_ACTIONS actions)
01225 {
01226 PREG_NUM pregNo;
01227 TYPE_ID type;
01228 ST *preg = MTYPE_To_PREG(TY_mtype(Ty_Table[ty]));
01229
01230 Is_True((WN_operator_is(tree, OPR_PARM)==FALSE),("bad parm"));
01231
01232 type = TY_mtype(Ty_Table[ty]);
01233 pregNo = Create_Preg(type, current_preg_name);
01234
01235 {
01236 WN *stBlock, *stid;
01237
01238 stid = WN_Stid(type, pregNo, preg, ty, tree);
01239
01240 if (srcpos)
01241 WN_Set_Linenum (stid, srcpos);
01242
01243 stBlock = WN_CreateBlock();
01244
01245
01246
01247
01248
01249 if (actions)
01250 stid = lower_store(stBlock, stid, actions);
01251
01252 WN_INSERT_BlockLast(stBlock, stid);
01253
01254 WN_INSERT_BlockLast(block, stBlock);
01255 }
01256
01257 return pregNo;
01258 }
01259
01260
01261 extern PREG_NUM AssignExprTY(WN *block, WN *tree, TY_IDX type)
01262 {
01263 return AssignPregExprPos(block, tree, type, current_srcpos,
01264 current_actions);
01265 }
01266
01267 extern PREG_NUM AssignExpr(WN *block, WN *tree, TYPE_ID type)
01268 {
01269 return AssignPregExprPos(block, tree, MTYPE_To_TY(type), current_srcpos,
01270 current_actions);
01271 }
01272
01273
01274
01275 static BOOL WN_unconditional_goto(WN *tree)
01276 {
01277 switch(WN_operator(tree))
01278 {
01279 case OPR_GOTO:
01280 case OPR_REGION_EXIT:
01281 case OPR_RETURN:
01282 case OPR_RETURN_VAL:
01283 return TRUE;
01284 }
01285 return FALSE;
01286 }
01287
01288
01289
01290
01291
01292
01293
01294
01295
01296
01297
01298
01299
01300 PARITY WN_parity(WN *tree)
01301 {
01302 if (WN_map_id(tree) != -1)
01303 {
01304 INT32 map;
01305
01306 Is_True((lowering_parity_map != 0), ("parity map not initialized"));
01307 map = WN_MAP32_Get(lowering_parity_map, tree);
01308
01309 if (map!=0)
01310 return (PARITY) map;
01311 }
01312 return PARITY_UNKNOWN;
01313 }
01314
01315 BOOL WN_parity_independent(WN *wn1, WN *wn2)
01316 {
01317
01318 if (wn1 == NULL ||
01319 wn2 == NULL ||
01320 WN_map_id(wn1) == -1 ||
01321 WN_map_id(wn2) == -1)
01322 return FALSE;
01323
01324 {
01325 PARITY p1 = WN_parity(wn1);
01326 PARITY p2 = WN_parity(wn2);
01327
01328 return (p1 & p2) ? FALSE : TRUE;
01329 }
01330 }
01331
01332
01333
01334
01335
01336
01337
01338
01339
01340
01341
01342
01343
01344
01345
01346
01347
01348
01349
01350
01351 static void lower_maps_init(LOWER_ACTIONS actions)
01352 {
01353
01354 }
01355
01356 static void lower_maps_reset(LOWER_ACTIONS actions)
01357 {
01358 if (Action(LOWER_DEPGRAPH_MAPS))
01359 {
01360 LNOPruneMapsUsingParity();
01361 }
01362 }
01363
01364 static void lower_map(WN *tree, LOWER_ACTIONS actions)
01365 {
01366 if (Action(LOWER_ALIAS_MAPS))
01367 {
01368 if (alias_manager)
01369 {
01370 if (Valid_alias(alias_manager, tree) == FALSE)
01371 Create_alias(alias_manager, tree);
01372 }
01373 }
01374 }
01375
01376 static void lower_copy_maps(WN *orig, WN *tree, LOWER_ACTIONS actions)
01377 {
01378 if (orig == NULL)
01379 return;
01380
01381
01382
01383
01384
01385 if (WN_has_map_id(orig))
01386 {
01387 if (WN_has_alias_info(orig) &&
01388 WN_has_alias_info(tree))
01389 {
01390 if (Action(LOWER_PREFETCH_MAPS))
01391 {
01392 WN_CopyMap(tree, WN_MAP_PREFETCH, orig);
01393 }
01394 if (Action(LOWER_ALIAS_MAPS))
01395 {
01396 if (alias_manager)
01397 Copy_alias_info(alias_manager, orig, tree);
01398 }
01399 }
01400 }
01401 WN_Set_Flags(orig, tree);
01402 }
01403
01404
01405
01406
01407
01408
01409
01410 static void lower_copy_tys (WN *orig, WN *node1, WN *node2)
01411 {
01412 TY_IDX ty;
01413
01414 if (WN_operator_is(orig, OPR_ILOAD))
01415 {
01416 ty = WN_load_addr_ty(orig);
01417
01418 if (TY_is_f90_pointer(Ty_Table[ty]))
01419 {
01420 if (node1 && WN_operator_is(node1, OPR_ILOAD))
01421 WN_set_load_addr_ty(node1, ty);
01422
01423 if (node2 && WN_operator_is(node2, OPR_ILOAD))
01424 WN_set_load_addr_ty(node2, ty);
01425 }
01426 }
01427 else if (WN_operator_is(orig, OPR_ISTORE))
01428 {
01429 ty = WN_ty(orig);
01430 if (TY_is_f90_pointer(Ty_Table[ty]))
01431 {
01432 if (node1 && WN_operator_is(node1, OPR_ISTORE))
01433 WN_set_ty(node1, ty);
01434 if (node2 && WN_operator_is(node2, OPR_ISTORE))
01435 WN_set_ty(node2, ty);
01436 }
01437 }
01438 }
01439
01440
01441 static void lower_quad_maps(WN *orig, WN *hipart, WN *lopart,
01442 LOWER_ACTIONS actions)
01443 {
01444 lower_copy_maps(orig, hipart, actions);
01445 lower_copy_maps(orig, lopart, actions);
01446 lower_copy_tys(orig,hipart,lopart);
01447
01448 if (Action(LOWER_DEPGRAPH_MAPS))
01449 {
01450 LNOPreserveMapPair(orig, hipart, lopart);
01451 }
01452
01453 if (Action(LOWER_PARITY_MAPS))
01454 {
01455 WN_MAP32_Set(lowering_parity_map, hipart, PARITY_QUAD_HI);
01456 WN_MAP32_Set(lowering_parity_map, lopart, PARITY_QUAD_LO);
01457 }
01458 }
01459
01460 static void lower_complex_maps(WN *orig, WN *real, WN *imag,
01461 LOWER_ACTIONS actions)
01462 {
01463 lower_copy_maps(orig, real, actions);
01464 lower_copy_maps(orig, imag, actions);
01465 lower_copy_tys(orig,real,imag);
01466
01467 if (Action(LOWER_DEPGRAPH_MAPS))
01468 {
01469 LNOPreserveMapPair(orig, real, imag);
01470 }
01471
01472 if (Action(LOWER_PARITY_MAPS))
01473 {
01474 WN_MAP32_Set(lowering_parity_map, real, PARITY_COMPLEX_REAL);
01475 WN_MAP32_Set(lowering_parity_map, imag, PARITY_COMPLEX_IMAG);
01476 }
01477
01478 }
01479
01480 static WN *add_to_base(WN **base, WN *tree)
01481 {
01482 if (*base)
01483 {
01484 return WN_Add(Pointer_type, *base, tree);
01485 }
01486 return tree;
01487 }
01488
01489 static WN *sub_from_base(WN **base, WN *tree)
01490 {
01491 if (*base)
01492 {
01493 return WN_Sub(Pointer_type, *base, tree);
01494 }
01495 return tree;
01496 }
01497
01498 static BOOL baseAddress(WN *tree)
01499 {
01500 switch(WN_operator(tree))
01501 {
01502 case OPR_LDA:
01503 case OPR_LDID:
01504 case OPR_ILOAD:
01505 case OPR_ILOADX:
01506 return TRUE;
01507 }
01508 return FALSE;
01509 }
01510
01511
01512
01513
01514
01515
01516
01517
01518
01519
01520
01521
01522
01523
01524
01525
01526
01527
01528
01529
01530 static void lower_to_base_index(WN *addr, WN **base, WN **index)
01531 {
01532 WN *l, *r;
01533
01534 switch (WN_operator(addr))
01535 {
01536 case OPR_ARRAY:
01537 *base = add_to_base(base, WN_array_base(addr));
01538 *index = add_to_base(index, addr);
01539 WN_array_base(addr) = WN_Zerocon(WN_rtype(addr));
01540 break;
01541
01542 case OPR_ADD:
01543 l = WN_kid0(addr);
01544 r = WN_kid1(addr);
01545
01546 if (baseAddress(l))
01547 {
01548 *base = add_to_base(base, l);
01549 *index = add_to_base(index, r);
01550 }
01551 else if (baseAddress(r))
01552 {
01553 *base = add_to_base(base, r);
01554 *index = add_to_base(index, l);
01555 }
01556 else if (WN_operator_is(r, OPR_ARRAY))
01557 {
01558 *base = add_to_base(base, WN_array_base(r));
01559 WN_array_base(r) = WN_Zerocon(WN_rtype(r));
01560 *index = add_to_base(index, addr);
01561 }
01562 else if (WN_operator_is(l, OPR_ARRAY))
01563 {
01564 *base = add_to_base(base, WN_array_base(l));
01565 WN_array_base(l) = WN_Zerocon(WN_rtype(l));
01566 *index = add_to_base(index, addr);
01567 }
01568 else if ((WN_operator_is(r, OPR_ADD) || WN_operator_is(r, OPR_SUB))
01569 && WN_operator_is(l, OPR_INTCONST))
01570 {
01571 lower_to_base_index(r, base, index);
01572 *index = add_to_base(index, l);
01573 }
01574 else if ((WN_operator_is(l, OPR_ADD) || WN_operator_is(l, OPR_SUB))
01575 && WN_operator_is(r, OPR_INTCONST))
01576 {
01577 lower_to_base_index(l, base, index);
01578 *index = add_to_base(index, r);
01579 }
01580 else
01581 {
01582
01583 *base = add_to_base(base, addr);
01584 *index = add_to_base(index, WN_Zerocon(WN_rtype(addr)));
01585 }
01586 break;
01587
01588 case OPR_SUB:
01589 l = WN_kid0(addr);
01590 r = WN_kid1(addr);
01591
01592 if (baseAddress(l))
01593 {
01594 *base = add_to_base(base, l);
01595 *index = sub_from_base(index, r);
01596 }
01597 else if (baseAddress(r))
01598 {
01599 *base = sub_from_base(base, r);
01600 *index = add_to_base(index, l);
01601 }
01602 else if (WN_operator_is(r, OPR_ARRAY))
01603 {
01604 *base = sub_from_base(base, WN_array_base(r));
01605 WN_array_base(r) = WN_Zerocon(WN_rtype(r));
01606 *index = add_to_base(index, addr);
01607 }
01608 else if (WN_operator_is(l, OPR_ARRAY))
01609 {
01610 *base = add_to_base(base, WN_array_base(l));
01611 WN_array_base(l) = WN_Zerocon(WN_rtype(l));
01612 *index = add_to_base(index, addr);
01613 }
01614 else if ((WN_operator_is(r, OPR_ADD) || WN_operator_is(r, OPR_SUB))
01615 && WN_operator_is(l, OPR_INTCONST))
01616 {
01617 lower_to_base_index(r, base, index);
01618 *base = WN_Neg(WN_rtype(*base),*base);
01619 *index = sub_from_base(&l,*index);
01620 }
01621 else if ((WN_operator_is(l, OPR_ADD) || WN_operator_is(l, OPR_SUB))
01622 && WN_operator_is(r, OPR_INTCONST))
01623 {
01624 lower_to_base_index(l, base, index);
01625 *index = sub_from_base(index, r);
01626 }
01627 else
01628 {
01629
01630 *base = add_to_base(base, addr);
01631 *index = add_to_base(index, WN_Zerocon(WN_rtype(addr)));
01632 }
01633 break;
01634 default:
01635
01636 *base = add_to_base(base, addr);
01637 *index = add_to_base(index, WN_Zerocon(WN_rtype(addr)));
01638 break;
01639 }
01640 }
01641
01642
01643
01644
01645
01646 typedef enum {LEAF_IS_CONST, LEAF_IS_INTCONST, LEAF_IS_PREG} LEAF_KIND;
01647 typedef struct {
01648 LEAF_KIND kind;
01649 TYPE_ID type;
01650 union {
01651 PREG_NUM n;
01652 INT64 intval;
01653 TCON tc;
01654 } u;
01655 } LEAF;
01656
01657
01658
01659
01660
01661
01662
01663
01664
01665
01666
01667
01668
01669
01670
01671
01672 static LEAF Make_Leaf(WN *block, WN *tree, TYPE_ID type)
01673 {
01674 LEAF leaf;
01675 leaf.type = type;
01676 switch (WN_operator(tree)) {
01677 case OPR_CONST:
01678 leaf.kind = LEAF_IS_CONST;
01679 leaf.u.tc = Const_Val(tree);
01680 WN_Delete(tree);
01681 break;
01682 case OPR_INTCONST:
01683 leaf.kind = LEAF_IS_INTCONST;
01684 leaf.u.intval = WN_const_val(tree);
01685 WN_Delete(tree);
01686 break;
01687 default:
01688 leaf.kind = LEAF_IS_PREG;
01689 leaf.u.n = AssignExpr(block, tree, type);
01690 break;
01691 }
01692 return leaf;
01693 }
01694
01695
01696
01697
01698
01699
01700
01701
01702
01703
01704 static WN *Load_Leaf(const LEAF &leaf)
01705 {
01706 switch (leaf.kind) {
01707 case LEAF_IS_CONST:
01708 return Make_Const(leaf.u.tc);
01709 case LEAF_IS_INTCONST:
01710 return WN_CreateIntconst(OPR_INTCONST, leaf.type, MTYPE_V, leaf.u.intval);
01711 case LEAF_IS_PREG:
01712 return WN_LdidPreg(leaf.type, leaf.u.n);
01713 }
01714 FmtAssert(FALSE, ("unhandled leaf kind in Load_Leaf"));
01715
01716 }
01717
01718
01719
01720
01721
01722
01723
01724
01725
01726
01727
01728
01729
01730
01731 static void lower_complex_expr(WN *block, WN *tree, LOWER_ACTIONS actions,
01732 WN **realpart, WN **imagpart)
01733 {
01734 TYPE_ID type;
01735
01736
01737 Is_True(OPCODE_is_expression(WN_opcode(tree)),
01738 ("expected expression node, not %s", OPCODE_name(WN_opcode(tree))));
01739 Is_True(Action(LOWER_COMPLEX), ("actions does not contain LOWER_COMPLEX"));
01740 Is_True((MTYPE_is_complex(WN_rtype(tree))),
01741 ("expected complex-type node, not %s",
01742 OPCODE_name(WN_opcode(tree))));
01743 type = Mtype_complex_to_real(WN_rtype(tree));
01744
01745
01746
01747
01748
01749
01750
01751
01752
01753
01754
01755
01756 switch (WN_operator(tree))
01757 {
01758 case OPR_LDID:
01759 {
01760
01761
01762
01763
01764
01765 TY_IDX beTY = MTYPE_To_TY(type);
01766 WN_OFFSET offset = WN_load_offset(tree);
01767
01768 if (WN_class(tree) == CLASS_CONST && offset == 0)
01769 {
01770 TCON val = WN_val(tree);
01771 TYPE_ID valType = WN_val_type(tree);
01772
01773 if (WN_rtype(tree) == valType)
01774 {
01775 *realpart = Make_Const( Extract_Complex_Real(val));
01776 *imagpart = Make_Const( Extract_Complex_Imag(val));
01777 break;
01778 }
01779 }
01780
01781 *realpart = WN_Ldid(type, offset,
01782 coerceST(WN_st(tree), type),
01783 beTY);
01784
01785 *imagpart = WN_Ldid(type,
01786 coerceOFFSET(tree, type, offset),
01787 coerceST(WN_st(tree), type),
01788 beTY);
01789 }
01790 break;
01791
01792 case OPR_ILOAD:
01793 {
01794
01795
01796
01797
01798
01799
01800
01801
01802 WN_OFFSET offset = WN_load_offset(tree);
01803
01804 if (Action(LOWER_BASE_INDEX))
01805 {
01806 WN *addr, *base, *index;
01807 LEAF indexN;
01808
01809 base = index= NULL;
01810 lower_to_base_index(WN_kid0(tree), &base, &index) ;
01811
01812 base = lower_expr(block, base, actions);
01813 index = lower_expr(block, index, actions);
01814
01815 indexN = Make_Leaf(block, index, Pointer_type);
01816
01817 addr = WN_Add(Pointer_type,
01818 Load_Leaf(indexN),
01819 lower_copy_tree(base, actions));
01820
01821 *realpart = WN_Iload(type,
01822 offset,
01823 coerceTY(WN_ty(tree), type),
01824 addr);
01825
01826 addr = WN_Add(Pointer_type, Load_Leaf(indexN), base);
01827
01828 *imagpart = WN_Iload(type,
01829 coerceOFFSET(tree, type, offset),
01830 coerceTY(WN_ty(tree), type),
01831 addr);
01832 }
01833 else
01834 {
01835 WN *addr;
01836 LEAF addrN;
01837
01838 addr = lower_expr(block, WN_kid0(tree), actions);
01839
01840 addrN = Make_Leaf(block, addr, Pointer_type);
01841
01842 *realpart = WN_Iload(type,
01843 offset,
01844 coerceTY(WN_ty(tree), type),
01845 Load_Leaf(addrN));
01846
01847 *imagpart = WN_Iload(type,
01848 coerceOFFSET(tree, type, offset),
01849 coerceTY(WN_ty(tree), type),
01850 Load_Leaf(addrN));
01851 }
01852 lower_complex_maps(tree, *realpart, *imagpart, actions);
01853 }
01854 break;
01855
01856 case OPR_ILOADX:
01857 Is_True(FALSE, ("unexpected complex ILOADX"));
01858 break;
01859
01860 case OPR_NEG:
01861 {
01862
01863
01864
01865 WN *rz, *iz;
01866
01867 lower_complex_expr(block, WN_kid0(tree), actions, &rz, &iz);
01868 *realpart = WN_Neg( type, rz);
01869 *imagpart = WN_Neg( type, iz);
01870
01871 }
01872 break;
01873
01874 case OPR_ADD:
01875 {
01876 WN *rz, *rw, *iz, *iw;
01877
01878
01879
01880
01881 lower_complex_expr(block, WN_kid0(tree), actions, &rz, &iz);
01882 lower_complex_expr(block, WN_kid1(tree), actions, &rw, &iw);
01883
01884 *realpart = WN_Add( type, rz, rw);
01885 *imagpart = WN_Add( type, iz, iw);
01886 }
01887 break;
01888
01889 case OPR_SUB:
01890 {
01891
01892
01893
01894 WN *rz, *rw, *iz, *iw;
01895
01896 lower_complex_expr(block, WN_kid0(tree), actions, &rz, &iz);
01897 lower_complex_expr(block, WN_kid1(tree), actions, &rw, &iw);
01898
01899 *realpart = WN_Sub( type, rz, rw);
01900 *imagpart = WN_Sub( type, iz, iw);
01901 }
01902 break;
01903
01904 case OPR_MPY:
01905 {
01906
01907
01908
01909
01910 WN *rz, *rw, *iz, *iw;
01911 LEAF rzN, rwN, izN, iwN;
01912
01913 lower_complex_expr(block, WN_kid0(tree), actions, &rz, &iz);
01914 lower_complex_expr(block, WN_kid1(tree), actions, &rw, &iw);
01915
01916 rzN = Make_Leaf(block, rz, type);
01917 rwN = Make_Leaf(block, rw, type);
01918 izN = Make_Leaf(block, iz, type);
01919 iwN = Make_Leaf(block, iw, type);
01920
01921 *realpart = WN_Sub(type,
01922 WN_Mpy(type, Load_Leaf(rzN), Load_Leaf(rwN)),
01923 WN_Mpy(type, Load_Leaf(izN), Load_Leaf(iwN)));
01924
01925 *imagpart = WN_Add(type,
01926 WN_Mpy(type, Load_Leaf(rzN), Load_Leaf(iwN)),
01927 WN_Mpy(type, Load_Leaf(rwN), Load_Leaf(izN)));
01928 }
01929 break;
01930
01931 case OPR_COMPLEX:
01932
01933
01934
01935
01936
01937 *realpart = lower_expr(block, WN_kid0(tree), actions);
01938 *imagpart = lower_expr(block, WN_kid1(tree), actions);
01939 WN_Delete(tree);
01940 break;
01941
01942 case OPR_MADD:
01943 case OPR_MSUB:
01944 case OPR_NMADD:
01945 case OPR_NMSUB:
01946 Is_True( FALSE, ("unexpected complex madd"));
01947 break;
01948
01949 case OPR_CVT:
01950 {
01951 WN *rz, *iz;
01952 TYPE_ID desc = WN_desc(tree);
01953
01954 lower_complex_expr(block, WN_kid0(tree), actions, &rz, &iz);
01955
01956 *realpart = WN_Cvt( type, Mtype_complex_to_real(desc), rz);
01957 *imagpart = WN_Cvt( type, Mtype_complex_to_real(desc), iz);
01958 }
01959 break;
01960
01961 case OPR_CONST:
01962 {
01963
01964
01965
01966 TCON val = Const_Val(tree);
01967
01968 *realpart = Make_Const( Extract_Complex_Real(val));
01969 *imagpart = Make_Const( Extract_Complex_Imag(val));
01970
01971 WN_Delete(tree);
01972 }
01973 break;
01974
01975 case OPR_RSQRT:
01976 {
01977 TYPE_ID desc = WN_desc(tree);
01978 WN *div;
01979
01980 div = WN_Div(desc,
01981 WN_Floatconst(desc, 1.0),
01982 WN_Sqrt(desc, WN_kid0(tree)));
01983
01984 lower_complex_expr(block, div, actions, realpart, imagpart);
01985
01986 WN_Delete(tree);
01987 }
01988 break;
01989
01990 case OPR_SQRT:
01991 lower_complex_emulation(block, tree, actions, realpart, imagpart);
01992 break;
01993
01994
01995 case OPR_PAREN:
01996 {
01997 lower_complex_expr(block, WN_kid0(tree), actions, realpart, imagpart);
01998
01999 *realpart = WN_Paren(type, *realpart);
02000 *imagpart = WN_Paren(type, *imagpart);
02001 WN_Delete(tree);
02002 }
02003 break;
02004
02005 case OPR_ARRAY:
02006 break;
02007
02008 case OPR_RECIP:
02009 {
02010
02011
02012
02013
02014
02015
02016 LEAF rzN, izN;
02017 {
02018
02019
02020
02021
02022 WN *rz, *iz;
02023
02024 lower_complex_expr(block, WN_kid0(tree), actions, &rz, &iz);
02025
02026 rzN = Make_Leaf(block, rz, type);
02027 izN = Make_Leaf(block, iz, type);
02028 }
02029
02030 if (Fast_Complex_Allowed)
02031 {
02032
02033
02034
02035
02036
02037
02038 LEAF denomN;
02039 WN *rz2, *iz2, *add;
02040
02041 rz2 = WN_Mpy(type, Load_Leaf(rzN), Load_Leaf(rzN));
02042 iz2 = WN_Mpy(type, Load_Leaf(izN), Load_Leaf(izN));
02043 add = WN_Add(type, rz2, iz2);
02044 denomN = Make_Leaf(block, add, type);
02045
02046 *realpart = WN_Div(type, Load_Leaf(rzN), Load_Leaf(denomN));
02047 *imagpart = WN_Neg(type,
02048 WN_Div(type, Load_Leaf(izN), Load_Leaf(denomN)));
02049 }
02050 else
02051 {
02052
02053
02054
02055
02056
02057
02058
02059
02060
02061
02062
02063
02064
02065
02066
02067
02068
02069
02070
02071
02072 WN *if_then, *if_else, *IF;
02073 PREG_NUM realpartN, imagpartN;
02074 LEAF xN, arzN, aizN;
02075
02076 {
02077 WN *numer, *denom, *div;
02078
02079 arzN = Make_Leaf(block,
02080 WN_Abs(type, Load_Leaf(rzN)),
02081 type);
02082
02083 aizN = Make_Leaf(block,
02084 WN_Abs(type, Load_Leaf(izN)),
02085 type);
02086
02087
02088
02089
02090
02091
02092
02093 numer = WN_Select(type,
02094 WN_GT(type, Load_Leaf(arzN), Load_Leaf(aizN)),
02095 Load_Leaf(izN),
02096 Load_Leaf(rzN));
02097 denom = WN_Select(type,
02098 WN_GT(type, Load_Leaf(arzN), Load_Leaf(aizN)),
02099 Load_Leaf(rzN),
02100 Load_Leaf(izN));
02101
02102 div = WN_Div(type, numer, denom);
02103
02104 xN = Make_Leaf(block, div, type);
02105 }
02106
02107 if_then = WN_CreateBlock();
02108 {
02109
02110
02111
02112
02113
02114 WN *scale, *div;
02115 LEAF scaleN;
02116
02117 scale = WN_Add(type,
02118 Load_Leaf(rzN),
02119 WN_Mpy(type, Load_Leaf(izN), Load_Leaf(xN)));
02120 scaleN = Make_Leaf(if_then, scale, type);
02121
02122 div = WN_Inverse(type, Load_Leaf(scaleN));
02123
02124 realpartN = AssignExpr(if_then, div, type);
02125
02126 div = WN_Div(type,
02127 WN_Neg(type, Load_Leaf(xN)),
02128 Load_Leaf(scaleN));
02129
02130 imagpartN = AssignExpr(if_then, div, type);
02131 }
02132
02133 if_else = WN_CreateBlock();
02134 {
02135
02136
02137
02138
02139
02140 WN *scale, *div, *stid;
02141 LEAF scaleN;
02142 ST *preg = MTYPE_To_PREG(type);
02143
02144 scale = WN_Add(type,
02145 WN_Mpy(type, Load_Leaf(rzN), Load_Leaf(xN)),
02146 Load_Leaf(izN));
02147 scaleN = Make_Leaf(if_else, scale, type);
02148
02149 div = WN_Div(type, Load_Leaf(xN), Load_Leaf(scaleN));
02150 stid = WN_StidIntoPreg(type, realpartN, preg, div);
02151 WN_INSERT_BlockLast(if_else, stid);
02152
02153 div = WN_Neg(type,WN_Inverse(type, Load_Leaf(scaleN)));
02154 stid = WN_StidIntoPreg(type, imagpartN, preg, div);
02155 WN_INSERT_BlockLast(if_else, stid);
02156 }
02157
02158 IF = WN_CreateIf(WN_GT(type, Load_Leaf(arzN), Load_Leaf(aizN)),
02159 if_then, if_else);
02160
02161 if ( Cur_PU_Feedback ) {
02162 Cur_PU_Feedback->Annot( IF, FB_EDGE_BRANCH_TAKEN, FB_FREQ_UNKNOWN );
02163 Cur_PU_Feedback->Annot( IF, FB_EDGE_BRANCH_NOT_TAKEN,
02164 FB_FREQ_UNKNOWN );
02165 }
02166
02167 WN_INSERT_BlockLast(block, lower_if(block, IF, actions));
02168
02169 *realpart = WN_LdidPreg(type, realpartN);
02170 *imagpart = WN_LdidPreg(type, imagpartN);
02171 }
02172 WN_Delete(tree);
02173 }
02174 break;
02175
02176 case OPR_DIV:
02177 {
02178
02179
02180
02181
02182 WN *rz, *rw, *iz, *iw;
02183 LEAF rzN, rwN, izN, iwN;
02184
02185 lower_complex_expr(block, WN_kid0(tree), actions, &rz, &iz);
02186 lower_complex_expr(block, WN_kid1(tree), actions, &rw, &iw);
02187
02188 rzN = Make_Leaf(block, rz, type);
02189 izN = Make_Leaf(block, iz, type);
02190 rwN = Make_Leaf(block, rw, type);
02191 iwN = Make_Leaf(block, iw, type);
02192
02193 if (Fast_Complex_Allowed)
02194 {
02195
02196
02197
02198
02199
02200
02201 LEAF denomN;
02202 {
02203 WN *rw2, *iw2, *add;
02204
02205 rw2 = WN_Mpy(type,Load_Leaf(rwN), Load_Leaf(rwN));
02206 iw2 = WN_Mpy(type, Load_Leaf(iwN), Load_Leaf(iwN));
02207 add = WN_Add(type, rw2, iw2);
02208 denomN = Make_Leaf(block, add, type);
02209 }
02210 {
02211 WN *rzrw, *iziw;
02212
02213 rzrw = WN_Mpy(type, Load_Leaf(rzN), Load_Leaf(rwN));
02214 iziw = WN_Mpy(type, Load_Leaf(izN), Load_Leaf(iwN));
02215 *realpart = WN_Div(type,
02216 WN_Add(type, rzrw, iziw),
02217 Load_Leaf(denomN));
02218 }
02219 {
02220 WN *rziw, *izrw;
02221
02222 izrw = WN_Mpy(type, Load_Leaf(izN), Load_Leaf(rwN));
02223 rziw = WN_Mpy(type, Load_Leaf(rzN), Load_Leaf(iwN));
02224 *imagpart = WN_Div(type,
02225 WN_Sub(type, izrw, rziw),
02226 Load_Leaf(denomN));
02227 }
02228 }
02229 else
02230 {
02231
02232
02233
02234
02235
02236
02237
02238
02239
02240
02241
02242
02243
02244
02245
02246
02247
02248
02249
02250
02251 WN *if_then, *if_else, *IF;
02252 LEAF xN, arwN, aiwN;
02253 PREG_NUM realpartN, imagpartN;
02254 {
02255 WN *numer, *denom, *div;
02256
02257 arwN = Make_Leaf(block,
02258 WN_Abs(type, Load_Leaf(rwN)),
02259 type);
02260 aiwN = Make_Leaf(block,
02261 WN_Abs(type, Load_Leaf(iwN)),
02262 type);
02263
02264
02265
02266
02267
02268
02269
02270 numer = WN_Select(type,
02271 WN_GT(type, Load_Leaf(arwN), Load_Leaf(aiwN)),
02272 Load_Leaf(iwN),
02273 Load_Leaf(rwN));
02274 denom = WN_Select(type,
02275 WN_GT(type, Load_Leaf(arwN), Load_Leaf(aiwN)),
02276 Load_Leaf(rwN),
02277 Load_Leaf(iwN));
02278 div = WN_Div(type, numer, denom);
02279 xN = Make_Leaf(block, div, type);
02280 }
02281
02282 if_then = WN_CreateBlock();
02283 {
02284 WN *scale;
02285 LEAF scaleN;
02286
02287 scale = WN_Add(type,
02288 Load_Leaf(rwN),
02289 WN_Mpy(type, Load_Leaf(iwN), Load_Leaf(xN)));
02290 scaleN = Make_Leaf(if_then, scale, type);
02291 {
02292
02293
02294
02295 WN *numer, *div;
02296
02297 numer = WN_Add(type,
02298 Load_Leaf(rzN),
02299 WN_Mpy(type, Load_Leaf(izN), Load_Leaf(xN)));
02300 div = WN_Div(type, numer, Load_Leaf(scaleN));
02301 realpartN = AssignExpr(if_then, div, type);
02302 }
02303 {
02304
02305
02306
02307 WN *numer, *div;
02308
02309 numer = WN_Sub(type,
02310 Load_Leaf(izN),
02311 WN_Mpy(type, Load_Leaf(rzN), Load_Leaf(xN)));
02312 div = WN_Div(type, numer, Load_Leaf(scaleN));
02313 imagpartN = AssignExpr(if_then, div, type);
02314 }
02315 }
02316
02317 if_else = WN_CreateBlock();
02318 {
02319 WN *scale;
02320 LEAF scaleN;
02321 ST *preg = MTYPE_To_PREG(type);
02322
02323 scale = WN_Add(type,
02324 WN_Mpy(type, Load_Leaf(rwN), Load_Leaf(xN)),
02325 Load_Leaf(iwN));
02326 scaleN = Make_Leaf(if_else, scale, type);
02327 {
02328
02329
02330
02331
02332 WN *numer, *div, *stid;
02333
02334 numer = WN_Add(type,
02335 WN_Mpy(type, Load_Leaf(rzN), Load_Leaf(xN)),
02336 Load_Leaf(izN));
02337 div = WN_Div(type, numer, Load_Leaf(scaleN));
02338 stid = WN_StidIntoPreg(type, realpartN, preg, div);
02339 WN_INSERT_BlockLast(if_else, stid);
02340 }
02341 {
02342
02343
02344
02345
02346 WN *numer, *div, *stid;
02347
02348 numer = WN_Sub(type,
02349 WN_Mpy(type, Load_Leaf(izN), Load_Leaf(xN)),
02350 Load_Leaf(rzN));
02351 div = WN_Div(type, numer, Load_Leaf(scaleN));
02352 stid = WN_StidIntoPreg(type, imagpartN, preg, div);
02353 WN_INSERT_BlockLast(if_else, stid);
02354 }
02355 }
02356
02357 IF = WN_CreateIf(WN_GT(type, Load_Leaf(arwN), Load_Leaf(aiwN)),
02358 if_then, if_else);
02359
02360 if ( Cur_PU_Feedback ) {
02361 Cur_PU_Feedback->Annot( IF, FB_EDGE_BRANCH_TAKEN, FB_FREQ_UNKNOWN );
02362 Cur_PU_Feedback->Annot( IF, FB_EDGE_BRANCH_NOT_TAKEN,
02363 FB_FREQ_UNKNOWN );
02364 }
02365
02366 WN_INSERT_BlockLast(block, lower_if(block, IF, actions));
02367
02368 *realpart = WN_LdidPreg(type, realpartN);
02369 *imagpart = WN_LdidPreg(type, imagpartN);
02370 }
02371 WN_Delete(tree);
02372 }
02373 break;
02374
02375 case OPR_RND:
02376 case OPR_TRUNC:
02377 case OPR_MOD:
02378 case OPR_REM:
02379 case OPR_ABS:
02380 Fail_FmtAssertion("unexpected complex op (%s)",
02381 OPCODE_name(WN_opcode(tree)));
02382
02383
02384 case OPR_INTRINSIC_OP:
02385 {
02386 INTRINSIC id = (INTRINSIC) WN_intrinsic(tree);
02387
02388 switch(id)
02389 {
02390 case INTRN_C4CONJG:
02391 case INTRN_C8CONJG:
02392 case INTRN_CQCONJG:
02393 {
02394 WN *iz;
02395
02396 lower_complex_expr(block, WN_actual(tree, 0), actions,
02397 realpart, &iz);
02398
02399 *imagpart = WN_Neg(type, iz);
02400
02401 WN_Delete(tree);
02402 }
02403 break;
02404
02405
02406
02407
02408
02409
02410
02411
02412
02413
02414
02415
02416
02417 default:
02418 if (INTRN_is_actual(WN_intrinsic(tree)))
02419 {
02420 tree = lower_intrinsic(block, tree, actions);
02421 }
02422 else
02423 {
02424 lower_complex_emulation(block, tree, actions, realpart, imagpart);
02425 }
02426 break;
02427 }
02428 }
02429 break;
02430
02431 case OPR_SELECT:
02432 {
02433 WN *r1, *i1;
02434 WN *r2, *i2;
02435 LEAF cond;
02436
02437 cond = Make_Leaf(block, WN_kid0(tree), WN_rtype(WN_kid0(tree)));
02438
02439 lower_complex_expr(block, WN_kid1(tree), actions, &r1, &i1);
02440 lower_complex_expr(block, WN_kid2(tree), actions, &r2, &i2);
02441
02442 *realpart = WN_Select(type, Load_Leaf(cond), r1, r2);
02443 *imagpart = WN_Select(type, Load_Leaf(cond), i1, i2);
02444 }
02445 break;
02446
02447 case OPR_PARM:
02448 lower_complex_expr(block, WN_kid0(tree), actions, realpart, imagpart);
02449 break;
02450 }
02451 }
02452
02453
02454
02455
02456
02457
02458
02459
02460
02461
02462
02463 static void lower_quad_expr(WN *block, WN *tree, LOWER_ACTIONS actions,
02464 WN **hipart, WN **lopart)
02465 {
02466 TYPE_ID type = MTYPE_F8;
02467
02468
02469 Is_True(OPCODE_is_expression(WN_opcode(tree)),
02470 ("expected expression node, not %s", OPCODE_name(WN_opcode(tree))));
02471 Is_True(actions & LOWER_QUAD, ("actions does not contain LOWER_QUAD"));
02472 Is_True((MTYPE_is_quad(WN_rtype(tree))),
02473 ("expected quad-type node, not %s", OPCODE_name(WN_opcode(tree))));
02474
02475
02476
02477
02478
02479
02480 tree = lower_expr(block, tree, actions);
02481
02482 switch (WN_operator(tree))
02483 {
02484 case OPR_LDID:
02485 {
02486
02487
02488
02489 TY_IDX beTY = MTYPE_To_TY(type);
02490 WN_OFFSET offset = WN_load_offset(tree);
02491
02492 *hipart = WN_Ldid(type, offset,
02493 coerceST(WN_st(tree), type), beTY);
02494
02495 *lopart = WN_Ldid(type,
02496 coerceOFFSET(tree, type, offset),
02497 coerceST(WN_st(tree), type),
02498 beTY);
02499
02500 lower_quad_maps(tree, *hipart, *lopart, actions);
02501 }
02502 break;
02503
02504 case OPR_ILOAD:
02505 {
02506 WN *addr;
02507 WN_OFFSET offset = WN_load_offset(tree);
02508 LEAF addrN;
02509
02510 addr = lower_expr(block, WN_kid0(tree), actions);
02511
02512 addrN = Make_Leaf(block, addr, Pointer_type);
02513
02514 *hipart = WN_Iload(type,
02515 offset,
02516 coerceTY(WN_ty(tree), type),
02517 Load_Leaf(addrN));
02518
02519 *lopart = WN_Iload(type,
02520 coerceOFFSET(tree, type, offset),
02521 coerceTY(WN_ty(tree), type),
02522 Load_Leaf(addrN));
02523
02524 lower_quad_maps(tree, *hipart, *lopart, actions);
02525 }
02526 break;
02527
02528 case OPR_CONST:
02529 {
02530 TCON val = Const_Val(tree);
02531
02532 *hipart = Make_Const( Extract_Quad_Hi(val));
02533 *lopart = Make_Const( Extract_Quad_Lo(val));
02534
02535 }
02536 break;
02537
02538 case OPR_PAREN:
02539 {
02540
02541
02542
02543 lower_quad_expr(block, WN_kid0(tree), actions, hipart, lopart);
02544
02545 *hipart = WN_Paren(type, *hipart);
02546 *lopart = WN_Paren(type, *lopart);
02547 }
02548 break;
02549
02550 case OPR_PARM:
02551 lower_quad_expr(block, WN_kid0(tree), actions, hipart, lopart);
02552 break;
02553
02554 case OPR_ILOADX:
02555 Is_True( FALSE, ("unexpected QUAD ILOADX"));
02556 break;
02557
02558 default:
02559 Is_True((FALSE),
02560 ("lower_quad_expr didn't %s", OPCODE_name(WN_opcode(tree))));
02561 }
02562 }
02563
02564
02565
02566
02567 static WN *WN_Coerce(TYPE_ID dst, WN *expr)
02568 {
02569 TYPE_ID src= WN_rtype(expr);
02570
02571 if (MTYPE_size_min(dst) == MTYPE_size_min(src))
02572 return expr;
02573
02574 return WN_Cvt(src, dst, expr);
02575 }
02576
02577
02578
02579
02580
02581
02582
02583
02584
02585
02586
02587
02588
02589
02590
02591
02592
02593
02594
02595
02596
02597 static WN *lower_linearize_array_addr(WN *block, WN *tree,
02598 LOWER_ACTIONS actions)
02599 {
02600 TYPE_ID rtype = WN_rtype(tree);
02601 WN *result, *product;
02602 INT32 n, i;
02603 BOOL is_non_contig=FALSE;
02604 WN_ESIZE element_size;
02605
02606 Is_True((WN_operator_is(tree,OPR_ARRAY)),
02607 ("expected ARRAY node, not %s", OPCODE_name(WN_opcode(tree))));
02608 Is_True(Action(LOWER_ARRAY), ("actions doesn't contain LOWER_ARRAY"));
02609 Is_True(WN_num_dim(tree) > 0, ("WN_num_dim of ARRAY node not > 0"));
02610
02611 n = WN_num_dim(tree);
02612 element_size = WN_element_size(tree);
02613 if (element_size < 0) {
02614 is_non_contig = TRUE;
02615 element_size = -element_size;
02616 }
02617
02618 if (is_non_contig)
02619 {
02620 WN *stride_mult;
02621
02622 result = WN_Coerce(rtype, WN_array_index(tree, n-1));
02623 stride_mult = WN_Coerce(rtype, WN_array_dim(tree, n-1));
02624 result = WN_Mpy(rtype,result,stride_mult);
02625
02626 for (i = n-2; i >= 0; i--) {
02627 product = WN_Coerce(rtype, WN_array_index(tree, i));
02628 stride_mult = WN_Coerce(rtype, WN_array_dim(tree, i));
02629 product = WN_Mpy(rtype,product,stride_mult);
02630 result = WN_Add(rtype,result,product);
02631 }
02632 }
02633 else
02634 {
02635
02636
02637
02638 result = WN_Coerce(rtype, WN_array_index(tree, n-1));
02639
02640
02641
02642
02643 for (i = n-2; i >= 0; i--)
02644 {
02645 INT32 m;
02646 WN *mpy;
02647
02648 product = WN_Coerce(rtype, lower_copy_tree(WN_array_dim(tree, n-1),
02649 actions));
02650 for (m=n-2; m>i; m--)
02651 {
02652 product = WN_Mpy(rtype,
02653 product,
02654 WN_Coerce(rtype, lower_copy_tree(WN_array_dim(tree, m),
02655 actions)));
02656 }
02657
02658 mpy = WN_Mpy(rtype,
02659 WN_Coerce(rtype, WN_array_index(tree,i)),
02660 product);
02661 result = WN_Add(rtype, result, mpy);
02662 }
02663 }
02664
02665
02666
02667
02668
02669 {
02670 WN *elm_size;
02671 TY_IDX arr_ty = Get_Type_From_ArrayOp(WN_array_base(tree));
02672 elm_size = WN_Intconst(rtype, element_size);
02673
02674 if (Type_Is_Shared_Ptr(arr_ty)) {
02675 SPTR_ACCUMULATION_STATE saved_acc_state = sptr_accumulation_state;
02676 SPTR_OFFSET_TERM_STACK *term_stack;
02677 if (sptr_accumulation_state != ARRAY_ACCUMULATION) {
02678 sptr_accumulation_state = ARRAY_ACCUMULATION;
02679 sptr_off_accumulation_stack.push(CXX_NEW(SPTR_OFFSET_TERM_STACK,Malloc_Mem_Pool));
02680 }
02681
02682 term_stack = sptr_off_accumulation_stack.top();
02683 WN *base = lower_expr(block, WN_array_base(tree), actions);
02684
02685 if (saved_acc_state == ARRAY_ACCUMULATION) {
02686 sptr_accumulation_state = NO_ACCUMULATION;
02687 result = lower_expr(block, result, actions);
02688 term_stack->push(result);
02689
02690 WN_Delete (tree);
02691 sptr_accumulation_state = saved_acc_state;
02692 return base;
02693 } else {
02694 sptr_accumulation_state = NO_ACCUMULATION;
02695 result = lower_expr(block, result, actions);
02696 term_stack->push(result);
02697
02698 result = Combine_Offset_Terms(*term_stack);
02699
02700
02701 sptr_accumulation_state = saved_acc_state;
02702 sptr_off_accumulation_stack.pop();
02703 CXX_DELETE(term_stack, Malloc_Mem_Pool);
02704
02705 result = WN_Create_Shared_Ptr_Arithmetic (base, result, OPR_ADD,
02706 Get_Type_Inner_Size(arr_ty),
02707 Get_Type_Block_Size(arr_ty),
02708 Get_Type_Block_Size(arr_ty) <= 1);
02709 }
02710 } else {
02711
02712 result = WN_Add(rtype,
02713 WN_array_base(tree),
02714 WN_Mpy(rtype, result, elm_size));
02715 result = lower_expr(block, result, actions);
02716 WN_Delete(tree);
02717 }
02718 }
02719
02720
02721
02722 return result;
02723 }
02724
02725
02726
02727
02728
02729
02730
02731
02732
02733
02734
02735
02736
02737 static WN *lower_unsigned_to_float(WN *block, WN *expr, TYPE_ID src,
02738 TYPE_ID dst, LOWER_ACTIONS actions)
02739 {
02740 LEAF srcNo, dstNo;
02741
02742
02743
02744
02745
02746
02747 if (src == MTYPE_U4 && !Slow_CVTDL)
02748 {
02749 BOOL simp= WN_Simplifier_Enable(FALSE);
02750 WN * r;
02751
02752 r = WN_Cvt(MTYPE_I8,dst,WN_Cvt(MTYPE_U4, MTYPE_U8, expr));
02753
02754 WN_Simplifier_Enable(simp);
02755 return (r);
02756 }
02757
02758
02759
02760
02761
02762
02763 srcNo = Make_Leaf(block, expr, src);
02764
02765
02766
02767
02768 {
02769 WN *ldid, *cvt;
02770
02771 ldid = Load_Leaf(srcNo);
02772
02773 cvt = WN_Cvt(MTYPE_complement(src), dst, ldid);
02774
02775 dstNo = Make_Leaf(block, cvt, dst);
02776 }
02777
02778
02779
02780
02781
02782
02783 {
02784 WN *rel, *add, *select;
02785
02786 rel = WN_LT(MTYPE_complement(src),
02787 Load_Leaf(srcNo),
02788 WN_Zerocon(MTYPE_complement(src)));
02789
02790 add = WN_Add(dst,
02791 Load_Leaf(dstNo),
02792 WN_ConstPowerOf2( dst, MTYPE_size_reg(src)));
02793
02794 select = WN_Select(dst, rel, add, Load_Leaf(dstNo));
02795 return select;
02796 }
02797 }
02798
02799
02800
02801
02802
02803
02804
02805
02806
02807
02808
02809
02810
02811 static WN *lower_float_to_unsigned(WN *block, WN *expr, TYPE_ID src,
02812 TYPE_ID dst, LOWER_ACTIONS actions)
02813 {
02814 LEAF srcNo;
02815 WN *trunc1,*r;
02816 WN *rel, *sub, *trunc2,*add;
02817
02818
02819
02820 if (dst == MTYPE_U4) {
02821 r = WN_Cvt(MTYPE_I8,dst,WN_Trunc(src,MTYPE_I8,expr));
02822 } else if (src==MTYPE_FQ) {
02823
02824
02825
02826
02827
02828
02829 srcNo = Make_Leaf(block, expr, src);
02830
02831
02832
02833
02834
02835
02836
02837
02838
02839
02840 trunc1 = WN_Trunc(src, MTYPE_complement(dst), Load_Leaf(srcNo));
02841
02842 sub = WN_Sub(src, Load_Leaf(srcNo),
02843 WN_ConstPowerOf2(src, MTYPE_size_reg(dst)-1));
02844
02845 trunc2 = WN_Trunc(src, MTYPE_complement(dst),sub);
02846
02847 add = WN_Add(dst,trunc2,WN_ConstPowerOf2(dst, MTYPE_size_reg(dst)-1));
02848
02849 rel = WN_LE(src,
02850 WN_ConstPowerOf2(src, MTYPE_size_reg(dst)-1),
02851 Load_Leaf(srcNo));
02852
02853 r = WN_Cselect(dst,rel,add,trunc1);
02854 } else {
02855
02856
02857
02858
02859
02860 srcNo = Make_Leaf(block, expr, src);
02861
02862
02863
02864
02865
02866
02867
02868
02869
02870
02871 trunc1 = WN_Trunc(src, MTYPE_complement(dst), Load_Leaf(srcNo));
02872
02873 sub = WN_Sub(src, Load_Leaf(srcNo),
02874 WN_ConstPowerOf2(src, MTYPE_size_reg(dst)));
02875
02876 trunc2 = WN_Floor(src, MTYPE_complement(dst),sub);
02877
02878 rel = WN_LE(src,
02879 WN_ConstPowerOf2(src, MTYPE_size_reg(dst)-1),
02880 Load_Leaf(srcNo));
02881
02882 r = WN_Cselect(dst,rel,trunc2,trunc1);
02883 }
02884 return (r);
02885 }
02886
02887
02888
02889
02890
02891
02892
02893
02894
02895
02896
02897
02898
02899 static WN *lower_cvt(WN *block, WN *tree, LOWER_ACTIONS actions)
02900 {
02901 WN *expr, *cvt;
02902 TYPE_ID dst = WN_rtype(tree);
02903 TYPE_ID src = WN_desc(tree);
02904
02905 expr = lower_expr(block, WN_kid0(tree), actions);
02906 WN_kid0(tree) = expr;
02907
02908 if ( Targ_Lower_Unsigned_To_Float
02909 && MTYPE_is_unsigned(src) && MTYPE_is_float(dst))
02910 {
02911 WN_Delete(tree);
02912
02913 cvt = lower_unsigned_to_float(block, expr, src, dst, actions);
02914
02915 return lower_expr(block, cvt, actions);
02916 }
02917 else if ( Targ_Lower_Float_To_Unsigned
02918 && MTYPE_is_float(src) && MTYPE_is_unsigned(dst))
02919 {
02920 WN_Delete(tree);
02921
02922 cvt = lower_float_to_unsigned(block, expr, src, dst, actions);
02923
02924 return lower_expr(block, cvt, actions);
02925 }
02926 else if ( OPERATOR_is_compare(WN_operator(expr))
02927 && WN_rtype(expr) == MTYPE_B
02928 && (MTYPE_is_integral(dst) && src == MTYPE_B))
02929 {
02930
02931
02932
02933 WN_Delete(tree);
02934
02935 WN_set_rtype(expr, dst);
02936
02937 return lower_expr(block, expr, actions);
02938 }
02939
02940 return tree;
02941 }
02942
02943
02944
02945
02946
02947
02948
02949
02950
02951
02952
02953 static WN *lower_nary_madd(WN *block, WN *tree, LOWER_ACTIONS actions)
02954 {
02955
02956 if (Enable_NaryExpr && Roundoff_Level >= ROUNDOFF_ASSOC)
02957 {
02958 TYPE_ID type = WN_rtype(tree);
02959
02960 tree = WN_ExprToNaryType(tree, type, 0);
02961
02962 if (WN_nary_add(tree))
02963 {
02964 INT32 i;
02965 BOOL found= TRUE;
02966
02967
02968
02969
02970
02971 while(found)
02972 {
02973 INT32 mpyI, exprI, nmpyI, narympyI;
02974 WN *mpy, *nmpy, *expr, *narympy;
02975 INT32 num_kids = WN_kid_count(tree);
02976
02977 found= FALSE;
02978 mpy = nmpy = expr = narympy = NULL;
02979 mpyI = exprI = nmpyI = narympyI = 0;
02980
02981 for(i = 0; i < num_kids; i++)
02982 {
02983 WN *actual= WN_actual(tree, i);
02984
02985 if (WN_operator_is(actual, OPR_MPY))
02986 {
02987 mpyI = i;
02988 mpy = actual;
02989 }
02990 else if (WN_operator_is(actual, OPR_NEG) &&
02991 WN_operator_is(WN_kid0(actual), OPR_MPY))
02992 {
02993 nmpyI = i;
02994 nmpy = WN_kid0(actual);
02995 }
02996 else if (WN_nary_mpy(actual) && WN_kid_count(actual) >= 2)
02997 {
02998 narympyI = i;
02999 narympy = actual;
03000 }
03001 else
03002 {
03003 exprI = i;
03004 expr = actual;
03005 }
03006
03007 if (mpy && expr)
03008 {
03009 WN_actual(tree, mpyI)= WN_Madd(type, expr, WN_kid0(mpy),
03010 WN_kid1(mpy));
03011 tree = WN_NaryDelete(tree, exprI);
03012 found= TRUE;
03013 break;
03014 }
03015 else if (nmpy && expr)
03016 {
03017 WN_actual(tree, nmpyI)= WN_Nmsub(type, expr, WN_kid0(nmpy),
03018 WN_kid1(nmpy));
03019 tree = WN_NaryDelete(tree, exprI);
03020 found= TRUE;
03021 break;
03022 }
03023 else if (narympy && expr)
03024 {
03025 mpy= WN_kid0(narympy);
03026 narympy= WN_NaryDelete(narympy, 0);
03027
03028 WN_actual(tree, narympyI)= WN_Madd(type, expr, mpy, narympy);
03029 tree = WN_NaryDelete(tree, exprI);
03030 found= TRUE;
03031 break;
03032 }
03033 }
03034 }
03035
03036
03037
03038 for(i = 0; i < WN_kid_count(tree); i++)
03039 {
03040 WN_actual(tree, i)= lower_madd(block, WN_actual(tree,i), actions);
03041 }
03042
03043 }
03044
03045 if (WN_nary_intrinsic(tree))
03046 {
03047 tree = WN_NaryToExpr(tree);
03048 }
03049 }
03050
03051 return tree;
03052 }
03053
03054
03055
03056
03057
03058
03059
03060
03061
03062
03063
03064
03065
03066 static WN *lower_madd(WN *block, WN *tree, LOWER_ACTIONS actions)
03067 {
03068 TYPE_ID type = WN_rtype(tree);
03069
03070
03071
03072
03073 switch (WN_operator(tree))
03074 {
03075 case OPR_NEG:
03076 {
03077 WN *child = WN_kid0(tree);
03078
03079 switch(WN_operator(child))
03080 {
03081 case OPR_MADD:
03082 WN_Delete(tree);
03083 return WN_Nmadd(type, WN_kid0(child), WN_kid1(child), WN_kid2(child));
03084
03085 case OPR_MSUB:
03086 WN_Delete(tree);
03087 return WN_Nmsub(type, WN_kid0(child), WN_kid1(child), WN_kid2(child));
03088
03089 case OPR_NMADD:
03090 WN_Delete(tree);
03091 return WN_Madd(type, WN_kid0(child), WN_kid1(child), WN_kid2(child));
03092
03093 case OPR_NMSUB:
03094 WN_Delete(tree);
03095 return WN_Msub(type, WN_kid0(child), WN_kid1(child), WN_kid2(child));
03096 }
03097 }
03098 break;
03099
03100 case OPR_ADD:
03101 {
03102 WN *l= WN_kid0(tree);
03103 WN *r= WN_kid1(tree);
03104
03105 if (WN_operator_is(l, OPR_MPY))
03106 {
03107 WN_Delete(tree);
03108 return WN_Madd(type, r, WN_kid0(l), WN_kid1(l));
03109 }
03110 else if (WN_operator_is(r, OPR_MPY))
03111 {
03112 WN_Delete(tree);
03113 return WN_Madd(type, l, WN_kid0(r), WN_kid1(r));
03114 }
03115 }
03116 break;
03117
03118 case OPR_SUB:
03119 {
03120 WN *l= WN_kid0(tree);
03121 WN *r= WN_kid1(tree);
03122
03123 if (WN_operator_is(l, OPR_MPY))
03124 {
03125 WN_Delete(tree);
03126 return WN_Msub(type, r, WN_kid0(l), WN_kid1(l));
03127 }
03128 else if (WN_operator_is(r, OPR_MPY))
03129 {
03130 WN_Delete(tree);
03131 return WN_Nmsub(type, l, WN_kid0(r), WN_kid1(r));
03132 }
03133 }
03134 break;
03135
03136 case OPR_MADD:
03137 {
03138 WN *neg= WN_kid0(tree);
03139
03140 if (WN_operator_is(neg, OPR_NEG))
03141 {
03142 WN *child= WN_kid0(neg);
03143
03144 WN_Delete(neg);
03145 return WN_Msub(type, child, WN_kid1(tree), WN_kid2(tree));
03146 }
03147 }
03148 break;
03149
03150 case OPR_MSUB:
03151 {
03152 WN *neg= WN_kid0(tree);
03153
03154 if (WN_operator_is(neg, OPR_NEG))
03155 {
03156 WN *child= WN_kid0(neg);
03157
03158 WN_Delete(neg);
03159 return WN_Madd(type, child, WN_kid1(tree), WN_kid2(tree));
03160 }
03161 }
03162 break;
03163
03164 case OPR_NMADD:
03165 {
03166 WN *neg= WN_kid0(tree);
03167
03168 if (WN_operator_is(neg, OPR_NEG))
03169 {
03170 WN *child= WN_kid0(neg);
03171
03172 WN_Delete(neg);
03173 return WN_Nmsub(type, child, WN_kid1(tree), WN_kid2(tree));
03174 }
03175 }
03176 break;
03177
03178 case OPR_NMSUB:
03179 {
03180 WN *neg= WN_kid0(tree);
03181
03182 if (WN_operator_is(neg, OPR_NEG))
03183 {
03184 WN *child= WN_kid0(neg);
03185
03186 WN_Delete(neg);
03187 return WN_Nmadd(type, child, WN_kid1(tree), WN_kid2(tree));
03188 }
03189 }
03190 break;
03191 }
03192
03193 return tree;
03194 }
03195
03196
03197
03198
03199
03200
03201
03202
03203
03204
03205
03206
03207
03208 static WN *lower_tree_height(WN *block, WN *wn, LOWER_ACTIONS actions)
03209 {
03210 OPCODE opcode = WN_opcode(wn);
03211 WN *l, *r;
03212
03213 if (NotAction(LOWER_TREEHEIGHT))
03214 return wn;
03215
03216 Is_True(WN_is_commutative(wn),("expected commutative op"));
03217
03218 l = WN_kid0(wn);
03219 r = WN_kid1(wn);
03220
03221
03222
03223
03224 if (opcode == WN_opcode(l) ^ opcode == WN_opcode(r))
03225
03226 {
03227 WN *wn1 = (opcode == WN_opcode(l)) ? l : r;
03228 WN *wn1X = (opcode == WN_opcode(l)) ? r : l;
03229
03230 WN *wn1_l = WN_kid0(wn1);
03231 WN *wn1_r = WN_kid1(wn1);
03232
03233 if (opcode == WN_opcode(wn1_l) ^ opcode == WN_opcode(wn1_r))
03234 {
03235
03236 WN *wn2 = (opcode == WN_opcode(wn1_l)) ? wn1_l : wn1_r;
03237 WN *wn2X = (opcode == WN_opcode(wn1_l)) ? wn1_r : wn1_l;
03238
03239
03240
03241 WN_kid0(wn1) = wn2X;
03242 WN_kid1(wn1) = wn1X;
03243
03244 WN_kid0(wn) = wn2;
03245 WN_kid1(wn) = wn1;
03246
03247 if (traceTreeHeight)
03248 {
03249 DevWarn("lower_tree_height: trace (%s) has been reassociated (line %d)",
03250 OPCODE_name(WN_opcode(wn)), Srcpos_To_Line(current_srcpos));
03251 }
03252 }
03253 }
03254 return wn;
03255 }
03256
03257
03258
03259
03260
03261
03262
03263
03264
03265
03266
03267
03268
03269
03270
03271
03272
03273 static WN *lower_recip(WN *block, WN *tree, LOWER_ACTIONS actions)
03274 {
03275 TYPE_ID type = WN_rtype(tree);
03276 WN *kid0 = WN_kid0(tree);
03277 WN *div = NULL;
03278
03279 Is_True(WN_operator_is(tree, OPR_RECIP), ("expected recip"));
03280 Is_True(MTYPE_float(type), ("expected float type"));
03281
03282
03283 if (Recip_Allowed == FALSE)
03284 {
03285 div = WN_Div(type, WN_Floatconst(type, 1.0), kid0);
03286 }
03287 else if (Action(LOWER_QUAD) && MTYPE_is_quad(type))
03288 {
03289 BOOL simp= WN_Simplifier_Enable(FALSE);
03290
03291 div = WN_Div(type, WN_Floatconst(type, 1.0), kid0);
03292
03293 WN_Simplifier_Enable(simp);
03294 }
03295
03296 if (div)
03297 {
03298 WN_Delete(tree);
03299 return div;
03300 }
03301
03302 return tree;
03303 }
03304
03305 static WN *lower_rsqrt(WN *block, WN *tree, LOWER_ACTIONS actions)
03306 {
03307 TYPE_ID type = WN_rtype(tree);
03308
03309 Is_True(WN_operator_is(tree, OPR_RSQRT), ("expected rsqrt"));
03310 Is_True(MTYPE_float(WN_rtype(tree)), ("expected float type"));
03311
03312 if (Rsqrt_Allowed == FALSE || MTYPE_is_quad(type))
03313 {
03314 WN *div;
03315
03316 div = WN_Div(type, WN_Floatconst(type, 1.0), WN_Sqrt(type, WN_kid0(tree)));
03317 WN_Delete(tree);
03318
03319 return div;
03320 }
03321 return tree;
03322 }
03323
03324
03325
03326
03327
03328
03329 static BOOL Symbol_Is_Base_Register (ST *sym)
03330 {
03331 return ((ST_class(sym) == CLASS_BLOCK && STB_is_basereg(sym)) ||
03332 (ST_class(sym) == CLASS_VAR && ST_gprel(sym)));
03333 }
03334
03335
03336
03337
03338
03339
03340
03341
03342
03343
03344
03345
03346 static WN *lower_split_sym_addrs(WN *tree, INT64 offset, LOWER_ACTIONS actions)
03347 {
03348 ST *sym = WN_st(tree);
03349 ST *base = ST_base(sym);
03350 INT64 newoffset = 0;
03351
03352 if (traceSplitSymOff)
03353 return NULL;
03354
03355 switch(ST_class(sym))
03356 {
03357 case CLASS_CONST:
03358
03359
03360
03361
03362 if (PIC_NONSHARED && (ST_size(sym) > Max_Sdata_Elt_Size))
03363 {
03364 Allocate_Object(sym);
03365 Base_Symbol_And_Offset_For_Addressing(sym, offset, &base, &newoffset);
03366 return lower_base_reference(tree, base, newoffset, actions);
03367 }
03368 return NULL;
03369
03370 case CLASS_PREG:
03371 return NULL;
03372
03373 case CLASS_FUNC:
03374 if (PIC_SHARED && ST_is_preemptible(sym))
03375 {
03376 return NULL;
03377 }
03378 break;
03379
03380 case CLASS_BLOCK:
03381 case CLASS_VAR:
03382 Base_Symbol_And_Offset_For_Addressing(sym, offset, &base, &newoffset);
03383
03384 if (ST_is_uplevelTemp(sym))
03385 {
03386 return NULL;
03387 }
03388 if (ST_assigned_to_dedicated_preg(sym))
03389 {
03390 return NULL;
03391 }
03392
03393
03394
03395
03396 if (WN_operator_is(tree, OPR_LDA) && base == sym)
03397 return NULL;
03398
03399 switch(ST_sclass(sym))
03400 {
03401 case SCLASS_REG:
03402 case SCLASS_TEXT:
03403 return NULL;
03404
03405 case SCLASS_FORMAL_REF:
03406
03407
03408
03409
03410 if (base != sym)
03411 {
03412 base = sym;
03413 }
03414 break;
03415
03416 case SCLASS_FORMAL:
03417
03418
03419
03420
03421 return NULL;
03422
03423 case SCLASS_AUTO:
03424
03425
03426
03427
03428
03429
03430
03431
03432
03433
03434 #if 0
03435 if (Uses_Small_Offset(sym, offset))
03436 break;
03437 #endif
03438 return NULL;
03439
03440 case SCLASS_EXTERN:
03441
03442
03443
03444
03445 if (ST_is_weak_symbol(sym))
03446 return NULL;
03447 break;
03448
03449 case SCLASS_COMMON:
03450
03451
03452
03453
03454
03455
03456
03457
03458
03459
03460
03461
03462 sym = base;
03463 break;
03464
03465 case SCLASS_PSTATIC:
03466 case SCLASS_UGLOBAL:
03467 case SCLASS_DGLOBAL:
03468 case SCLASS_FSTATIC:
03469
03470
03471
03472
03473
03474 break;
03475
03476 default:
03477 return NULL;
03478 }
03479
03480 if (ST_gprel(sym))
03481 {
03482 return NULL;
03483 }
03484 tree = lower_base_reference(tree, base, newoffset, actions);
03485 return tree;
03486
03487 default:
03488 return NULL;
03489 }
03490
03491 return NULL;
03492 }
03493
03494
03495
03496
03497
03498
03499
03500
03501
03502
03503
03504
03505 static WN *lower_uplevel_reference(WN *tree, INT64 offset,
03506 LOWER_ACTIONS actions)
03507 {
03508 ST *sym = WN_st(tree);
03509 ST *base;
03510 INT64 newoffset;
03511
03512 Is_True(ST_is_uplevelTemp(sym), ("expected uplevel %s",ST_name(sym)));
03513
03514 Base_Symbol_And_Offset_For_Addressing(sym, offset, &base, &newoffset);
03515 base = Find_Slink_For_ST(sym);
03516
03517 tree = lower_dereference(tree, newoffset, base, 0, actions);
03518 return tree;
03519 }
03520
03521
03522
03523
03524
03525
03526
03527
03528
03529
03530
03531
03532
03533
03534 static WN *lower_formal_ref(WN *tree, INT64 offset, ST *base,
03535 LOWER_ACTIONS actions)
03536 {
03537 PREG_NUM preg;
03538
03539 switch(ST_sclass(base))
03540 {
03541 case SCLASS_FORMAL_REF:
03542 base = Get_ST_formal_ref_base(base);
03543 if (preg = Get_ST_formal_preg_num(base))
03544 {
03545 Is_True((ST_has_nested_ref(WN_st(tree))==FALSE),
03546 ("lower_formal_ref: cannot use preg for nested ref %s",
03547 ST_name(WN_st(tree))));
03548 base = MTYPE_To_PREG(TY_mtype(Ty_Table[ST_type(base)]));
03549 }
03550 return lower_dereference(tree, offset, base, preg, actions);
03551
03552 case SCLASS_FORMAL:
03553 if (preg= Get_ST_formal_preg_num(base))
03554 {
03555 base = MTYPE_To_PREG(TY_mtype(Ty_Table[ST_type(base)]));
03556 tree = lower_base_register(tree, base, preg, actions);
03557 return tree;
03558 }
03559 break;
03560 }
03561 return NULL;
03562 }
03563
03564
03565
03566
03567
03568
03569
03570
03571
03572
03573
03574
03575
03576
03577 static WN *lower_base_register(WN *tree, ST *base, INT64 offset,
03578 LOWER_ACTIONS actions)
03579 {
03580 Is_True(WN_st(tree) != base, ("lower_base_register(): possible recursion"));
03581
03582 switch (WN_operator(tree))
03583 {
03584 case OPR_LDA:
03585
03586
03587
03588
03589
03590
03591 WN_st_idx(tree) = ST_st_idx(base);
03592 WN_lda_offset(tree) = mem_offset_hi(offset);
03593 return tree;
03594
03595 case OPR_LDID:
03596
03597
03598
03599
03600
03601 WN_st_idx(tree) = ST_st_idx(base);
03602 WN_load_offset(tree) = offset;
03603 break;
03604
03605 case OPR_STID:
03606
03607
03608
03609
03610
03611 WN_st_idx(tree) = ST_st_idx(base);
03612 WN_store_offset(tree) = offset;
03613 break;
03614
03615 default:
03616 Is_True(FALSE,("expected lda/ldid/stid"));
03617 return NULL;
03618 }
03619
03620 return tree;
03621 }
03622
03623
03624
03625
03626 static void
03627 lower_field_id (WN* tree)
03628 {
03629 OPERATOR opr = WN_operator(tree);
03630
03631 Is_True (opr == OPR_LDID || opr == OPR_STID || opr == OPR_MLOAD ||
03632 opr == OPR_MSTORE, ("expecting LDID or STID nodes"));
03633
03634 if (WN_field_id (tree) == 0)
03635 return;
03636
03637 BOOL is_ptr_type = (opr == OPR_MLOAD || opr == OPR_MSTORE);
03638
03639 TY_IDX ty_idx = is_ptr_type ? TY_pointed (WN_ty (tree)) : WN_ty (tree);
03640
03641 Is_True (TY_kind (ty_idx) == KIND_STRUCT,
03642 ("non-zero field id must have KIND_STRUCT"));
03643
03644 UINT field_id = 0;
03645 FLD_HANDLE fld = FLD_get_to_field (ty_idx, WN_field_id (tree), field_id);
03646
03647 Is_True (! fld.Is_Null (), ("invalid bit-field ID for %s",
03648 OPERATOR_name(opr)));
03649
03650 WN_set_ty (tree, (is_ptr_type ? Make_Pointer_Type (FLD_type (fld)) :
03651 FLD_type (fld)));
03652 WN_set_field_id (tree, 0);
03653 return;
03654 }
03655
03656
03657
03658
03659
03660
03661
03662
03663
03664
03665
03666 static WN *lower_base_reference(WN *tree, ST *base, INT64 offset,
03667 LOWER_ACTIONS actions)
03668 {
03669 WN *addr, *wn;
03670
03671 switch (WN_operator(tree))
03672 {
03673 case OPR_LDA:
03674
03675
03676
03677
03678
03679
03680
03681
03682
03683
03684
03685
03686
03687
03688
03689 WN_st_idx(tree) = ST_st_idx(base);
03690
03691 if (mem_offset_2GB(offset))
03692 {
03693 addr = WN_Add(Pointer_type, tree, WN_Intconst(Pointer_type, offset));
03694 WN_lda_offset(tree)= 0;
03695 return addr;
03696 }
03697 else if (Action(LOWER_SPLIT_CONST_OFFSETS) &&
03698 mem_offset_lo(offset))
03699 {
03700
03701 BOOL simp= WN_Simplifier_Enable(FALSE);
03702
03703 addr = WN_Add(Pointer_type,
03704 tree,
03705 WN_Intconst(Pointer_type, mem_offset_lo(offset)));
03706 WN_lda_offset(tree)= mem_offset_hi(offset);
03707
03708 WN_Simplifier_Enable(simp);
03709 return addr;
03710 }
03711 WN_lda_offset(tree)= offset;
03712 return tree;
03713
03714 case OPR_LDID:
03715 case OPR_STID:
03716 case OPR_LDBITS:
03717 case OPR_STBITS:
03718
03719
03720
03721
03722
03723
03724
03725
03726
03727
03728
03729
03730 addr = WN_Lda(Pointer_type, 0, base);
03731
03732 if (mem_offset_2GB(offset))
03733 {
03734 addr = WN_Add(Pointer_type, addr, WN_Intconst(Pointer_type, offset));
03735 offset = 0;
03736 }
03737 if (Action(LOWER_SPLIT_CONST_OFFSETS) && mem_offset_must_be_split(offset))
03738 {
03739 WN_lda_offset(addr) = mem_offset_hi(offset);
03740 offset = mem_offset_lo(offset);
03741 }
03742 break;
03743
03744 default:
03745 Is_True(FALSE,("expected lda/ldid/stid"));
03746 return NULL;
03747 }
03748
03749 switch (WN_operator(tree))
03750 {
03751 case OPR_LDID:
03752
03753
03754
03755
03756
03757 if (WN_field_id (tree) != 0)
03758 lower_field_id (tree);
03759
03760 wn = WN_RIload(WN_rtype(tree), WN_desc(tree), offset, WN_ty(tree),
03761 addr);
03762 break;
03763 case OPR_LDBITS:
03764 wn = WN_RIload(WN_rtype(tree), WN_desc(tree), offset, WN_ty(tree),
03765 addr);
03766 WN_set_operator(wn, OPR_ILDBITS);
03767 WN_set_bit_offset_size(wn, WN_bit_offset(tree), WN_bit_size(tree));
03768 break;
03769
03770 case OPR_STID:
03771
03772
03773
03774
03775
03776
03777 if (WN_field_id (tree) != 0)
03778 lower_field_id (tree);
03779
03780 wn = WN_Istore(WN_desc(tree),
03781 offset,
03782
03783
03784
03785
03786
03787
03788
03789
03790 Make_Pointer_Type(WN_ty(tree)),
03791 addr,
03792 WN_kid0(tree));
03793 WN_Set_Linenum(wn, WN_Get_Linenum(tree));
03794 break;
03795 case OPR_STBITS:
03796 wn = WN_Istore(WN_desc(tree),
03797 offset,
03798 Make_Pointer_Type(WN_ty(tree)),
03799 addr,
03800 WN_kid0(tree));
03801 WN_set_operator(wn, OPR_ISTBITS);
03802 WN_set_bit_offset_size(wn, WN_bit_offset(tree), WN_bit_size(tree));
03803 WN_Set_Linenum(wn, WN_Get_Linenum(tree));
03804 break;
03805 }
03806
03807 lower_copy_maps(tree, wn, actions);
03808 WN_Delete(tree);
03809
03810 return wn;
03811 }
03812
03813
03814
03815
03816
03817
03818
03819
03820
03821
03822
03823
03824
03825
03826
03827
03828
03829 static WN
03830 *lower_dereference(WN *tree, INT64 offset, ST *base, PREG_NUM preg,
03831 LOWER_ACTIONS actions)
03832 {
03833 WN *addr, *deref;
03834 TY_IDX addr_ty;
03835
03836 switch (WN_operator(tree))
03837 {
03838 case OPR_LDA:
03839
03840
03841
03842
03843
03844
03845
03846
03847 deref = WN_Ldid(Pointer_type, preg, base, WN_ty(tree));
03848 addr = WN_Add(Pointer_type, deref, WN_Intconst(Pointer_type, offset));
03849 return addr;
03850
03851 case OPR_LDID:
03852 case OPR_STID:
03853
03854
03855
03856
03857 addr_ty = Make_Pointer_Type(WN_ty(tree));
03858 addr = WN_Ldid(Pointer_type, preg, base, addr_ty);
03859
03860 if (mem_offset_2GB(offset))
03861 {
03862 addr = WN_Add(Pointer_type, addr, WN_Intconst(Pointer_type, offset));
03863 offset = 0;
03864 }
03865 break;
03866
03867 default:
03868 Is_True(FALSE,("expected lda/ldid/stid"));
03869 return NULL;
03870 }
03871
03872 switch (WN_operator(tree))
03873 {
03874 case OPR_LDID:
03875
03876
03877
03878
03879
03880
03881 deref = WN_RIload(WN_rtype(tree), WN_desc(tree), offset, WN_ty(tree), addr);
03882 break;
03883
03884 case OPR_STID:
03885
03886
03887
03888
03889
03890
03891 deref = WN_Istore(WN_desc(tree), offset, addr_ty, addr, WN_kid0(tree));
03892 WN_Set_Linenum(deref, WN_Get_Linenum(tree));
03893 break;
03894 }
03895
03896 lower_copy_maps(tree, deref, actions);
03897 WN_Delete(tree);
03898
03899 return deref;
03900 }
03901
03902
03903
03904
03905
03906
03907
03908
03909
03910
03911 static WN *lower_return_ldid(WN *block, WN *tree, LOWER_ACTIONS actions)
03912 {
03913 TY_IDX ty_idx = WN_ty(tree);
03914 TY& ty = Ty_Table[ty_idx];
03915 TYPE_ID mtype = TY_mtype (ty);
03916
03917 Is_True((WN_operator(tree) == OPR_LDID),
03918 ("expected LDID node, not %s", OPCODE_name(WN_opcode(tree))));
03919
03920 switch (mtype) {
03921
03922 case MTYPE_I8:
03923 case MTYPE_U8:
03924 WN_st_idx(tree) = ST_st_idx(MTYPE_To_PREG(mtype));
03925 WN_load_offset(tree) = First_Int_Preg_Return_Offset;
03926 return tree;
03927
03928 case MTYPE_I1:
03929 case MTYPE_I2:
03930 case MTYPE_I4:
03931 case MTYPE_U1:
03932 case MTYPE_U2:
03933 case MTYPE_U4:
03934 WN_st_idx(tree) = ST_st_idx(Int_Preg);
03935 WN_load_offset(tree) = First_Int_Preg_Return_Offset;
03936 return tree;
03937
03938 case MTYPE_F4:
03939 case MTYPE_F8:
03940 case MTYPE_FQ:
03941 case MTYPE_C4:
03942 case MTYPE_C8:
03943 case MTYPE_CQ:
03944 WN_st_idx(tree) = ST_st_idx(Float_Preg);
03945 WN_load_offset(tree) = First_Float_Preg_Return_Offset;
03946 return tree;
03947
03948 case MTYPE_M:
03949 Fail_FmtAssertion ("MLDID of Return_Val_Preg not allowed in middle"
03950 " of expression");
03951
03952 default:
03953 Fail_FmtAssertion ("Unexpected type in lower_return_ldid");
03954
03955 }
03956 }
03957
03958
03959 static TY_IDX
03960 get_field_type (TY_IDX struct_type, UINT field_id)
03961 {
03962 Is_True (TY_kind (struct_type) == KIND_STRUCT, ("expecting KIND_STRUCT"));
03963 UINT cur_field_id = 0;
03964 FLD_HANDLE fld = FLD_get_to_field (struct_type, field_id, cur_field_id);
03965 Is_True (! fld.Is_Null(), ("Invalid field id %d for type 0x%x",
03966 field_id, struct_type));
03967 return FLD_type (fld);
03968 }
03969
03970
03971
03972
03973
03974
03975
03976
03977
03978
03979
03980
03981 static WN *lower_mldid(WN *block, WN *tree, LOWER_ACTIONS actions)
03982 {
03983 TY_IDX ty_idx = WN_ty(tree);
03984 TY_IDX fld_idx = WN_field_id(tree) == 0 ? 0 :
03985 get_field_type (ty_idx, WN_field_id (tree));
03986 TY_IDX pty_idx;
03987
03988 UINT64 size = fld_idx == 0 ? TY_size(ty_idx) : TY_size(fld_idx);
03989
03990 if(Action(LOWER_UPC_MFIELD) && WN_field_id(tree) && Type_Is_Shared_Ptr(fld_idx))
03991 size = TY_size(TY_To_Sptr_Idx(fld_idx));
03992
03993 WN* wn;
03994 WN* awn;
03995 WN* swn;
03996
03997 Is_True((WN_opcode(tree) == OPC_MMLDID),
03998 ("expected mldid node, not %s", OPCODE_name(WN_opcode(tree))));
03999
04000 pty_idx = Make_Pointer_Type (ty_idx, FALSE);
04001
04002 swn = WN_CreateIntconst(OPC_U4INTCONST, size);
04003 awn = WN_CreateLda(OPR_LDA, Pointer_Mtype, MTYPE_V, WN_load_offset(tree),
04004 pty_idx, WN_st(tree));
04005 wn = WN_CreateMload(0, pty_idx, awn, swn);
04006 WN_set_field_id(wn, WN_field_id(tree));
04007 wn = lower_expr(block, wn, actions);
04008
04009 WN_Delete(tree);
04010 return wn;
04011 }
04012
04013
04014
04015
04016
04017
04018
04019
04020
04021
04022 static WN *lower_miload(WN *block, WN *tree, LOWER_ACTIONS actions)
04023 {
04024 TY_IDX ty_idx = WN_field_id (tree) == 0 ?
04025 WN_ty(tree) :
04026 get_field_type (WN_ty (tree), WN_field_id (tree));
04027 TY_IDX pty_idx = WN_load_addr_ty(tree);
04028 UINT64 size = TY_size(Ty_Table[ty_idx]);
04029 if(Action(LOWER_UPC_MFIELD) && WN_field_id(tree) && Type_Is_Shared_Ptr(ty_idx)) {
04030 pty_idx = Make_Pointer_Type(WN_ty(tree));
04031 size = TY_size(TY_To_Sptr_Idx(ty_idx));
04032 }
04033 WN* wn;
04034 WN* swn;
04035
04036 Is_True((WN_opcode(tree) == OPC_MMILOAD),
04037 ("expected miload node, not %s", OPCODE_name(WN_opcode(tree))));
04038
04039 swn = WN_CreateIntconst (OPC_U4INTCONST, size);
04040 wn = WN_CreateMload (WN_offset(tree), pty_idx, WN_kid0(tree), swn);
04041 WN_set_field_id(wn, WN_field_id(tree));
04042
04043
04044 wn = lower_expr (block, wn, actions);
04045
04046 WN_Delete (tree);
04047 return wn;
04048 }
04049
04050
04051
04052
04053
04054
04055
04056
04057 static WN*
04058 lower_load_bits (WN* block, WN* wn, LOWER_ACTIONS actions)
04059 {
04060 Is_True (WN_operator (wn) == OPR_LDBITS || WN_operator (wn) == OPR_ILDBITS,
04061 ("expected LDBITS or ILDBITS, not %s",
04062 OPERATOR_name(WN_operator(wn))));
04063
04064 TYPE_ID rtype = WN_rtype (wn);
04065 TYPE_ID desc = WN_desc (wn);
04066 INT delta = MTYPE_bit_size(rtype) - MTYPE_bit_size(desc);
04067 if (delta < 0) {
04068 rtype = Mtype_TransferSize (desc, rtype);
04069 delta = 0;
04070 }
04071
04072 WN* tree = wn;
04073
04074 INT bit_size = WN_bit_size (wn);
04075 INT bit_ofst = Target_Byte_Sex == BIG_ENDIAN ?
04076 WN_bit_offset (wn) :
04077 MTYPE_bit_size(desc) - bit_size - WN_bit_offset (wn);
04078 BOOL bits_signed = MTYPE_signed(rtype);
04079
04080 if (bit_ofst == 0)
04081 bit_size += delta;
04082 else {
04083 bit_ofst += delta;
04084 if (bits_signed)
04085 tree = WN_Shl (rtype, tree, WN_Intconst (MTYPE_I4, bit_ofst));
04086 else {
04087 INT shift_count = 64 - (MTYPE_bit_size(rtype) - bit_ofst);
04088 mUINT64 mask = (~(mUINT64)0) >> shift_count;
04089 tree = WN_Band (rtype, tree,
04090 WN_Intconst (Mtype_TransferSign (MTYPE_U4, rtype),
04091 mask));
04092 bit_size += bit_ofst;
04093 }
04094 }
04095
04096 INT right_shift = MTYPE_bit_size(rtype) - bit_size;
04097
04098 if (right_shift > 0) {
04099 OPERATOR opr = bits_signed ? OPR_ASHR : OPR_LSHR;
04100 tree = WN_Binary (opr, rtype, tree, WN_Intconst (MTYPE_I4, right_shift));
04101 }
04102
04103 TYPE_ID orig_rtype = WN_rtype (wn);
04104
04105 WN_set_rtype (wn, rtype);
04106 WN_set_bit_offset_size (wn, 0, 0);
04107 WN_set_operator (wn, WN_operator (wn) == OPR_LDBITS ? OPR_LDID : OPR_ILOAD);
04108
04109 if (rtype != orig_rtype)
04110 tree = WN_Type_Conversion (tree, orig_rtype);
04111
04112 return lower_expr (block, tree, actions);
04113 }
04114
04115
04116
04117
04118
04119
04120
04121
04122
04123 static WN*
04124 lower_store_bits (WN* block, WN* wn, LOWER_ACTIONS actions)
04125 {
04126 Is_True (WN_operator (wn) == OPR_STBITS || WN_operator (wn) == OPR_ISTBITS,
04127 ("expected STBITS or ISTBITS, not %s",
04128 OPERATOR_name (WN_operator (wn))));
04129
04130 INT bit_size = WN_bit_size (wn);
04131 INT bit_ofst = WN_bit_offset (wn);
04132
04133 WN* orig_value;
04134
04135 if (WN_operator (wn) == OPR_ISTBITS) {
04136 WN* load_address = lower_copy_tree (WN_kid1 (wn), actions);
04137 orig_value = WN_Iload (Mtype_TransferSign (MTYPE_U4, WN_desc (wn)),
04138 WN_offset (wn), WN_ty (wn), load_address, 0);
04139 } else
04140 orig_value = WN_Ldid (Mtype_TransferSign (MTYPE_U4, WN_desc (wn)),
04141 WN_offset (wn), WN_st_idx (wn), WN_ty (wn), 0);
04142
04143 TYPE_ID cmp_type = WN_rtype (orig_value);
04144
04145 INT shift = Target_Byte_Sex == BIG_ENDIAN ?
04146 MTYPE_bit_size (WN_desc (wn)) - bit_ofst - bit_size :
04147 bit_ofst;
04148 mUINT64 mask = ~((~((mUINT64)0) >> (64 - bit_size)) << shift);
04149 orig_value = WN_Band (cmp_type, orig_value, WN_Intconst (cmp_type, mask));
04150
04151 WN* new_value = WN_kid0 (wn);
04152
04153
04154 if (bit_size > MTYPE_bit_size (WN_rtype (new_value)))
04155 new_value =
04156 WN_CreateCvtl (OPR_CVTL,
04157 Mtype_TransferSign (WN_rtype (new_value), cmp_type),
04158 WN_rtype (new_value),
04159 MTYPE_bit_size (WN_rtype (new_value)),
04160 new_value);
04161
04162
04163 mask = ~((mUINT64)0) >> (64 - bit_size);
04164 new_value =
04165 WN_Band (cmp_type, new_value,
04166 WN_Intconst (Mtype_TransferSize (WN_rtype (new_value), cmp_type),
04167 mask));
04168
04169
04170 if (shift > 0)
04171 new_value = WN_Shl (cmp_type, new_value, WN_Intconst (cmp_type, shift));
04172
04173
04174 new_value = WN_Bior (cmp_type, orig_value, new_value);
04175
04176 WN_kid0 (wn) = new_value;
04177 WN_set_bit_offset_size (wn, 0, 0);
04178 WN_set_operator (wn, WN_operator(wn) == OPR_STBITS ? OPR_STID : OPR_ISTORE);
04179
04180 return lower_store (block, wn, actions);
04181 }
04182
04183 #if 0
04184
04185
04186
04187
04188
04189
04190
04191
04192
04193 static bool check_unaligned(INT required_alignment, INT offset, INT ty_align)
04194 {
04195 if (required_alignment <= 1)
04196 return FALSE;
04197 INT align = ty_align;
04198 if (offset) {
04199 INT offset_align = offset % required_alignment;
04200 if (offset_align)
04201 align = MIN(align, offset_align);
04202 }
04203 return align < required_alignment;
04204 }
04205 #endif
04206
04207
04208
04209
04210
04211
04212
04213
04214 FLD_HANDLE
04215 FLD_And_Offset_From_Field_Id (TY_IDX struct_ty_idx,
04216 UINT field_id,
04217 UINT& cur_field_id,
04218 UINT64& offset)
04219 {
04220 FLD_ITER fld_iter = Make_fld_iter(TY_fld(struct_ty_idx));
04221 do {
04222 FLD_HANDLE fld(fld_iter);
04223 cur_field_id++;
04224 if (cur_field_id == field_id) {
04225 offset += FLD_ofst(fld);
04226 return fld;
04227 }
04228 if (TY_kind(FLD_type(fld)) == KIND_STRUCT &&
04229 TY_fld(FLD_type(fld)) != FLD_HANDLE()) {
04230 UINT64 nested_offset = offset + FLD_ofst(fld);
04231 fld = FLD_And_Offset_From_Field_Id(FLD_type(fld), field_id,
04232 cur_field_id, nested_offset);
04233 if (cur_field_id == field_id) {
04234 offset = nested_offset;
04235 return fld;
04236 }
04237 }
04238 } while (!FLD_last_field(fld_iter++));
04239
04240 return FLD_HANDLE();
04241 }
04242
04243
04244
04245
04246
04247
04248
04249
04250
04251
04252
04253 static void lower_bit_field_id(WN *wn)
04254 {
04255 TY_IDX struct_ty_idx;
04256 TY_IDX ty_idx;
04257 TYPE_ID rtype;
04258 OPERATOR opr = WN_operator(wn);
04259 OPERATOR new_opr;
04260 BOOL indirect;
04261 if (opr == OPR_LDID || opr == OPR_STID) {
04262 ST_IDX st_idx = WN_st_idx(wn);
04263 struct_ty_idx = WN_ty(wn);
04264 new_opr = (opr == OPR_LDID) ? OPR_LDBITS : OPR_STBITS;
04265 indirect = FALSE;
04266 }
04267 else {
04268 if (WN_operator(wn) == OPR_ILOAD) {
04269 ty_idx = WN_load_addr_ty(wn);
04270 new_opr = OPR_ILDBITS;
04271 }
04272 else {
04273 ty_idx = WN_ty(wn);
04274 new_opr = OPR_ISTBITS;
04275 }
04276 Is_True(TY_kind(ty_idx) == KIND_POINTER,
04277 ("addr ty not pointer type for %s", OPERATOR_name(opr)));
04278 struct_ty_idx = TY_pointed(ty_idx);
04279 indirect = TRUE;
04280 }
04281 Is_True(TY_kind(struct_ty_idx) == KIND_STRUCT,
04282 ("struct type not associated with bit-field access for %s", OPERATOR_name(opr)));
04283 UINT cur_field_id = 0;
04284 UINT64 field_offset = 0;
04285 FLD_HANDLE fld = FLD_And_Offset_From_Field_Id(struct_ty_idx,
04286 WN_field_id(wn),
04287 cur_field_id,
04288 field_offset);
04289 Is_True(! fld.Is_Null(),
04290 ("invalid bit-field ID for %s", OPERATOR_name(opr)));
04291 TY_IDX fld_ty_idx = FLD_type(fld);
04292 WN_set_ty (wn, (opr == OPR_ISTORE ?
04293 Make_Pointer_Type (fld_ty_idx, FALSE) :
04294 fld_ty_idx));
04295
04296 Is_True(FLD_is_bit_field(fld),
04297 ("non-bit-field associated with bit-field access for %s", OPERATOR_name(opr)));
04298
04299
04300 UINT bytes_accessed = TY_size(fld_ty_idx);
04301 if (OPERATOR_is_store(new_opr))
04302 rtype = TY_mtype(fld_ty_idx);
04303 else rtype = WN_rtype(wn);
04304 INT ofst = field_offset;
04305 #if 0
04306 BOOL unaligned_field = check_unaligned(bytes_accessed * 8, ofst,
04307 TY_align(struct_ty_idx));
04308 #endif
04309 if (ofst >= 0)
04310 ofst = ofst / bytes_accessed * bytes_accessed;
04311 else ofst = (ofst - bytes_accessed + 1) / bytes_accessed * bytes_accessed;
04312 UINT bsize = FLD_bsize(fld);
04313 UINT bofst = FLD_bofst(fld) + (field_offset-ofst) * 8;
04314 if ((bofst + bsize) > (bytes_accessed * 8)) {
04315 if (bytes_accessed == MTYPE_byte_size(Max_Int_Mtype)) {
04316
04317 ofst = field_offset;
04318 bofst = FLD_bofst(fld);
04319 }
04320 else bytes_accessed *= 2;
04321 }
04322 WN_load_offset(wn) = WN_load_offset(wn) + ofst;
04323
04324 if ((bsize & 7) == 0 &&
04325 (bytes_accessed * 8 % bsize) == 0 &&
04326 (bofst % bsize) == 0) {
04327
04328 WN_set_field_id(wn, 0);
04329 WN_set_desc(wn, Mtype_AlignmentClass(bsize >> 3, MTYPE_type_class(rtype)));
04330 WN_load_offset(wn) = WN_load_offset(wn) + (bofst >> 3);
04331 }
04332 else {
04333 #if defined(TARG_MIPS) || defined(TARG_IA32)
04334 if ((indirect || WN_class(wn) != CLASS_PREG) &&
04335 bofst % 8 == 0 &&
04336 compute_offset_alignment(bytes_accessed*8, bofst) >= bsize) {
04337
04338 WN_load_offset(wn) = WN_load_offset(wn) + (bofst >> 3);
04339 bytes_accessed = compute_offset_alignment(bytes_accessed, bofst >> 3);
04340 bofst = 0;
04341 }
04342 #endif
04343 WN_set_operator(wn, new_opr);
04344 WN_set_desc(wn, Mtype_AlignmentClass(bytes_accessed, MTYPE_type_class(rtype)));
04345 if (OPERATOR_is_load(new_opr) &&
04346 MTYPE_byte_size(WN_rtype(wn)) < bytes_accessed)
04347 WN_set_rtype(wn, WN_desc(wn));
04348 WN_set_bit_offset_size(wn, bofst, bsize);
04349 }
04350 }
04351
04352 static void lower_trapuv_alloca (WN *block, WN *tree, LOWER_ACTIONS actions)
04353 {
04354 WN *size = WN_kid0(tree);
04355 WN *con = WN_UVConst(WN_rtype(size));
04356 WN *mstore;
04357 if (WN_operator(size) == OPR_INTCONST && WN_const_val(size) == 0)
04358 return;
04359
04360 mstore = WN_CreateMstore(0,
04361 Make_Pointer_Type(MTYPE_To_TY(WN_rtype(size)),TRUE),
04362 con,
04363 WN_LdidPreg(Pointer_type, Stack_Pointer_Preg_Offset),
04364 WN_COPY_Tree(size) );
04365 mstore = lower_store (block, mstore, actions);
04366 WN_INSERT_BlockLast(block, mstore);
04367 }
04368
04369
04370 inline BOOL Should_Call_Divide(TYPE_ID rtype)
04371 {
04372 #if defined(TARG_IA64)
04373 if (!OPT_Inline_Divide) {
04374 if ( rtype == MTYPE_I8 || rtype == MTYPE_U8
04375 || rtype == MTYPE_I4 || rtype == MTYPE_U4
04376 || rtype == MTYPE_F4 || rtype == MTYPE_F8) return TRUE;
04377 }
04378 #elif defined(EMULATE_LONGLONG)
04379 if (rtype == MTYPE_I8 || rtype == MTYPE_U8) return TRUE;
04380 #endif
04381 return FALSE;
04382 }
04383
04384 static BOOL Is_Fast_Divide(WN *wn)
04385 {
04386 OPERATOR opr = WN_operator(wn);
04387 switch (opr) {
04388 case OPR_DIV:
04389 case OPR_REM:
04390 case OPR_MOD:
04391 {
04392 if (WN_operator_is(WN_kid1(wn), OPR_INTCONST)) {
04393 TYPE_ID rtype = OPCODE_rtype(WN_opcode(wn));
04394 INT64 constval = WN_const_val(WN_kid1(wn));
04395
04396 return opr == OPR_DIV
04397 ? Can_Do_Fast_Divide(rtype, constval)
04398 : Can_Do_Fast_Remainder(rtype, constval);
04399 }
04400 }
04401 break;
04402 }
04403
04404 return FALSE;
04405 }
04406
04407
04408
04409 static WN *lower_parm(WN *block, WN *tree, LOWER_ACTIONS actions){
04410
04411
04412 Is_True(Action(LOWER_UPC_TO_INTR) && WN_operator(tree) == OPR_PARM,
04413 ("Incorrect call to lower parm",""));
04414
04415 WN *kid = WN_kid0(tree);
04416 TY_IDX actual_ty;
04417 TY_IDX formal_ty = WN_ty(tree);
04418 TY_IDX access_ty;
04419 INT field_id;
04420 WN_OFFSET offset;
04421 WN *result;
04422 INTRINSIC iop;
04423
04424
04425
04426 SPTR_ACCUMULATION_STATE saved_acc_state = sptr_accumulation_state;
04427 sptr_accumulation_state = NO_ACCUMULATION;
04428
04429 field_id = WN_field_id(kid);
04430 offset = WN_offset(kid);
04431
04432 switch (WN_operator(kid)) {
04433 case OPR_LDID: {
04434 BOOL cvt = FALSE;
04435 INTRINSIC iop;
04436 if(field_id) {
04437 actual_ty = WN_object_ty(kid);
04438 access_ty = WN_ty(kid);
04439 } else
04440 actual_ty = ST_type(WN_st(kid));
04441
04442 if(Type_Is_Shared_Ptr(formal_ty)) {
04443 if(!Type_Is_Shared_Ptr(actual_ty) ||
04444 ( field_id && !Type_Is_Shared_Ptr(access_ty)) ) {
04445 Is_True(0, ("Local to shared cast in function param!",""));
04446 } else {
04447
04448 kid = lower_expr(block, kid, actions);
04449 if(Need_StoP_Cvt(actual_ty, formal_ty, &iop)) {
04450 kid = WN_Create_StoP_Cvt(kid, iop);
04451 actual_ty = formal_ty;
04452 }
04453 if(TY_kind(formal_ty) == KIND_SCALAR && TY_kind(actual_ty) == KIND_SCALAR)
04454 result = WN_CreateParm(TY_mtype(actual_ty), kid, actual_ty, WN_PARM_BY_VALUE);
04455 else
04456 result = WN_CreateParm(TY_mtype(TY_To_Sptr_Idx(actual_ty)), kid,
04457 TY_To_Sptr_Idx(actual_ty), WN_PARM_BY_VALUE);
04458 }
04459 } else {
04460
04461 Is_True(Type_Is_Shared_Ptr(actual_ty) || Type_Is_Shared_Ptr(access_ty),
04462 ("",""));
04463 if(WN_rtype(tree) != MTYPE_M) {
04464 kid = lower_expr(block, kid, actions);
04465 kid = Spill_Shared_Load(kid);
04466 result = WN_CreateParm(TY_mtype(formal_ty), kid,
04467 formal_ty, WN_PARM_BY_VALUE);
04468 } else {
04469
04470 }
04471
04472 }
04473 }
04474 break;
04475 case OPR_ILOAD:
04476 actual_ty = WN_ty(kid);
04477
04478 if (TY_mtype(actual_ty) != MTYPE_M ||
04479 (field_id && WN_object_ty(kid) != MTYPE_M))
04480 {
04481 INTRINSIC iop;
04482 kid = lower_expr(block, kid, actions);
04483 if(WN_operator(WN_kid0(tree)) == OPR_TAS)
04484 kid = Strip_TAS(kid);
04485 TY_IDX src = actual_ty;
04486 TY_IDX dest = formal_ty;
04487
04488 if(field_id) {
04489
04490 }
04491
04492 if(Type_Is_Shared_Ptr(actual_ty, TRUE) && Type_Is_Shared_Ptr(formal_ty, TRUE) &&
04493 Need_StoP_Cvt(actual_ty, formal_ty, &iop)) {
04494 kid = WN_Create_StoP_Cvt(kid, iop);
04495 actual_ty = formal_ty;
04496 }
04497
04498 if(TY_kind(formal_ty) != KIND_SCALAR && Type_Is_Shared_Ptr(formal_ty)) {
04499 formal_ty = TY_To_Sptr_Idx(formal_ty);
04500 }
04501 result = WN_CreateParm(TY_mtype(formal_ty), kid,
04502 formal_ty, WN_PARM_BY_VALUE);
04503 } else {
04504 access_ty = WN_load_addr_ty(kid);
04505 if (Type_Is_Shared_Ptr(access_ty)) {
04506 WN_kid0(tree) = lower_expr(block, WN_kid0(tree), actions);
04507 if(WN_operator(WN_kid0(tree)) == OPR_TAS)
04508 WN_kid0(tree) = WN_kid0(WN_kid0(tree));
04509
04510 ST *spill_st = Gen_Temp_Symbol(actual_ty, (char*) ".Mspill");
04511 WN *dest = WN_Lda(Pointer_Mtype, 0, spill_st, 0);
04512 kid = WN_Create_Shared_Load(kid, dest, TRUE, 0, actual_ty);
04513 WN *blk = WN_CreateBlock();
04514 WN_INSERT_BlockLast(blk, kid);
04515 WN *ld = WN_Ldid(MTYPE_M, 0, spill_st, access_ty);
04516 kid = WN_CreateComma(OPR_COMMA, MTYPE_M, MTYPE_V, blk, ld);
04517 WN_kid0(tree) = kid;
04518 result = tree;
04519 } else
04520 Is_True(0,("",""));
04521 }
04522 break;
04523 case OPR_MLOAD:
04524 {
04525
04526 actual_ty = WN_ty(tree);
04527 access_ty = WN_ty(kid);
04528
04529 WN_OFFSET offt = WN_offset(WN_kid0(kid));
04530 WN_kid0(kid) = lower_expr(block, WN_kid0(kid), actions);
04531 WN_kid1(kid) = lower_expr(block, WN_kid1(kid), actions);
04532
04533 ST *spill_st = Gen_Temp_Symbol(actual_ty, (char*) ".Mspill");
04534 WN *dest = WN_Lda(Pointer_Mtype, 0, spill_st, 0);
04535 kid = WN_Create_Shared_Load(kid, dest, TRUE, offt, actual_ty);
04536 WN *blk = WN_CreateBlock();
04537 WN_INSERT_BlockLast(blk, kid);
04538
04539 WN *ld = WN_Ldid(MTYPE_M, 0, spill_st, actual_ty);
04540 kid = WN_CreateComma(OPR_COMMA, MTYPE_M, MTYPE_V, blk, ld);
04541 WN_kid0(tree) = kid;
04542 result = tree;
04543 }
04544 break;
04545
04546 case OPR_TAS:
04547 {
04548 BOOL cvt = TRUE;
04549 actual_ty = WN_ty(kid);
04550 if (WN_Type_Is_Shared_Ptr(WN_kid0(kid), TRUE) &&
04551 Type_Is_Shared_Ptr(actual_ty, TRUE)) {
04552
04553 cvt = FALSE;
04554 }
04555
04556 kid = lower_expr(block, kid, actions);
04557 kid = Strip_TAS(kid);
04558
04559 if (!Type_Is_Shared_Ptr(formal_ty, TRUE)) {
04560 if(Type_Is_Shared_Ptr(actual_ty, TRUE)) {
04561 kid = WN_Convert_Shared_To_Local(kid);
04562 }
04563 } else {
04564 if (cvt && Type_Is_Shared_Ptr(actual_ty, TRUE) &&
04565 Need_StoP_Cvt(actual_ty, formal_ty, &iop))
04566 {
04567 kid = WN_Create_StoP_Cvt(kid, iop);
04568 }
04569 }
04570
04571 WN_kid0(tree) = kid;
04572 result = tree;
04573 }
04574 break;
04575 case OPR_LDA:
04576 {
04577 actual_ty = WN_ty(kid);
04578
04579 if(Type_Is_Shared_Ptr(actual_ty) && Type_Is_Shared_Ptr(formal_ty) &&
04580 Need_StoP_Cvt(actual_ty, formal_ty, &iop)) {
04581 kid = lower_expr(block, kid, actions);
04582 kid = WN_Create_StoP_Cvt(kid, iop);
04583 } else
04584 kid = lower_expr(block, kid, actions);
04585 WN_kid0(tree) = kid;
04586 result = tree;
04587 }
04588 break;
04589 default:
04590 WN_kid0(tree) = lower_expr(block, WN_kid0(tree), actions);
04591 result = tree;
04592 }
04593
04594 sptr_accumulation_state = saved_acc_state;
04595 return result;
04596 }
04597
04598
04599
04600
04601
04602
04603
04604
04605
04606
04607
04608
04609
04610 static WN *lower_expr(WN *block, WN *tree, LOWER_ACTIONS actions)
04611 {
04612 BOOL kids_lowered = FALSE;
04613 BOOL intrinsic_lowered;
04614
04615 TYPE_ID type = WN_rtype(tree);
04616
04617 Is_True(OPCODE_is_expression(WN_opcode(tree)),
04618 ("expected expression node, not %s", OPCODE_name(WN_opcode(tree))));
04619
04620 if (OPCODE_is_load(WN_opcode(tree)))
04621 lower_map(tree, actions);
04622
04623
04624
04625
04626 if (Action(LOWER_MADD) &&
04627 Madd_Allowed &&
04628 (MTYPE_id(type) == MTYPE_F4 || MTYPE_id(type) == MTYPE_F8))
04629 {
04630 tree = lower_nary_madd(block, tree, actions);
04631 tree = lower_madd(block, tree, actions);
04632 }
04633 if (Action(LOWER_TREEHEIGHT) &&
04634 WN_is_commutative(tree))
04635 {
04636 if (MTYPE_is_integral(type) || Roundoff_Level >= ROUNDOFF_ASSOC)
04637 tree = lower_tree_height(block, tree, actions);
04638 }
04639
04640
04641
04642
04643
04644 switch (WN_operator(tree)) {
04645
04646 case OPR_SUB:
04647 {
04648 if(Action(LOWER_UPC_TO_INTR)) {
04649 if(WN_Type_Is_Shared_Ptr(WN_kid0(tree), TRUE) &&
04650 WN_Type_Is_Shared_Ptr(WN_kid1(tree), TRUE)) {
04651
04652 TY_IDX eltype = WN_ty(WN_kid0(tree));
04653 TY_IDX eltype2 = WN_ty(WN_kid1(tree));
04654 return WN_Create_Shared_Ptr_Diff(lower_expr(block, WN_kid0(tree), actions),
04655 lower_expr(block, WN_kid1(tree), actions),
04656 eltype,
04657 eltype2);
04658 }
04659 }
04660 }
04661 break;
04662 case OPR_PARM:
04663 {
04664 if(Action(LOWER_UPC_TO_INTR)) {
04665 TY_IDX formal_idx = WN_ty(tree);
04666 TY_IDX actual_idx = WN_object_ty(WN_kid0(tree));
04667 if (Type_Is_Shared_Ptr(formal_idx) ||
04668 WN_Type_Is_Shared_Ptr(WN_kid0(tree)) ||
04669 (WN_operator(WN_kid0(tree)) == OPR_ILOAD &&
04670 Type_Is_Shared_Ptr(WN_load_addr_ty(WN_kid0(tree))))) {
04671
04672 return lower_parm(block, tree, actions);
04673
04674
04675
04676
04677
04678
04679
04680
04681
04682
04683
04684
04685
04686
04687
04688
04689
04690
04691
04692
04693
04694 } else if (WN_operator(WN_kid0(tree)) == OPR_ADD) {
04695
04696
04697 WN* kid = WN_kid0(tree);
04698 WN* offset = WN_kid1(kid);
04699 if (WN_operator(offset) == OPR_INTCONST) {
04700 TY_IDX obj_ty = struct_addr_ty(WN_kid0(kid));
04701 if (obj_ty != 0) {
04702 int field_id = find_field_from_offset(obj_ty, WN_const_val(offset));
04703 int real_ofst = Adjust_Field_Offset(obj_ty, field_id);
04704 WN_kid1(kid) = WN_CreateIntconst(OPR_INTCONST, Pointer_Mtype, MTYPE_V, real_ofst);
04705
04706 }
04707 }
04708 }
04709 }
04710 }
04711 break;
04712
04713 case OPR_INTRINSIC_OP:
04714
04715 if (WN_intrinsic(tree) == INTRN_TLD_ADDR) {
04716
04717 kids_lowered = TRUE;
04718 }
04719
04720 if (INTRN_is_nary(WN_intrinsic(tree)))
04721 break;
04722
04723 if (INTRN_cg_intrinsic(WN_intrinsic(tree)))
04724 break;
04725
04726 if (INTRN_is_actual(WN_intrinsic(tree)))
04727 {
04728 if (Action(LOWER_INTRINSIC))
04729 {
04730 tree = lower_intrinsic(block, tree, actions);
04731 kids_lowered = TRUE;
04732 }
04733 break;
04734 }
04735 if (Action(LOWER_INTRINSIC) ||
04736 Action(LOWER_INLINE_INTRINSIC) ||
04737 Action(LOWER_INL_STACK_INTRINSIC))
04738 {
04739 tree = lower_emulation(block, tree, actions, intrinsic_lowered);
04740 kids_lowered = TRUE;
04741 }
04742 break;
04743
04744 case OPR_ARRAY:
04745 if (Action(LOWER_ARRAY))
04746 {
04747
04748 tree = lower_linearize_array_addr(block, tree, actions);
04749 kids_lowered = TRUE;
04750
04751 }
04752 break;
04753
04754 case OPR_ADD:
04755 if (Action(LOWER_SPLIT_CONST_OFFSETS))
04756 {
04757
04758
04759
04760
04761
04762
04763
04764
04765
04766
04767 WN *lda = WN_kid0(tree);
04768 WN *con = WN_kid1(tree);
04769
04770 if (WN_operator_is(con, OPR_INTCONST) &&
04771 foldLdaOffset(lda, WN_const_val(con)))
04772 {
04773 WN_OFFSET offset = WN_lda_offset(lda) + WN_const_val(con);
04774
04775 if (mem_offset_must_be_split(offset))
04776 {
04777 WN_lda_offset(lda) = mem_offset_hi(offset);
04778 WN_const_val(con) = mem_offset_lo(offset);
04779 }
04780 }
04781 }
04782 else
04783 {
04784
04785
04786
04787
04788
04789
04790
04791
04792 WN *lda = WN_kid0(tree);
04793 WN *con = WN_kid1(tree);
04794
04795 if (Action(LOWER_UPC_TO_INTR)) {
04796
04797 TY_IDX idx_ptr, idx_off;
04798 idx_ptr = WN_ty(lda);
04799 idx_off = WN_ty(con);
04800 int esize = 0;
04801 int bsize = 0;
04802 WN *ptr, *off;
04803 BOOL ptr_ptr = FALSE;
04804
04805
04806
04807
04808
04809
04810
04811
04812
04813
04814
04815 if (WN_operator(lda) == OPR_CONST) {
04816 idx_ptr = 0;
04817 } else if(OPERATOR_is_load(WN_operator(lda)) && WN_field_id(lda)) {
04818 idx_ptr = Get_Field_Type(WN_ty(lda), WN_field_id(lda));
04819 }
04820
04821 if (WN_operator(con) == OPR_CONST) {
04822 idx_off = 0;
04823 } else if(OPERATOR_is_load(WN_operator(con)) && WN_field_id(con)) {
04824 idx_off = Get_Field_Type(WN_ty(con), WN_field_id(con));
04825 }
04826
04827
04828
04829
04830
04831
04832
04833
04834 if (!idx_ptr && !idx_off) {
04835 TY_IDX op_ty;
04836
04837
04838 if (WN_operator(lda) == OPR_ADD) {
04839 op_ty = WN_ty(WN_kid0(lda));
04840 if(Type_Is_Shared_Ptr(op_ty) && TY_kind(op_ty) != KIND_SCALAR)
04841 idx_ptr = op_ty;
04842 op_ty = WN_ty(WN_kid1(lda));
04843 if(Type_Is_Shared_Ptr(op_ty) && TY_kind(op_ty) != KIND_SCALAR)
04844 idx_ptr = op_ty;
04845 }
04846 else if (WN_operator(con) == OPR_ADD) {
04847 op_ty = WN_ty(WN_kid0(con));
04848 if(Type_Is_Shared_Ptr(op_ty) && TY_kind(op_ty) != KIND_SCALAR)
04849 idx_off = op_ty;
04850 op_ty = WN_ty(WN_kid1(con));
04851 if(Type_Is_Shared_Ptr(op_ty) && TY_kind(op_ty) != KIND_SCALAR)
04852 idx_off = op_ty;
04853 }
04854 }
04855
04856
04857
04858
04859
04860
04861 if (idx_ptr || idx_off ) {
04862
04863 ptr = lda;
04864 off = con;
04865
04866 if ( TY_kind(idx_ptr) == KIND_POINTER && TY_is_shared(TY_pointed(idx_ptr)) ) {
04867 idx_off = TY_pointed(idx_ptr);
04868 esize = Get_Type_Inner_Size(idx_off);
04869 bsize = Get_Type_Block_Size(idx_off);
04870 } else if ( TY_kind(idx_off) == KIND_POINTER && TY_is_shared(TY_pointed(idx_off)) ) {
04871 ptr = con;
04872 off = lda;
04873 idx_ptr = idx_off;
04874 idx_off = TY_pointed(idx_off);
04875 esize = Get_Type_Inner_Size(idx_off);
04876 bsize = Get_Type_Block_Size(idx_off);
04877 } else if ( TY_kind(idx_ptr) == KIND_ARRAY && TY_is_shared(TY_etype(idx_ptr)) ) {
04878 Is_True(0,("",""));
04879 esize = TY_size(TY_etype(idx_ptr));
04880 bsize = TY_block_size(TY_etype(idx_ptr));
04881 } else if ( TY_kind(idx_off) == KIND_ARRAY && TY_is_shared(TY_etype(idx_off)) ) {
04882 Is_True(0,("",""));
04883 ptr = con;
04884 off = lda;
04885 esize = TY_size(TY_etype (idx_off));
04886 bsize = TY_block_size(TY_etype(idx_off));
04887 } else {
04888
04889 ptr_ptr = TRUE;
04890 }
04891
04892
04893
04894
04895
04896
04897
04898
04899
04900
04901
04902
04903
04904
04905
04906 if(sptr_accumulation_state == ACCUMULATION) {
04907 if(!ptr_ptr) {
04908 if(WN_offset(ptr)) {
04909 if(OPERATOR_is_load(WN_operator(ptr)) && WN_field_id(ptr) &&
04910 Type_Is_Shared_Ptr(WN_ty(ptr)))
04911 ;
04912 else
04913 sptr_off_accumulation_stack.top()->push(WN_Intconst(Integer_type, WN_offset(ptr)));
04914 WN_offset(ptr) = 0;
04915 }
04916 }
04917 }
04918
04919 ptr = lower_expr(block, ptr, actions);
04920 off = lower_expr(block, off, actions);
04921
04922
04923
04924 if(ptr_ptr) {
04925
04926
04927 if (WN_operator(ptr) == OPR_COMMA &&
04928 (WN_ty(WN_kid1(ptr)) == shared_ptr_idx || WN_ty(WN_kid1(ptr)) == pshared_ptr_idx))
04929 goto do_arith;
04930 else if (WN_operator(off) == OPR_COMMA &&
04931 (WN_ty(WN_kid1(off)) == shared_ptr_idx || WN_ty(WN_kid1(off)) == pshared_ptr_idx)){
04932 lda = ptr;
04933 ptr = off;
04934 off = lda;
04935 goto do_arith;
04936 }
04937
04938 WN_kid0(tree) = ptr;
04939 WN_kid1(tree) = off;
04940 return tree;
04941 }
04942
04943 do_arith:
04944
04945 if (sptr_accumulation_state == NO_ACCUMULATION) {
04946
04947 Is_True(TY_kind(idx_ptr) == KIND_POINTER && Type_Is_Shared_Ptr(idx_ptr)
04948
04949 , ("",""));
04950 if(Type_Is_Shared_Ptr(TY_pointed(idx_ptr)))
04951 ptr = WN_Create_Shared_Ptr_Arithmetic (ptr, off, OPR_ADD, esize, bsize);
04952 else {
04953 WN_kid0(tree) = ptr;
04954 WN_kid1(tree) = off;
04955 return tree;
04956 }
04957 } else {
04958 sptr_off_accumulation_stack.top()->push(off);
04959 }
04960 WN_Delete (tree);
04961
04962 tree = ptr;
04963 kids_lowered = TRUE;
04964
04965 }
04966 }
04967
04968 no_shared:
04969 if (WN_operator_is(con, OPR_INTCONST) &&
04970 foldLdaOffset(lda, WN_const_val(con)))
04971 {
04972 WN_lda_offset(lda) += WN_const_val(con);
04973 WN_Delete(tree);
04974 WN_Delete(con);
04975 tree = lower_expr(block, lda, actions);;
04976 }
04977 }
04978 break;
04979
04980 case OPR_MLOAD:
04981 if (Action(LOWER_UPC_TO_INTR)) {
04982 TY_IDX idx = WN_ty(tree);
04983 WN *ild;
04984 if (Type_Is_Shared_Ptr(idx)) {
04985 SPTR_ACCUMULATION_STATE saved_acc_state = sptr_accumulation_state;
04986 sptr_accumulation_state = ACCUMULATION;
04987 sptr_off_accumulation_stack.push(CXX_NEW(SPTR_OFFSET_TERM_STACK, Malloc_Mem_Pool));
04988 SPTR_OFFSET_TERM_STACK *term_stack = sptr_off_accumulation_stack.top();
04989 if(WN_offset(tree)) {
04990 term_stack->push(WN_Intconst(Integer_type, WN_offset(tree)));
04991 WN_offset(tree) = 0;
04992 }
04993
04994 WN_kid0(tree) = lower_expr(block, WN_kid0(tree), actions);
04995 WN_kid1(tree) = lower_expr(block, WN_kid1(tree), actions);
04996
04997 if(WN_operator(WN_kid0(tree)) == OPR_TAS)
04998 WN_kid0(tree) = Strip_TAS(WN_kid0(tree));
04999
05000 ild = Combine_Offset_Terms(*term_stack);
05001
05002
05003
05004 sptr_accumulation_state = saved_acc_state;
05005 sptr_off_accumulation_stack.pop();
05006 CXX_DELETE(term_stack, Malloc_Mem_Pool);
05007
05008
05009
05010
05011
05012 return WN_Create_Shared_Load(tree, 0, FALSE, 0, 0, TRUE, ild);
05013 }
05014 } else
05015 if (Align_Object)
05016 {
05017 WN_kid0(tree)= lower_expr(block, WN_kid0(tree), actions);
05018
05019 kids_lowered = TRUE;
05020 if(Action(LOWER_UPC_MFIELD) &&
05021 WN_operator(WN_kid1(tree)) == OPR_INTCONST) {
05022 WN_const_val(WN_kid1(tree)) =
05023 Adjusted_Type_Size(WN_field_id(tree) == 0 ? TY_pointed(WN_ty(tree)) : Get_Field_Type(TY_pointed(WN_ty(tree)), WN_field_id(tree)));
05024 }
05025 tree = improve_Malignment(tree, WN_kid0(tree), WN_kid1(tree),
05026 WN_load_offset(tree));
05027 break;
05028 }
05029
05030 case OPR_ILOAD:
05031 if (Action(LOWER_MLDID_MSTID) && WN_opcode(tree) == OPC_MMILOAD)
05032 return lower_miload(block, tree, actions);
05033
05034 if (Action(LOWER_BIT_FIELD_ID) && WN_desc(tree) == MTYPE_BS) {
05035 lower_bit_field_id(tree);
05036 if (Action(LOWER_BITS_OP) && WN_operator(tree) == OPR_ILDBITS)
05037 return lower_load_bits (block, tree, actions);
05038 }
05039
05040 if (Action(LOWER_SPLIT_CONST_OFFSETS))
05041 {
05042
05043
05044
05045
05046
05047
05048
05049
05050
05051
05052 WN_OFFSET offset = WN_load_offset(tree);
05053 if (mem_offset_must_be_split(offset))
05054 {
05055 WN_kid0(tree) = WN_Add(Pointer_type,
05056 WN_kid0(tree),
05057 WN_Intconst(Pointer_type,
05058 mem_offset_hi(offset)));
05059 WN_load_offset(tree) = mem_offset_lo(offset);
05060 }
05061 }
05062 else
05063 {
05064
05065
05066
05067
05068
05069
05070
05071
05072 WN *kid = WN_kid0(tree);
05073
05074 if (foldLdaOffset(kid, WN_load_offset(tree)))
05075 {
05076 WN_load_offset(tree) += WN_lda_offset(kid);
05077 WN_lda_offset(kid) = 0;
05078 }
05079
05080
05081
05082
05083
05084
05085
05086
05087
05088
05089 else if (WN_operator_is(kid, OPR_ADD) &&
05090 foldConstOffset(WN_kid1(kid), WN_load_offset(tree)))
05091 {
05092 WN_load_offset(tree) += WN_const_val(WN_kid1(kid));
05093 WN_kid0(tree) = WN_kid0(kid);
05094
05095 TY_IDX obj_ty = struct_addr_ty(WN_kid0(tree));
05096 if (obj_ty != 0) {
05097
05098 int field_id = find_field_from_offset(obj_ty, WN_load_offset(tree));
05099 WN_store_offset(tree) = Adjust_Field_Offset(obj_ty, field_id);
05100
05101 }
05102
05103 WN_Delete(WN_kid1(kid));
05104 WN_Delete(kid);
05105 }
05106 }
05107
05108 if(Action(LOWER_UPC_TO_INTR) ) {
05109 TY_IDX idx = WN_ty(tree);
05110 WN *ild = 0;
05111 BOOL has_off = TRUE;
05112 BOOL local_off = FALSE;
05113 WN *offt = 0;
05114 TY_IDX src_idx;
05115 if (Type_Is_Shared_Ptr(WN_load_addr_ty(tree))) {
05116 TY_IDX ptr_idx = WN_load_addr_ty(tree);
05117 Is_True(TY_kind(ptr_idx) == KIND_POINTER, ("",""));
05118
05119 SPTR_ACCUMULATION_STATE saved_acc_state = sptr_accumulation_state;
05120 sptr_accumulation_state = ACCUMULATION;
05121 sptr_off_accumulation_stack.push(CXX_NEW(SPTR_OFFSET_TERM_STACK, Malloc_Mem_Pool));
05122 SPTR_OFFSET_TERM_STACK *term_stack = sptr_off_accumulation_stack.top();
05123
05124 WN *kid0 = WN_kid0(tree);
05125
05126 if((WN_operator(kid0) == OPR_LDID && !WN_offset(tree)) ||
05127 WN_operator(kid0) == OPR_ARRAY ||
05128
05129
05130 ( WN_operator(kid0) == OPR_TAS && WN_operator(WN_kid0(kid0)) == OPR_LDA &&
05131 TY_kind(TY_pointed(WN_ty(WN_kid0(kid0)))) == KIND_ARRAY) )
05132 has_off = FALSE;
05133
05134 if(WN_offset(tree) || WN_field_id(tree)) {
05135
05136 offt = WN_Intconst(Integer_type, WN_field_id(tree) > 1 ? Adjust_Field_Offset(WN_ty(tree), WN_field_id(tree)) : WN_offset(tree));
05137 WN_offset(tree) = 0;
05138 local_off = TRUE;
05139 }
05140
05141 if(WN_operator(WN_kid0(tree)) == OPR_TAS)
05142 WN_set_load_addr_ty(tree, WN_ty(WN_kid0(tree)));
05143
05144
05145 switch (WN_operator(WN_kid0(tree))) {
05146 case OPR_LDID:
05147 idx = ST_type(WN_st(WN_kid0(tree)));
05148 break;
05149 case OPR_TAS:
05150 idx = WN_ty(WN_kid0(tree));
05151 break;
05152 default:
05153 break;
05154 }
05155
05156 WN_kid0(tree) = lower_expr(block, WN_kid0(tree), actions);
05157
05158 if(WN_operator(WN_kid0(tree)) == OPR_TAS) {
05159 src_idx = WN_ty(WN_kid0(tree));
05160 WN_kid0(tree) = Strip_TAS(WN_kid0(tree));
05161 } else
05162 src_idx = idx;
05163
05164 if(has_off) {
05165
05166 ild = Combine_Offset_Terms(*term_stack);
05167
05168
05169
05170
05171 if(( TY_kind(idx) == KIND_POINTER && TY_kind(TY_pointed(idx)) != KIND_STRUCT)
05172 ||
05173 ( TY_kind(idx) == KIND_POINTER && TY_kind(TY_pointed(idx)) == KIND_STRUCT && ild)
05174 ||
05175 (TY_kind(idx) == KIND_ARRAY && TY_kind(Get_Inner_Array_Type(idx)) != KIND_STRUCT)
05176 ||
05177 (TY_kind(idx) == KIND_ARRAY && TY_kind(Get_Inner_Array_Type(idx)) == KIND_STRUCT && ild)
05178 ) {
05179 if (TY_kind(src_idx) == KIND_POINTER &&
05180 (WN_operator(WN_kid0(tree)) == OPR_LDID &&
05181 Types_Are_Equiv(src_idx, ST_type(WN_st(WN_kid0(tree))))
05182 || !local_off)) {
05183 UINT esize = Get_Type_Inner_Size(idx);
05184 if(TY_kind(idx) == KIND_POINTER && TY_is_shared(TY_pointed(idx)) &&
05185 TY_kind(TY_pointed(idx)) == KIND_POINTER)
05186 esize = TY_size(TY_To_Sptr_Idx(idx));
05187 if(ild)
05188 WN_kid0(tree) = WN_Create_Shared_Ptr_Arithmetic (WN_kid0(tree), ild, OPR_ADD,
05189 esize,
05190 Get_Type_Block_Size(idx),
05191 Get_Type_Block_Size(idx) <= 1);
05192 if(offt)
05193 ild = offt;
05194 else
05195 has_off = FALSE;
05196 }
05197 }
05198
05199 if(!ild && offt)
05200 ild = offt;
05201 else if(!ild)
05202 has_off = FALSE;
05203 }
05204
05205 sptr_accumulation_state = saved_acc_state;
05206 sptr_off_accumulation_stack.pop();
05207 CXX_DELETE(term_stack, Malloc_Mem_Pool);
05208 return WN_Create_Shared_Load(tree, 0, FALSE, 0, 0, has_off, ild);
05209 } else if(TY_kind(idx) == KIND_STRUCT && !TY_is_shared(idx) &&
05210 Type_Is_Shared_Ptr(TY_pointed(WN_load_addr_ty(tree)), TRUE)) {
05211
05212
05213
05214
05215
05216 idx = TY_To_Sptr_Idx(TY_pointed(WN_load_addr_ty(tree)));
05217 if(TY_mtype(idx) == MTYPE_M) {
05218 WN_set_rtype(tree, MTYPE_M);
05219 WN_set_desc(tree, MTYPE_M);
05220 WN_set_load_addr_ty(tree, Make_Pointer_Type(idx));
05221 WN_load_offset(tree) = Adjust_Field_Offset(WN_ty(tree),WN_field_id(tree));
05222
05223
05224
05225 return tree;
05226 }
05227 } else if(Type_Is_Shared_Ptr(WN_ty(tree), TRUE)) {
05228 idx = TY_To_Sptr_Idx(WN_ty(tree));
05229 WN_set_rtype(tree, TY_mtype(idx));
05230 WN_set_desc(tree,TY_mtype(idx));
05231 } else if(WN_field_id(tree) > 1)
05232 WN_load_offset(tree) = Adjust_Field_Offset(TY_kind(WN_ty(tree)) == KIND_STRUCT ? WN_ty(tree) :TY_pointed(WN_ty(tree)),WN_field_id(tree));
05233 }
05234 break;
05235
05236 case OPR_LDID: {
05237
05238
05239
05240
05241
05242 if (Action(LOWER_RETURN_VAL) && WN_st(tree) == Return_Val_Preg)
05243 return lower_return_ldid(block, tree, actions);
05244
05245 if (Action(LOWER_MLDID_MSTID) && WN_opcode(tree) == OPC_MMLDID)
05246 return lower_mldid(block, tree, actions);
05247
05248 if (Action(LOWER_BIT_FIELD_ID) && WN_desc(tree) == MTYPE_BS) {
05249 lower_bit_field_id(tree);
05250 if (Action(LOWER_BITS_OP) && WN_operator(tree) == OPR_LDBITS)
05251 return lower_load_bits (block, tree, actions);
05252 }
05253
05254 if(Action(LOWER_UPC_TO_INTR) ) {
05255 WN *ical;
05256 TY_IDX idx, src_idx;
05257 if ( TY_is_shared(ST_type(WN_st(tree)))) {
05258 ical = WN_Create_Shared_Load(tree);
05259 } else if (TY_kind(ST_type(WN_st(tree))) == KIND_POINTER &&
05260 TY_is_shared(TY_pointed(ST_type(WN_st(tree)))) ) {
05261
05262
05263 ical = WN_COPY_Tree(tree);
05264 idx = TY_To_Sptr_Idx(ST_type(WN_st(tree)));
05265 WN_set_rtype(ical, TY_mtype(idx));
05266 WN_set_desc (ical, TY_mtype(idx));
05267 WN_set_ty(ical, idx);
05268 } else {
05269 idx = WN_field_id(tree) ? get_field_type(WN_ty(tree), WN_field_id(tree)) : WN_ty(tree);
05270 if(WN_field_id(tree) && Type_Is_Shared_Ptr(idx, TRUE)) {
05271 ical = WN_COPY_Tree(tree);
05272 src_idx = TY_To_Sptr_Idx(idx);
05273 WN_set_rtype(ical, TY_mtype(src_idx));
05274 WN_set_desc (ical, TY_mtype(src_idx));
05275
05276 WN_load_offset(ical) = Adjust_Field_Offset(WN_ty(tree) , WN_field_id(tree));
05277 } else if(WN_field_id(tree) > 1) {
05278 WN_load_offset(tree) = Adjust_Field_Offset(WN_ty(tree) , WN_field_id(tree));
05279 goto skip;
05280 } else
05281 goto skip;
05282 }
05283 return ical;
05284 }
05285 skip:
05286 if ((WN_class(tree) == CLASS_CONST) && (WN_load_offset(tree) == 0))
05287 {
05288 TCON val = WN_val(tree);
05289 TYPE_ID valType = WN_val_type(tree);
05290 WN *con;
05291
05292 if (MTYPE_is_integral(type) && MTYPE_is_integral(valType))
05293 {
05294 con = WN_Intconst(type, Targ_To_Host( val));
05295 WN_Delete(tree);
05296 return con;
05297 }
05298
05299
05300
05301 else if ((MTYPE_is_float(type) && MTYPE_is_float(valType)) &&
05302 !(!MTYPE_is_complex(type) && MTYPE_is_complex(valType)))
05303 {
05304 if (type != valType)
05305 {
05306 val = Targ_Conv(type, val);
05307 }
05308 con = Make_Const(val);
05309 WN_Delete(tree);
05310 return con;
05311 }
05312 }
05313 {
05314 PREG_NUM last_preg = Get_Preg_Num(PREG_Table_Size(CURRENT_SYMTAB));
05315 if ((WN_class(tree) == CLASS_PREG) &&
05316 (WN_load_offset(tree) > last_preg))
05317 {
05318 DevWarn("lower_expr() pregno %d > SYMTAB_last_preg(%d)",
05319 WN_load_offset(tree), last_preg);
05320 }
05321 }
05322
05323
05324
05325 if (Action(LOWER_SPLIT_SYM_ADDRS))
05326 {
05327 WN *iload;
05328 iload = lower_split_sym_addrs(tree, WN_load_offset(tree), actions);
05329 if (iload)
05330 {
05331 return lower_expr(block, iload, actions);
05332 }
05333 }
05334 if ( Action(LOWER_FORMAL_REF) && WN_class(tree) == CLASS_VAR)
05335 {
05336 WN *iload;
05337
05338 iload = lower_formal_ref(tree, WN_load_offset(tree),
05339 WN_st(tree), actions);
05340 if (iload)
05341 {
05342 return lower_expr(block, iload, actions);
05343 }
05344 }
05345 if ( Action(LOWER_UPLEVEL))
05346 {
05347 ST *sym = WN_st(tree);
05348
05349 if (ST_is_uplevelTemp(sym))
05350 {
05351 WN *iload;
05352
05353 iload = lower_uplevel_reference(tree, WN_load_offset(tree), actions);
05354 tree = lower_expr(block, iload, actions);
05355 return tree;
05356 }
05357 }
05358 break;
05359 }
05360 case OPR_ILDBITS:
05361 case OPR_LDBITS:
05362 if (Action(LOWER_BITS_OP))
05363 return lower_load_bits (block, tree, actions);
05364 break;
05365
05366 case OPR_LDA:
05367
05368
05369
05370 {
05371
05372
05373
05374
05375
05376
05377
05378
05379 ST *sym = WN_st(tree);
05380
05381
05382
05383
05384
05385
05386
05387
05388
05389 if (ST_class(sym) == CLASS_BLOCK && STB_merge(sym))
05390 {
05391 DevWarn("LDA (%s) potential bad exposed use of a mergeable symbol",
05392 ST_name(sym));
05393 }
05394 }
05395 if (Action(LOWER_SPLIT_SYM_ADDRS))
05396 {
05397 WN *lda;
05398 lda = lower_split_sym_addrs(tree, WN_lda_offset(tree), actions);
05399 if (lda)
05400 {
05401 return lower_expr(block, lda, actions);
05402 }
05403 }
05404 if ( Action(LOWER_FORMAL_REF) && WN_class(tree) == CLASS_VAR)
05405 {
05406 WN *ldid;
05407
05408 ldid = lower_formal_ref(tree, WN_lda_offset(tree), WN_st(tree),
05409 actions);
05410 if (ldid)
05411 {
05412 return lower_expr(block, ldid, actions);
05413 }
05414 }
05415 if ( Action(LOWER_UPLEVEL))
05416 {
05417 ST *sym = WN_st(tree);
05418
05419 if (ST_is_uplevelTemp(sym))
05420 {
05421 WN *ldid;
05422
05423 ldid = lower_uplevel_reference(tree, WN_lda_offset(tree), actions);
05424 tree = lower_expr(block, ldid, actions);
05425 return tree;
05426 }
05427 }
05428
05429 if ( Action(LOWER_UPC_TO_INTR) ) {
05430 TY_IDX tidx = WN_ty(tree);
05431
05432 if ( (TY_kind(tidx) == KIND_POINTER && TY_is_shared(TY_pointed(tidx))) ||
05433 (TY_kind(tidx) == KIND_ARRAY && TY_is_shared(TY_etype(tidx))) ){
05434 WN *ld;
05435 TY_IDX idx1 = TY_To_Sptr_Idx(TY_pointed(tidx));
05436 ld = WN_Ldid(TY_mtype(idx1), 0, WN_st(tree), idx1);
05437 if (WN_offset(tree) && TY_kind(TY_pointed(tidx)) != KIND_STRUCT)
05438 {
05439
05440 ld = WN_Create_Shared_Ptr_Arithmetic(ld,
05441 WN_Intconst(Integer_type,
05442 WN_offset(tree)),
05443 OPR_ADD,
05444 Get_Type_Inner_Size(tidx),
05445 Get_Type_Block_Size(tidx));
05446 }
05447 return ld;
05448 } else {
05449 tidx = TY_pointed(tidx);
05450 if(WN_offset(tree) && TY_kind(tidx) == KIND_STRUCT) {
05451 WN_load_offset(tree) = 0;
05452 }
05453
05454 }
05455 }
05456
05457 break;
05458
05459 case OPR_CVT:
05460 case OPR_TRUNC:
05461 case OPR_RND:
05462 if (Action(LOWER_CVT))
05463 {
05464 tree = lower_cvt(block, tree, actions);
05465 kids_lowered = TRUE;
05466 } else if(Action(LOWER_UPC_TO_INTR)) {
05467 TY_IDX ty_idx = 0;
05468 switch (WN_operator(WN_kid0(tree))) {
05469 case OPR_LDID:
05470 case OPR_TAS:
05471 ty_idx = WN_ty(WN_kid0(tree));
05472 break;
05473 case OPR_COMMA:
05474
05475 default:
05476
05477 break;
05478 }
05479 if(Type_Is_Shared_Ptr(ty_idx, TRUE))
05480 return WN_Convert_Shared_To_Local(lower_expr(block, WN_kid0(tree), actions));
05481 }
05482 break;
05483
05484 case OPR_TAS:
05485
05486
05487
05488
05489
05490 if (Action(LOWER_TO_CG))
05491 {
05492 WN *load = WN_kid0(tree);
05493 if ( OPERATOR_is_load(WN_operator(load))
05494 && (!WN_has_sym(load) || WN_class(load) != CLASS_PREG))
05495 {
05496 TYPE_ID tas_rtype = WN_rtype(tree);
05497 if (MTYPE_byte_size(tas_rtype) == MTYPE_byte_size(WN_desc(load))) {
05498 WN_set_rtype(load, tas_rtype);
05499 WN_set_desc(load, tas_rtype);
05500 WN_Delete(tree);
05501 return lower_expr(block, load, actions);
05502 }
05503 }
05504 }
05505
05506
05507
05508
05509 if (WN_Type_Is_Shared_Ptr(tree)) {
05510 if(Action(LOWER_UPC_TO_INTR)) {
05511
05512
05513
05514
05515 WN *kid0 = WN_kid0(tree);
05516 TY_IDX kid_idx = WN_ty(kid0);
05517 kid0 = Strip_TAS(kid0);
05518 UINT field_id;
05519 if(WN_operator(WN_kid0(tree)) != OPR_TAS || WN_ty(kid0) != 0) {
05520 kid_idx = WN_ty(kid0);
05521 if(OPERATOR_is_load(WN_operator(kid0)) && WN_field_id(kid0)) {
05522 switch(WN_operator(kid0)) {
05523 case OPR_LDID:
05524 case OPR_ILOAD:
05525 kid_idx = Get_Field_Type(kid_idx, WN_field_id(kid0));
05526 break;
05527 default:
05528 Is_True(0,("",""));
05529 }
05530 }
05531 }
05532 WN_kid0(tree) = kid0;
05533
05534
05535 TY_IDX tas_idx = WN_ty(tree);
05536 INTRINSIC iop;
05537 BOOL spill = (WN_operator(kid0) == OPR_LDID && ST_class(WN_st(kid0)) == CLASS_PREG);
05538
05539
05540 if(Type_Is_Shared_Ptr(kid_idx, TRUE) && Need_StoP_Cvt(kid_idx, tas_idx, &iop))
05541 {
05542
05543
05544 WN *res = lower_expr(block, kid0, actions);
05545 if(WN_operator(res) == OPR_COMMA || spill)
05546 res = Spill_Shared_Load(res);
05547 return WN_Create_StoP_Cvt(res, iop);
05548 }
05549 }
05550
05551
05552 WN_kid0(tree) = lower_expr(block, WN_kid0(tree), actions);
05553
05554
05555
05556 return tree;
05557 }
05558
05559 break;
05560
05561 case OPR_IMAGPART:
05562 if (Action(LOWER_COMPLEX))
05563 {
05564 WN *realexp, *imagexp;
05565 lower_complex_expr(block, WN_kid0(tree), actions, &realexp, &imagexp);
05566 WN_Delete(tree);
05567 tree = lower_expr(block, imagexp, actions);
05568 }
05569 break;
05570
05571 case OPR_REALPART:
05572 if (Action(LOWER_COMPLEX))
05573 {
05574 WN *realexp, *imagexp;
05575
05576 lower_complex_expr(block, WN_kid0(tree), actions, &realexp, &imagexp);
05577 WN_Delete(tree);
05578 tree = lower_expr(block, realexp, actions);
05579 }
05580 break;
05581
05582 case OPR_EQ:
05583 if (Action(LOWER_COMPLEX) && MTYPE_is_complex(WN_desc(tree)))
05584 {
05585
05586
05587
05588
05589 WN *rx, *ry, *ix, *iy;
05590 TYPE_ID realTY = Mtype_complex_to_real( WN_desc(tree));
05591
05592 lower_complex_expr(block, WN_kid0(tree), actions, &rx, &ix);
05593 lower_complex_expr(block, WN_kid1(tree), actions, &ry, &iy);
05594
05595 tree = WN_LAND(WN_EQ(realTY, rx, ry),
05596 WN_EQ(realTY, ix, iy));
05597
05598 return lower_expr(block, tree, actions);
05599 }
05600 if(Action(LOWER_UPC_TO_INTR)) {
05601 if(WN_Type_Is_Shared_Ptr(WN_kid0(tree)) ||
05602 WN_Type_Is_Shared_Ptr(WN_kid1(tree))) {
05603
05604 TY_IDX idx0 = WN_ty(WN_kid0(tree));
05605 TY_IDX idx1 = WN_ty(WN_kid1(tree));
05606 WN *kid0 = lower_expr(block, WN_kid0(tree), actions);
05607 WN *kid1 = lower_expr(block, WN_kid1(tree), actions);
05608 if(Type_Is_Shared_Ptr(idx0, TRUE) && Type_Is_Shared_Ptr(idx1, TRUE)) {
05609 tree = WN_Create_PtrEq_Test(OPR_EQ, kid0, kid1, idx0, idx1);
05610 } else if(Type_Is_Shared_Ptr(idx1, TRUE) || Type_Is_Shared_Ptr(idx0, TRUE)) {
05611 Is_True(WN_operator(kid0) == OPR_INTCONST ||
05612 WN_operator(kid1) == OPR_INTCONST ||
05613 WN_operator(kid0) == OPR_LDID ||
05614 WN_operator(kid1) == OPR_LDID,
05615 ("Mismatching operators for shared pointer operation",""));
05616 tree = WN_Create_PtrEq_Test(OPR_EQ, kid0, kid1, idx0, idx1);
05617 } else {
05618 WN_kid0(tree) = kid0;
05619 WN_kid1(tree) = kid1;
05620 kids_lowered = TRUE;
05621 }
05622 return tree;
05623 }
05624 }
05625 break;
05626
05627 case OPR_NE:
05628 if (Action(LOWER_COMPLEX) && MTYPE_is_complex(WN_desc(tree)))
05629 {
05630
05631
05632
05633
05634 WN *rx, *ry, *ix, *iy;
05635 TYPE_ID realTY = Mtype_complex_to_real( WN_desc(tree));
05636
05637 lower_complex_expr(block, WN_kid0(tree), actions, &rx, &ix);
05638 lower_complex_expr(block, WN_kid1(tree), actions, &ry, &iy);
05639
05640 tree = WN_LNOT(WN_LAND(WN_EQ(realTY, rx, ry),
05641 WN_EQ(realTY, ix, iy)));
05642
05643 return lower_expr(block, tree, actions);
05644 }
05645 if(Action(LOWER_UPC_TO_INTR)) {
05646 if(WN_Type_Is_Shared_Ptr(WN_kid0(tree)) ||
05647 WN_Type_Is_Shared_Ptr(WN_kid1(tree))) {
05648
05649 TY_IDX idx0 = WN_ty(WN_kid0(tree));
05650 TY_IDX idx1 = WN_ty(WN_kid1(tree));
05651 WN *kid0 = lower_expr(block, WN_kid0(tree), actions);
05652 WN *kid1 = lower_expr(block, WN_kid1(tree), actions);
05653 if(Type_Is_Shared_Ptr(idx0, TRUE) && Type_Is_Shared_Ptr(idx1, TRUE)) {
05654 tree = WN_Create_PtrEq_Test(OPR_NE, kid0, kid1, idx0, idx1);
05655 } else if(Type_Is_Shared_Ptr(idx1, TRUE) || Type_Is_Shared_Ptr(idx0, TRUE)) {
05656 Is_True( (WN_operator(kid0) == OPR_INTCONST && WN_const_val(kid0) == 0) ||
05657 (WN_operator(kid1) == OPR_INTCONST && WN_const_val(kid1) == 0) ||
05658 WN_operator(kid0) == OPR_LDID ||
05659 WN_operator(kid1) == OPR_LDID,
05660 ("Mismatching operators for shared pointer operation",""));
05661 tree = WN_Create_PtrEq_Test(OPR_NE, kid0, kid1, idx0, idx1);
05662 } else {
05663 WN_kid0(tree) = kid0;
05664 WN_kid1(tree) = kid1;
05665 kids_lowered = TRUE;
05666 }
05667 return tree;
05668 }
05669 }
05670 break;
05671
05672 case OPR_MADD:
05673 if (Action(LOWER_QUAD) && MTYPE_is_quad(type))
05674 {
05675
05676
05677
05678 WN *wn;
05679
05680 wn = WN_Add(type,
05681 WN_Mpy(type, WN_kid1(tree), WN_kid2(tree)),
05682 WN_kid0(tree));
05683 WN_Delete(tree);
05684
05685 tree = wn;
05686 }
05687 break;
05688
05689 case OPR_MSUB:
05690 if (Action(LOWER_QUAD) && MTYPE_is_quad(type))
05691 {
05692
05693
05694
05695 WN *wn;
05696
05697 wn = WN_Sub(type,
05698 WN_Mpy(type, WN_kid1(tree), WN_kid2(tree)),
05699 WN_kid0(tree));
05700 WN_Delete(tree);
05701
05702 tree = wn;
05703 }
05704 break;
05705
05706 case OPR_NMADD:
05707 if (Action(LOWER_QUAD) && MTYPE_is_quad(type))
05708 {
05709
05710
05711
05712 WN *wn, *madd;
05713
05714 madd = WN_Add(type,
05715 WN_Mpy(type, WN_kid1(tree), WN_kid2(tree)),
05716 WN_kid0(tree));
05717
05718 wn = WN_Neg(type, madd);
05719 WN_Delete(tree);
05720
05721 tree = wn;
05722 }
05723 break;
05724
05725 case OPR_NMSUB:
05726 if (Action(LOWER_QUAD) && MTYPE_is_quad(type))
05727 {
05728
05729
05730
05731 WN *wn;
05732
05733 wn = WN_Sub(type,
05734 WN_kid0(tree),
05735 WN_Mpy(type, WN_kid1(tree), WN_kid2(tree)));
05736 WN_Delete(tree);
05737
05738 tree = wn;
05739 }
05740 break;
05741
05742 case OPR_RSQRT:
05743 tree = lower_rsqrt(block, tree, actions);
05744 break;
05745
05746 case OPR_RECIP:
05747 tree = lower_recip(block, tree, actions);
05748 break;
05749
05750 case OPR_SELECT:
05751 {
05752 WN * const kid0 = WN_kid0(tree);
05753 if (WN_operator_is(kid0, OPR_INTCONST))
05754 {
05755 INT64 flag = WN_const_val(kid0);
05756 WN * const kid = flag ? WN_kid1(tree) : WN_kid2(tree);
05757 return lower_expr(block, kid, actions);
05758 } else if (WN_operator(kid0) == OPR_LNOT) {
05759
05760
05761
05762
05763 WN * const new_kid1 = WN_kid2(tree);
05764 WN * const new_kid2 = WN_kid1(tree);
05765 WN * const new_kid0 = WN_kid0(kid0);
05766 TYPE_ID new_desc = (WN_rtype(new_kid0) == MTYPE_B) ? MTYPE_B : MTYPE_V;
05767 WN_kid0(tree) = new_kid0;
05768 WN_kid1(tree) = new_kid1;
05769 WN_kid2(tree) = new_kid2;
05770 WN_set_desc(tree, new_desc);
05771 WN_Delete(kid0);
05772 return lower_expr(block, tree, actions);
05773 }
05774 }
05775 break;
05776
05777 case OPR_PAREN:
05778 if (Roundoff_Level > ROUNDOFF_ASSOC)
05779 {
05780
05781
05782
05783
05784 WN *kid0 = WN_kid0(tree);
05785
05786 WN_Delete(tree);
05787 return lower_expr(block, kid0, actions);
05788 }
05789 break;
05790
05791 case OPR_DIV:
05792 case OPR_REM:
05793 case OPR_MOD:
05794
05795 {
05796
05797
05798
05799
05800 TYPE_ID rtype = OPCODE_rtype(WN_opcode(tree));
05801 if (Should_Call_Divide(rtype) && !Is_Fast_Divide(tree)) {
05802
05803 #ifdef EMULATE_LONGLONG
05804 if (rtype == MTYPE_I8 || rtype == MTYPE_U8) {
05805 FmtAssert (OPCODE_rtype(WN_opcode(WN_kid0(tree))) == rtype,
05806 ("DIV/REM/MOD: kid0 should be %d, is %d",
05807 rtype, OPCODE_rtype(WN_opcode(WN_kid0(tree)))));
05808 FmtAssert (OPCODE_rtype(WN_opcode(WN_kid1(tree))) == rtype,
05809 ("DIV/REM/MOD: kid1 should be %d, is %d",
05810 rtype, OPCODE_rtype(WN_opcode(WN_kid1(tree)))));
05811 }
05812 #endif
05813
05814 WN *kids[2];
05815 WN *iwn;
05816 LEAF tmpY;
05817 INTRINSIC intrinsic;
05818 BOOL is_unsigned = MTYPE_is_unsigned(rtype);
05819 BOOL is_float = MTYPE_is_float(rtype);
05820 BOOL is_double = MTYPE_is_size_double(rtype);
05821 switch (WN_operator(tree)) {
05822 case OPR_DIV:
05823 if (is_float) {
05824 intrinsic = (is_double ? INTRN_DIVDF3 : INTRN_DIVSF3);
05825 } else if (is_double) {
05826 intrinsic = (is_unsigned ? INTRN_UDIVDI3 : INTRN_DIVDI3);
05827 } else {
05828 intrinsic = (is_unsigned ? INTRN_UDIVSI3 : INTRN_DIVSI3);
05829 }
05830 break;
05831 case OPR_MOD:
05832 FmtAssert(!is_float, ("Unexpected MOD operator on float"));
05833
05834
05835
05836
05837 if (!is_unsigned) {
05838 tmpY = Make_Leaf(block, WN_kid1(tree), type);
05839 WN_kid1(tree) = Load_Leaf(tmpY);
05840 }
05841
05842 case OPR_REM:
05843 FmtAssert(!is_float, ("Unexpected REM operator on float"));
05844 if (is_double) {
05845 intrinsic = (is_unsigned ? INTRN_UMODDI3 : INTRN_MODDI3);
05846 } else {
05847 intrinsic = (is_unsigned ? INTRN_UMODSI3 : INTRN_MODSI3);
05848 }
05849 break;
05850 default:
05851 FmtAssert (FALSE, ("Unexpected division operator"));
05852
05853 }
05854 kids[0] = WN_CreateParm (rtype,
05855 lower_expr(block, WN_kid0(tree), actions),
05856 Be_Type_Tbl(rtype),
05857 WN_PARM_BY_VALUE | WN_PARM_READ_ONLY);
05858 kids[1] = WN_CreateParm (rtype,
05859 lower_expr(block, WN_kid1(tree), actions),
05860 Be_Type_Tbl(rtype),
05861 WN_PARM_BY_VALUE | WN_PARM_READ_ONLY);
05862 iwn = WN_Create_Intrinsic(OPCODE_make_op(OPR_INTRINSIC_OP,
05863 rtype, MTYPE_V),
05864 intrinsic, 2, kids);
05865
05866 if (WN_operator(tree) == OPR_MOD && !is_unsigned) {
05867
05868
05869 WN *t2, *t3, *t4;
05870 PREG_NUM t1;
05871 t1 = AssignExpr(block, iwn, type);
05872 t2 = WN_Bxor(type, WN_LdidPreg(type, t1), Load_Leaf(tmpY));
05873 t3 = WN_Ashr(type, t2, WN_Intconst(type, MTYPE_size_reg(type) - 1));
05874 t4 = WN_Band(type, Load_Leaf(tmpY), t3);
05875 iwn = WN_Add(type, WN_LdidPreg(type, t1), t4);
05876 iwn = lower_expr(block, iwn, actions);
05877 }
05878
05879 WN_Delete(tree);
05880 return iwn;
05881 }
05882 }
05883
05884 if (Action(LOWER_COMPLEX) && MTYPE_is_complex(WN_rtype(tree))) {
05885
05886
05887
05888
05889
05890 TYPE_ID cdiv_mtype = WN_rtype(tree);
05891
05892
05893
05894 TY_IDX cdiv_ty = MTYPE_To_TY(cdiv_mtype);
05895 ST *cdiv_st = Gen_Temp_Symbol (cdiv_ty, ".complex_div");
05896 WN *stid = WN_Stid(cdiv_mtype, 0, cdiv_st, cdiv_ty, tree);
05897 WN_Set_Linenum (stid, current_srcpos);
05898 stid = lower_store(block, stid, actions);
05899 WN_INSERT_BlockLast(block, stid);
05900 WN *ldid = WN_Ldid(cdiv_mtype, 0, cdiv_st, cdiv_ty);
05901 return ldid;
05902 }
05903 break;
05904
05905 case OPR_COMMA:
05906 {
05907 WN *commaBlock;
05908 commaBlock = lower_block(WN_kid0(tree), actions);
05909
05910
05911
05912
05913 if (!Action(LOWER_UPC_TO_INTR) && !Action(LOWER_UPC_INTRINSIC))
05914 DevWarn("lower_expr(): comma operator seen, line %d",
05915 Srcpos_To_Line(current_srcpos));
05916
05917 WN_INSERT_BlockLast(block, commaBlock);
05918 }
05919 return lower_expr(block, WN_kid1(tree), actions);
05920
05921 case OPR_CSELECT:
05922
05923
05924
05925 if (Action(LOWER_SHORTCIRCUIT))
05926 {
05927
05928
05929
05930
05931
05932
05933 if (expr_is_speculative(tree))
05934 {
05935 WN *select = WN_Select(type, WN_kid0(tree), WN_kid1(tree),
05936 WN_kid2(tree));
05937
05938 WN_Delete(tree);
05939 return select;
05940 }
05941 else
05942 {
05943 PREG_NUM tmpN;
05944 WN *if_tree, *if_then, *if_else, *stid;
05945 WN *body = WN_CreateBlock();
05946
05947 if_then = WN_CreateBlock();
05948 tmpN = AssignExpr(if_then, WN_kid1(tree), type);
05949
05950 if_else = WN_CreateBlock();
05951 stid = WN_StidIntoPreg(type, tmpN, MTYPE_To_PREG(type), WN_kid2(tree));
05952 WN_INSERT_BlockLast(if_else, stid);
05953
05954 if_tree = WN_CreateIf( WN_kid0(tree), if_then, if_else );
05955 if ( Cur_PU_Feedback )
05956 Cur_PU_Feedback->FB_lower_branch( tree, if_tree );
05957 WN_INSERT_BlockLast( block, lower_if( body, if_tree, actions ) );
05958
05959 return WN_LdidPreg(type, tmpN);
05960 }
05961 }
05962 break;
05963
05964 case OPR_CAND:
05965 case OPR_CIOR:
05966
05967
05968
05969 if (Action(LOWER_SHORTCIRCUIT))
05970 {
05971 if (expr_is_speculative(tree))
05972 {
05973 WN *cond;
05974
05975 if (WN_operator_is(tree, OPR_CAND))
05976 cond = WN_LAND( WN_kid0(tree), WN_kid1(tree));
05977 else
05978 cond = WN_LIOR( WN_kid0(tree), WN_kid1(tree));
05979
05980 WN_Delete(tree);
05981 return lower_expr(block, cond, actions);
05982 }
05983 else
05984 {
05985 WN *select = WN_Cselect(type,
05986 tree,
05987 WN_Intconst(Boolean_type, 1),
05988 WN_Intconst(Boolean_type, 0));
05989 return lower_expr(block, select, actions);
05990 }
05991 }
05992 break;
05993 }
05994
05995
05996 if (Action(LOWER_QUAD))
05997 {
05998 if (WN_desc(tree) == MTYPE_FQ)
05999 {
06000 switch (WN_operator(tree))
06001 {
06002 case OPR_CONST:
06003 case OPR_LDID:
06004 case OPR_ILOAD:
06005 break;
06006 case OPR_EQ:
06007 case OPR_NE:
06008 case OPR_LE:
06009 case OPR_LT:
06010 case OPR_GT:
06011 case OPR_GE:
06012 case OPR_CVT:
06013 case OPR_TRUNC:
06014 case OPR_RND:
06015 case OPR_CEIL:
06016 case OPR_FLOOR:
06017 tree = lower_emulation(block, tree, actions,intrinsic_lowered);
06018 break;
06019 default:
06020 break;
06021 }
06022 }
06023 if (WN_rtype(tree) == MTYPE_FQ)
06024 {
06025 switch (WN_operator(tree))
06026 {
06027 case OPR_CONST:
06028 case OPR_LDID:
06029 case OPR_ILOAD:
06030 break;
06031
06032 case OPR_SELECT:
06033 case OPR_NEG:
06034 case OPR_ABS:
06035 case OPR_SQRT:
06036 case OPR_ADD:
06037 case OPR_SUB:
06038 case OPR_MPY:
06039 case OPR_DIV:
06040 case OPR_MOD:
06041 case OPR_REM:
06042 case OPR_MAX:
06043 case OPR_MIN:
06044 case OPR_CVT:
06045 case OPR_TRUNC:
06046 case OPR_RND:
06047 tree = lower_emulation(block, tree, actions, intrinsic_lowered);
06048 break;
06049 default:
06050 break;
06051 }
06052 }
06053 }
06054
06055 if (WN_nary_intrinsic(tree))
06056 {
06057 tree = WN_NaryToExpr(tree);
06058 }
06059
06060
06061 if (! kids_lowered)
06062 {
06063 INT16 i;
06064 for (i = 0; i < WN_kid_count(tree); i++)
06065 WN_kid(tree,i) = lower_expr(block, WN_kid(tree,i), actions);
06066 tree = WN_Simplify_Rebuild_Expr_Tree(tree,alias_manager);
06067 }
06068
06069 return tree;
06070 }
06071
06072
06073
06074
06075
06076
06077
06078
06079
06080
06081
06082 static TY_IDX coerceTY(TY_IDX type, TYPE_ID btype)
06083 {
06084 TY &ty = Ty_Table[type];
06085
06086 if (TY_is_pointer(ty))
06087 return Make_Pointer_Type(coerceTY(TY_pointed(ty), btype));
06088
06089 return MTYPE_To_TY(btype);
06090 }
06091
06092
06093
06094
06095
06096
06097
06098
06099
06100
06101
06102
06103 static ST *coerceST(const ST *st, TYPE_ID type)
06104 {
06105 if (ST_class(st) == CLASS_PREG)
06106 {
06107
06108
06109
06110 return MTYPE_To_PREG(type);
06111 }
06112
06113 return (ST *) st;
06114 }
06115
06116 static ST *coerceST(const ST &st, TYPE_ID type)
06117 {
06118 if (ST_class(&st) == CLASS_PREG)
06119 {
06120
06121
06122
06123 return MTYPE_To_PREG(type);
06124 }
06125
06126 return (ST *) &st;
06127 }
06128
06129
06130
06131
06132
06133
06134
06135
06136
06137
06138 static BOOL WN_StoreIsUnused(WN *tree)
06139 {
06140 ST *sym;
06141
06142 switch(WN_operator(tree))
06143 {
06144 case OPR_LDA:
06145 case OPR_STID:
06146 sym = WN_st(tree);
06147
06148 if (ST_class(sym) != CLASS_PREG &&
06149 ST_class(sym) != CLASS_BLOCK &&
06150 ST_is_not_used(sym))
06151 return TRUE;
06152 break;
06153
06154 case OPR_ARRAY:
06155 return WN_StoreIsUnused(WN_array_base(tree));
06156 }
06157
06158 return FALSE;
06159 }
06160
06161
06162
06163
06164
06165
06166
06167
06168
06169 static WN *add_fake_parm(WN *o_call, WN *fake_actual, TY_IDX ty_idx)
06170 {
06171 WN *n_call;
06172 if (WN_operator(o_call) == OPR_ICALL)
06173 n_call = WN_Icall(MTYPE_V, MTYPE_V, WN_kid_count(o_call)+1, WN_ty(o_call));
06174 else
06175 n_call = WN_generic_call(WN_operator(o_call), MTYPE_V, MTYPE_V,
06176 WN_kid_count(o_call)+1, WN_st_idx(o_call));
06177 WN_call_flag(n_call) = WN_call_flag(o_call);
06178 WN_Set_Linenum(n_call, WN_Get_Linenum(o_call));
06179 if ( Cur_PU_Feedback ) {
06180 Cur_PU_Feedback->FB_lower_call( o_call, n_call );
06181 }
06182 WN_kid0(n_call) = WN_CreateParm(Pointer_Mtype, fake_actual, ty_idx,
06183 WN_PARM_BY_REFERENCE | WN_PARM_PASSED_NOT_SAVED);
06184 for (INT32 i = 0; i < WN_kid_count(o_call); i++)
06185 WN_kid(n_call, i+1) = WN_COPY_Tree(WN_kid(o_call, i));
06186 return n_call;
06187 }
06188
06189
06190
06191
06192
06193
06194
06195
06196
06197
06198 static WN *lower_return_mstid(WN *block, WN *tree, LOWER_ACTIONS actions)
06199 {
06200 TYPE_ID mtype;
06201 ST *preg_st;
06202 WN *n_rhs;
06203 WN *wn = NULL;
06204 RETURN_INFO return_info = Get_Return_Info(WN_ty(tree), Complex_Not_Simulated);
06205 if (RETURN_INFO_return_via_first_arg(return_info)) {
06206
06207 WN *call = WN_last(block);
06208 Is_True(WN_operator(call) == OPR_CALL || WN_operator(call) == OPR_ICALL ||
06209 WN_operator(call) == OPR_PICCALL,
06210 ("statement preceding MMLDID of Return_Val_Preg must be a call"));
06211 Is_True(WN_rtype(call) == MTYPE_M,
06212 ("call preceding MMLDID of Return_Val_Preg not type M"));
06213 WN *awn = WN_CreateLda(OPR_LDA, Pointer_Mtype, MTYPE_V,
06214 WN_store_offset(tree),
06215 Make_Pointer_Type(WN_ty(tree)), WN_st_idx(tree));
06216 awn = lower_expr(block, awn, actions);
06217 WN *n_call = add_fake_parm(call, awn, WN_ty(awn));
06218 WN_DELETE_FromBlock(block, call);
06219 WN_INSERT_BlockLast(block, n_call);
06220
06221 WN_DELETE_Tree(tree);
06222 return NULL;
06223 }
06224 else {
06225 for (INT32 i = 0; i < RETURN_INFO_count(return_info); i++) {
06226 if (i != 0)
06227 WN_INSERT_BlockLast (block, wn);
06228 mtype = RETURN_INFO_mtype(return_info, i);
06229 preg_st = MTYPE_is_float(mtype) ? Float_Preg : Int_Preg;
06230 n_rhs = WN_CreateLdid(OPR_LDID, mtype, mtype,
06231 RETURN_INFO_preg(return_info, i), preg_st,
06232 Be_Type_Tbl(mtype));
06233 if (TY_align(ST_type(WN_st(tree))) < MTYPE_alignment(mtype)) {
06234
06235
06236
06237 if(ST_type(WN_st(tree)) != shared_ptr_idx && ST_type(WN_st(tree)) != pshared_ptr_idx)
06238 DevWarn("return_info struct alignment is smaller than register size, may produce wrong results");
06239 }
06240 wn = WN_CreateStid(OPR_STID, MTYPE_V, mtype,
06241 WN_store_offset(tree)+i*MTYPE_byte_size(mtype),
06242 WN_st_idx(tree), Be_Type_Tbl(mtype), n_rhs);
06243 wn = lower_store (block, wn, actions);
06244 WN_Set_Linenum (wn, WN_Get_Linenum(tree));
06245 }
06246 WN_DELETE_Tree(tree);
06247 return wn;
06248 }
06249 }
06250
06251
06252
06253
06254
06255
06256
06257
06258
06259
06260 static WN *lower_return_mistore(WN *block, WN *tree, LOWER_ACTIONS actions)
06261 {
06262 TYPE_ID mtype;
06263 ST *preg_st;
06264 WN *n_rhs;
06265 WN *wn = NULL;
06266 RETURN_INFO return_info = Get_Return_Info(WN_ty(tree), Complex_Not_Simulated);
06267 if (RETURN_INFO_return_via_first_arg(return_info)) {
06268
06269 WN *call = WN_last(block);
06270 Is_True(WN_operator(call) == OPR_CALL || WN_operator(call) == OPR_ICALL ||
06271 WN_operator(call) == OPR_PICCALL,
06272 ("statement preceding MMLDID of Return_Val_Preg must be a call"));
06273 Is_True(WN_rtype(call) == MTYPE_M,
06274 ("call preceding MMLDID of Return_Val_Preg not type M"));
06275 WN *awn = WN_COPY_Tree(WN_kid1(tree));
06276 if (WN_store_offset(tree) != 0) {
06277 WN *iwn = WN_CreateIntconst(OPR_INTCONST, Pointer_Mtype, MTYPE_V,
06278 WN_store_offset(tree));
06279 awn = WN_CreateExp2(OPR_ADD, Pointer_Mtype, Pointer_Mtype, awn, iwn);
06280 }
06281 awn = lower_expr(block, awn, actions);
06282 WN *n_call = add_fake_parm(call, awn, WN_ty(tree));
06283 WN_DELETE_FromBlock(block, call);
06284 WN_INSERT_BlockLast(block, n_call);
06285
06286 WN_DELETE_Tree(tree);
06287 return NULL;
06288 }
06289 else {
06290 WN *base_expr;
06291 for (INT32 i = 0; i < RETURN_INFO_count(return_info); i++) {
06292 if (i != 0)
06293 WN_INSERT_BlockLast (block, wn);
06294 mtype = RETURN_INFO_mtype(return_info, i);
06295 preg_st = MTYPE_is_float(mtype) ? Float_Preg : Int_Preg;
06296 n_rhs = WN_CreateLdid(OPR_LDID, mtype, mtype,
06297 RETURN_INFO_preg(return_info, i), preg_st,
06298 Be_Type_Tbl(mtype));
06299 base_expr = WN_COPY_Tree(WN_kid1(tree));
06300 wn = WN_CreateIstore(OPR_ISTORE, MTYPE_V, mtype,
06301 WN_store_offset(tree)+i*MTYPE_byte_size(mtype),
06302 Be_Type_Tbl(mtype), n_rhs, base_expr);
06303 wn = lower_store (block, wn, actions);
06304 WN_Set_Linenum (wn, WN_Get_Linenum(tree));
06305 }
06306 WN_DELETE_Tree(tree);
06307 return wn;
06308 }
06309 }
06310
06311
06312
06313
06314
06315
06316
06317
06318
06319
06320 static WN *lower_mstid(WN *block, WN *tree, LOWER_ACTIONS actions)
06321 {
06322 TY_IDX ty_idx = WN_ty(tree);
06323 TY_IDX pty_idx = WN_field_id(tree) == 0 ? 0 : get_field_type (ty_idx, WN_field_id(tree));
06324 UINT64 size = pty_idx == 0 ? TY_size(ty_idx): TY_size(pty_idx );
06325
06326
06327 if(Action(LOWER_UPC_MFIELD) && pty_idx && Type_Is_Shared_Ptr(pty_idx))
06328 size = TY_size(TY_To_Sptr_Idx(pty_idx));
06329
06330 WN* wn;
06331 WN* awn;
06332 WN* swn;
06333 WN *rhs = WN_kid0(tree);
06334
06335
06336
06337
06338
06339 if(Type_Is_Shared_Ptr(ty_idx) && WN_operator(rhs) == OPR_LDID &&
06340 WN_st(rhs) == Return_Val_Preg ) {
06341 ty_idx = TY_To_Sptr_Idx(ty_idx);
06342 TYPE_ID rtype = TY_mtype(ty_idx);
06343 WN_set_desc(tree, rtype);
06344
06345 WN_set_ty(tree, ty_idx);
06346
06347 WN_set_desc(rhs, rtype);
06348 WN_set_rtype(rhs, rtype);
06349 WN_set_ty(rhs, TY_To_Sptr_Idx(WN_ty(rhs)));
06350 }
06351
06352
06353 Is_True((WN_operator(tree) == OPR_STID && WN_desc(tree) == MTYPE_M),
06354 ("expected mstid node, not %s", OPCODE_name(WN_opcode(tree))));
06355
06356 pty_idx = Make_Pointer_Type (ty_idx, FALSE);
06357
06358 if (WN_opcode(rhs) == OPC_MMLDID && WN_st(rhs) == Return_Val_Preg) {
06359
06360 Is_True(Action(LOWER_RETURN_VAL),
06361 ("LOWER_RETURN_VAL action must be specified"));
06362 return lower_return_mstid(block, tree, actions);
06363 }
06364
06365 awn = WN_CreateLda (OPR_LDA, Pointer_Mtype, MTYPE_V, 0
06366 ,
06367 pty_idx, WN_st(tree));
06368 swn = WN_CreateIntconst (OPC_U4INTCONST, size);
06369 wn = WN_CreateMstore (WN_store_offset(tree)
06370 , pty_idx, WN_kid0(tree), awn, swn);
06371 WN_set_field_id(wn, WN_field_id(tree));
06372
06373
06374 wn = lower_store (block, wn, actions);
06375
06376 WN_Delete(tree);
06377 return wn;
06378 }
06379
06380
06381
06382
06383
06384
06385
06386
06387
06388
06389
06390 static WN *lower_mistore(WN *block, WN *tree, LOWER_ACTIONS actions)
06391 {
06392 TY_IDX pty_idx = WN_ty(tree);
06393 TY_IDX ty_idx = TY_pointed(pty_idx);
06394
06395 if (WN_field_id (tree) != 0)
06396 ty_idx = get_field_type (ty_idx, WN_field_id (tree));
06397
06398 UINT64 size = TY_size(Ty_Table[ty_idx]);
06399 if(Action(LOWER_UPC_MFIELD) && WN_field_id(tree) && Type_Is_Shared_Ptr(ty_idx))
06400 size = TY_size(TY_To_Sptr_Idx(ty_idx));
06401 WN* wn;
06402 WN* swn;
06403
06404 Is_True((WN_operator(tree) == OPR_ISTORE && WN_desc(tree) == MTYPE_M),
06405 ("expected mistore node, not %s", OPCODE_name(WN_opcode(tree))));
06406 Is_True(TY_kind(pty_idx) == KIND_POINTER,
06407 ("type specified in MISTORE not pointer"));
06408
06409 if (size == 0)
06410 DevWarn ("type in MISTORE cannot be zero size");
06411 WN *rhs = WN_kid0(tree);
06412 if (WN_opcode(rhs) == OPC_MMLDID && WN_st(rhs) == Return_Val_Preg) {
06413
06414 Is_True(Action(LOWER_RETURN_VAL),
06415 ("LOWER_RETURN_VAL action must be specified"));
06416 return lower_return_mistore(block, tree, actions);
06417 }
06418
06419 swn = WN_CreateIntconst(OPC_U4INTCONST, size);
06420 wn = WN_CreateMstore(WN_offset(tree), pty_idx,
06421 WN_COPY_Tree(WN_kid0(tree)),
06422 WN_COPY_Tree(WN_kid1(tree)), swn);
06423 WN_set_field_id(wn, WN_field_id(tree));
06424 wn = lower_store(block, wn, actions);
06425
06426 WN_DELETE_Tree (tree);
06427 return wn;
06428 }
06429
06430
06431
06432
06433
06434
06435
06436
06437
06438
06439
06440 static TY_IDX struct_addr_ty(WN* tree) {
06441
06442 if (WN_operator(tree) == OPR_ADD &&
06443 WN_operator(WN_kid0(tree)) == OPR_LDID) {
06444 TY_IDX addr_ty = WN_ty(WN_kid0(tree));
06445 if (TY_kind(addr_ty) == KIND_POINTER &&
06446 TY_kind(TY_pointed(addr_ty)) == KIND_STRUCT) {
06447 return TY_pointed(addr_ty);
06448 }
06449 }
06450 return 0;
06451 }
06452
06453 static int find_field_from_offset(TY_IDX ty, unsigned int offset) {
06454
06455 Is_True(TY_kind(ty) == KIND_STRUCT, ("TY is not a struct", ""));
06456 int cur_field = 1;
06457 FLD_ITER fld_iter = Make_fld_iter(TY_fld(ty));
06458 do {
06459 FLD_HANDLE fld(fld_iter);
06460 if (FLD_ofst(fld) == offset) {
06461 return cur_field;
06462 }
06463 if (FLD_ofst(fld) > offset) {
06464 fprintf(stderr, "can't find field with exact same offset in find_field_from_offset\n");
06465 return cur_field - 1;
06466 }
06467 TY_IDX fld_ty = FLD_type(fld);
06468 if (TY_kind(fld_ty) == KIND_STRUCT && !is_upcr_ptr(fld_ty) &&
06469 TY_fld(fld_ty) != FLD_HANDLE() && offset < (FLD_ofst(fld) + TY_size(fld_ty)) ) {
06470 return cur_field + find_field_from_offset(fld_ty, offset - FLD_ofst(fld));
06471 }
06472 cur_field++;
06473 } while (!FLD_last_field(fld_iter++));
06474 return -1;
06475 }
06476
06477
06478
06479
06480
06481
06482
06483
06484
06485
06486
06487 static WN *lower_store(WN *block, WN *tree, LOWER_ACTIONS actions)
06488 {
06489 BOOL kids_lowered = FALSE;
06490
06491 Is_True(OPCODE_is_store(WN_opcode(tree)),
06492 ("expected store node, not %s", OPCODE_name(WN_opcode(tree))));
06493
06494
06495
06496
06497
06498 if (Action(LOWER_TO_CG))
06499 {
06500 WN *tas = WN_kid0(tree);
06501 if ( WN_operator(tas) == OPR_TAS
06502 && (!WN_has_sym(tree) || WN_class(tree) != CLASS_PREG))
06503 {
06504 WN *tas_kid0 = WN_kid0(tas);
06505 TYPE_ID tas_kid0_rtype = WN_rtype(tas_kid0);
06506 if (MTYPE_byte_size(WN_rtype(tas)) == MTYPE_byte_size(tas_kid0_rtype)) {
06507 WN_set_desc(tree, tas_kid0_rtype);
06508 WN_kid0(tree) = tas_kid0;
06509 WN_Delete(tas);
06510 }
06511 }
06512 }
06513
06514
06515
06516
06517 lower_map(tree, actions);
06518
06519
06520
06521
06522
06523
06524
06525 switch (WN_operator(tree))
06526 {
06527 case OPR_ISTORE: {
06528 if (WN_StoreIsUnused(WN_kid1(tree)))
06529 {
06530 WN *eval;
06531
06532 eval = lower_eval(block, WN_CreateEval(WN_kid0(tree)), actions);
06533
06534 WN_Delete(tree);
06535
06536 return eval;
06537 }
06538
06539 if (Action(LOWER_MLDID_MSTID) && WN_desc(tree) == MTYPE_M)
06540 return lower_mistore(block, tree, actions);
06541
06542 if (Action(LOWER_BIT_FIELD_ID) && WN_desc(tree) == MTYPE_BS) {
06543 lower_bit_field_id(tree);
06544 if (Action(LOWER_BITS_OP) && WN_operator (tree) == OPR_ISTBITS)
06545 return lower_store_bits (block, tree, actions);
06546 }
06547
06548 if (Action(LOWER_COMPLEX) && MTYPE_is_complex(WN_desc(tree)))
06549 {
06550 WN *realstore, *imagstore;
06551 LEAF realexpN, imagexpN;
06552 WN_OFFSET offset = WN_store_offset(tree);
06553 TYPE_ID realTY = Mtype_complex_to_real( WN_desc(tree));
06554 {
06555
06556
06557
06558
06559
06560 WN *realexp, *imagexp;
06561
06562 lower_complex_expr(block, WN_kid0(tree), actions, &realexp, &imagexp);
06563
06564 realexpN = Make_Leaf(block, realexp, realTY);
06565 imagexpN = Make_Leaf(block, imagexp, realTY);
06566 }
06567
06568 if (Action(LOWER_BASE_INDEX))
06569 {
06570 WN *base, *index, *addr;
06571 LEAF indexN;
06572
06573 base = index= NULL;
06574 lower_to_base_index(WN_kid1(tree), &base, &index) ;
06575
06576 base = lower_expr(block, base, actions);
06577 index = lower_expr(block, index, actions);
06578
06579 indexN = Make_Leaf(block, index, Pointer_type);
06580
06581 addr = WN_Add(Pointer_type,
06582 Load_Leaf(indexN),
06583 lower_copy_tree(base, actions));
06584
06585 realstore = WN_Istore(realTY,
06586 offset,
06587 coerceTY(WN_ty(tree), realTY),
06588 addr,
06589 Load_Leaf(realexpN));
06590
06591 addr = WN_Add(Pointer_type, Load_Leaf(indexN), base);
06592
06593 imagstore = WN_Istore(realTY,
06594 coerceOFFSET(tree, realTY, offset),
06595 coerceTY(WN_ty(tree), realTY),
06596 addr,
06597 Load_Leaf(imagexpN));
06598 }
06599 else
06600 {
06601 WN *addr;
06602 LEAF addrN;
06603
06604 addr = lower_expr(block, WN_kid1(tree), actions);
06605 addrN = Make_Leaf(block, addr, Pointer_type);
06606
06607 realstore = WN_Istore(realTY,
06608 offset,
06609 coerceTY(WN_ty(tree), realTY),
06610 Load_Leaf(addrN),
06611 Load_Leaf(realexpN));
06612
06613 imagstore = WN_Istore(realTY,
06614 coerceOFFSET(tree, realTY, offset),
06615 coerceTY(WN_ty(tree), realTY),
06616 Load_Leaf(addrN),
06617 Load_Leaf(imagexpN));
06618 }
06619 realstore = lower_store(block, realstore, actions);
06620 WN_Set_Linenum (realstore, WN_Get_Linenum(tree));
06621 WN_INSERT_BlockLast(block, realstore);
06622
06623 imagstore = lower_store(block, imagstore, actions);
06624 lower_complex_maps(tree, realstore, imagstore, actions);
06625 WN_Delete(tree);
06626
06627 return imagstore;
06628 }
06629 else if (Action(LOWER_QUAD) && MTYPE_is_quad(WN_desc(tree)))
06630 {
06631 WN *hi, *lo, *hipart, *lopart;
06632 TYPE_ID realTY = MTYPE_F8;
06633 WN_OFFSET offset = WN_load_offset(tree);
06634
06635 lower_quad_expr(block, WN_kid0(tree), actions, &hi, &lo);
06636
06637 if (Action(LOWER_BASE_INDEX))
06638 {
06639 WN *addr, *base, *index;
06640 LEAF indexN;
06641
06642 base = index = NULL;
06643 lower_to_base_index(WN_kid1(tree), &base, &index) ;
06644
06645 base = lower_expr(block, base, actions);
06646 index = lower_expr(block, index, actions);
06647
06648 indexN = Make_Leaf(block, index, Pointer_type);
06649
06650 addr = WN_Add(Pointer_type,
06651 Load_Leaf(indexN),
06652 lower_copy_tree(base, actions));
06653
06654 hipart = WN_Istore(realTY,
06655 offset,
06656 coerceTY(WN_ty(tree), realTY),
06657 addr,
06658 hi);
06659
06660 addr = WN_Add(Pointer_type, Load_Leaf(indexN), base);
06661
06662 lopart = WN_Istore(realTY,
06663 coerceOFFSET(tree, realTY, offset),
06664 coerceTY(WN_ty(tree), realTY),
06665 addr,
06666 lo);
06667 }
06668 else
06669 {
06670 WN *addr;
06671 LEAF addrN;
06672
06673 addr = lower_expr(block, WN_kid1(tree), actions);
06674
06675 addrN = Make_Leaf(block, addr, Pointer_type);
06676
06677 hipart = WN_Istore(realTY,
06678 offset,
06679 coerceTY(WN_ty(tree), realTY),
06680 Load_Leaf(addrN),
06681 hi);
06682
06683 lopart = WN_Istore(realTY,
06684 coerceOFFSET(tree, realTY, offset),
06685 coerceTY(WN_ty(tree), realTY),
06686 Load_Leaf(addrN),
06687 lo);
06688 }
06689 hipart = lower_store(block, hipart, actions);
06690 WN_Set_Linenum (hipart, WN_Get_Linenum(tree));
06691 WN_INSERT_BlockLast(block, hipart);
06692
06693 lopart = lower_store(block, lopart, actions);
06694 lower_quad_maps(tree, hipart, lopart, actions);
06695 WN_Delete(tree);
06696 return lopart;
06697 }
06698 else if (Action(LOWER_SPLIT_CONST_OFFSETS))
06699 {
06700
06701
06702
06703
06704
06705
06706
06707
06708
06709
06710 WN_OFFSET offset = WN_store_offset(tree);
06711
06712 if (mem_offset_must_be_split(offset))
06713 {
06714 WN_kid1(tree) = WN_Add(Pointer_type, WN_kid1(tree),
06715 WN_Intconst(Pointer_type,
06716 mem_offset_hi(offset)));
06717 WN_store_offset(tree) = mem_offset_lo(offset);
06718 }
06719 }
06720 else {
06721
06722
06723
06724
06725
06726
06727
06728
06729
06730
06731 WN *addr_kid = WN_kid1(tree);
06732
06733 if (foldLdaOffset(addr_kid, WN_store_offset(tree)))
06734 {
06735 WN_store_offset(tree) += WN_lda_offset(addr_kid);
06736 WN_lda_offset(addr_kid) = 0;
06737 }
06738
06739
06740
06741
06742
06743
06744
06745
06746
06747
06748 if (WN_operator_is(addr_kid, OPR_ADD) &&
06749 foldConstOffset(WN_kid1(addr_kid), WN_store_offset(tree)))
06750 {
06751 WN_store_offset(tree) += WN_const_val(WN_kid1(addr_kid));
06752 WN_kid1(tree) = WN_kid0(addr_kid);
06753 TY_IDX obj_ty = struct_addr_ty(WN_kid1(tree));
06754 if (obj_ty != 0) {
06755
06756 int field_id = find_field_from_offset(obj_ty, WN_store_offset(tree));
06757 WN_store_offset(tree) = Adjust_Field_Offset(obj_ty, field_id);
06758
06759 }
06760 WN_Delete(WN_kid1(addr_kid));
06761 WN_Delete(addr_kid);
06762 }
06763 }
06764 if ( Action(LOWER_UPC_TO_INTR) ) {
06765
06766 TY_IDX idx = WN_ty(tree);
06767 TY_IDX dst_idx = 0;
06768 if(Type_Is_Shared_Ptr(idx)) {
06769 TY_IDX src_idx = WN_ty(WN_kid1(tree));
06770 WN *ist;
06771 BOOL do_arith = TRUE;
06772 BOOL is_field = FALSE;
06773 WN *offt = 0;
06774
06775 SPTR_ACCUMULATION_STATE saved_acc_state = sptr_accumulation_state;
06776 sptr_accumulation_state = ACCUMULATION;
06777 sptr_off_accumulation_stack.push(CXX_NEW(SPTR_OFFSET_TERM_STACK, Malloc_Mem_Pool));
06778 SPTR_OFFSET_TERM_STACK *term_stack = sptr_off_accumulation_stack.top();
06779 WN *kid1 = WN_kid1(tree);
06780
06781 if((WN_operator(kid1) == OPR_LDID && !WN_offset(tree)) ||
06782 WN_operator(kid1) == OPR_ARRAY ||
06783
06784
06785 ( WN_operator(kid1) == OPR_TAS && WN_operator(WN_kid0(kid1)) == OPR_LDA &&
06786 TY_kind(TY_pointed(WN_ty(WN_kid0(kid1)))) == KIND_ARRAY) )
06787 do_arith = FALSE;
06788
06789 if(WN_offset(tree)) {
06790 offt = WN_Intconst(Integer_type,
06791 WN_field_id(tree) > 1 ? Adjust_Field_Offset(TY_pointed(WN_ty(tree)), WN_field_id(tree)) : WN_offset(tree));
06792 WN_offset(tree) = 0;
06793 }
06794
06795 dst_idx = (OPERATOR_is_load(WN_operator(WN_kid0(tree))) ||
06796 WN_operator(WN_kid0(tree)) == OPR_TAS) ?
06797 WN_ty(WN_kid0(tree)) : dst_idx;
06798 sptr_accumulation_state = NO_ACCUMULATION;
06799 WN_kid0(tree) = lower_expr(block, WN_kid0(tree), actions);
06800
06801 sptr_accumulation_state = ACCUMULATION;
06802 WN_kid1(tree) = lower_expr(block, WN_kid1(tree), actions);
06803
06804
06805 INTRINSIC iop;
06806 if(src_idx && dst_idx &&
06807 Type_Is_Shared_Ptr(src_idx, TRUE) &&
06808 Type_Is_Shared_Ptr(dst_idx, TRUE) &&
06809 Need_StoP_Cvt(dst_idx, src_idx, &iop)) {
06810 WN_kid0(tree) = WN_Create_StoP_Cvt(WN_kid0(tree), iop);
06811 }
06812
06813 if(WN_operator(WN_kid1(tree)) == OPR_TAS) {
06814 dst_idx = WN_ty(WN_kid1(tree));
06815 WN_set_ty(tree, dst_idx);
06816 WN_kid1(tree) = Strip_TAS(WN_kid1(tree));
06817 } else
06818 dst_idx = WN_ty(tree);
06819
06820
06821
06822
06823
06824
06825 if (do_arith) {
06826 ist = Combine_Offset_Terms(*term_stack);
06827 if (WN_operator(WN_kid1(tree)) == OPR_LDID) {
06828 src_idx = ST_type(WN_st(WN_kid1(tree)));
06829 is_field = WN_field_id(tree)-1;
06830 } else if (WN_operator(WN_kid1(tree)) == OPR_COMMA) {
06831 Is_True(src_idx, ("",""));
06832 } else
06833 Is_True(src_idx,("",""));
06834
06835 UINT esize = Get_Type_Inner_Size(idx);
06836
06837
06838 if(dst_idx && Type_Is_Shared_Ptr(dst_idx, TRUE) &&
06839 TY_size(TY_pointed(dst_idx)) == 1 && Get_Type_Block_Size(dst_idx) == 0) {
06840 Is_True(Get_Type_Block_Size(idx) == 0, ("",""));
06841 esize = 1;
06842 }
06843
06844 if(TY_kind(idx) == KIND_POINTER && TY_is_shared(TY_pointed(idx)) &&
06845 TY_kind(TY_pointed(idx)) == KIND_POINTER)
06846 esize = TY_size(TY_To_Sptr_Idx(idx));
06847
06848 if(ist && TY_kind(dst_idx) == KIND_POINTER &&
06849 Types_Are_Equiv( dst_idx, src_idx) ) {
06850 WN_kid1(tree) = WN_Create_Shared_Ptr_Arithmetic (WN_kid1(tree), ist, OPR_ADD,
06851 esize,
06852 Get_Type_Block_Size(idx),
06853 Get_Type_Block_Size(idx) <= 1);
06854
06855 if(offt) {
06856 ist = offt;
06857 } else
06858 do_arith = FALSE;
06859
06860 } else if(offt)
06861 ist = offt;
06862 }
06863
06864 sptr_accumulation_state = saved_acc_state;
06865 sptr_off_accumulation_stack.pop();
06866 CXX_DELETE(term_stack, Malloc_Mem_Pool);
06867
06868 if(!ist)
06869 do_arith = FALSE;
06870 ist = WN_Create_Shared_Store (tree, FALSE, 0, do_arith , ist);
06871 WN_Delete(tree);
06872 return ist;
06873 } else if (WN_Type_Is_Shared_Ptr(WN_kid0(tree)) || WN_operator(WN_kid0(tree)) == OPR_TAS)
06874 {
06875
06876 WN *kid0 = lower_expr(block,
06877 WN_operator(WN_kid0(tree)) == OPR_TAS ? WN_kid0(WN_kid0(tree)) :
06878 WN_kid0(tree),
06879 actions);
06880 if (TY_kind(WN_object_ty(WN_kid0(tree))) == KIND_SCALAR)
06881 WN_kid0(tree) = kid0;
06882 else {
06883 if(OPERATOR_is_load(WN_operator(WN_kid0(tree))) && WN_field_id(WN_kid0(tree)))
06884 WN_kid0(tree) = kid0;
06885 else {
06886 idx = WN_field_id(tree) ?
06887 get_field_type(TY_pointed(WN_ty(tree)), WN_field_id(tree)) :
06888 WN_ty(tree) ;
06889 if(!Type_Is_Shared_Ptr(idx)) {
06890 if(!(TY_kind(idx) == KIND_POINTER && Type_Is_Shared_Ptr(TY_pointed(idx), TRUE)))
06891
06892
06893 WN_kid0(tree) = WN_Convert_Shared_To_Local(kid0, WN_ty(tree), 0);
06894 else WN_kid0(tree) = kid0;
06895 } else if(WN_field_id(tree) && !Type_Is_Shared_Ptr(WN_ty(tree)) &&
06896 Type_Is_Shared_Ptr(idx, TRUE)){
06897
06898
06899 dst_idx = TY_To_Sptr_Idx(idx);
06900 INTRINSIC iop = INTRINSIC_LAST;
06901 if((Type_Is_Shared_Ptr(WN_ty(kid0)) &&
06902 Need_StoP_Cvt(WN_ty(kid0), idx, &iop) ) ||
06903 Need_StoP_Cvt(WN_ty(WN_kid0(tree)), idx, &iop))
06904 kid0 = WN_Create_StoP_Cvt(Strip_TAS(kid0), iop);
06905
06906 if(TY_mtype(dst_idx) == MTYPE_M) {
06907 WN_set_rtype(tree, MTYPE_V);
06908 WN_set_desc(tree, MTYPE_M);
06909 WN_store_offset(tree) = Adjust_Field_Offset(TY_pointed(WN_ty(tree)),
06910 WN_field_id(tree));
06911
06912
06913 WN_kid0(tree) = kid0;
06914 }
06915 }
06916 }
06917 }
06918 WN_kid1(tree) = lower_expr(block, WN_kid1(tree), actions);
06919 return tree;
06920 } else if(WN_field_id(tree) > 1)
06921 WN_store_offset(tree) = Adjust_Field_Offset(TY_pointed(WN_ty(tree)),
06922 WN_field_id(tree));
06923 }
06924 break;
06925 }
06926 case OPR_STID:
06927 {
06928 PREG_NUM last_preg = Get_Preg_Num (PREG_Table_Size(CURRENT_SYMTAB));
06929
06930 if ((WN_class(tree) == CLASS_PREG) &&
06931 (WN_store_offset(tree) > last_preg))
06932 {
06933 DevWarn("lower_store() pregno %d > SYMTAB_last_preg(%d)",
06934 WN_load_offset(tree), last_preg);
06935 }
06936 }
06937
06938 if (WN_StoreIsUnused(tree))
06939 {
06940 WN *eval;
06941
06942 eval = lower_eval(block, WN_CreateEval(WN_kid0(tree)), actions);
06943
06944 WN_Delete(tree);
06945
06946 return eval;
06947 }
06948
06949 if (Action(LOWER_MLDID_MSTID) && WN_desc(tree) == MTYPE_M)
06950 return lower_mstid(block, tree, actions);
06951
06952 if (Action(LOWER_MLDID_MSTID) && WN_Type_Is_Shared_Ptr(tree) &&
06953 TY_mtype(TY_To_Sptr_Idx(WN_ty(tree))) == MTYPE_M &&
06954 WN_operator(WN_kid0(tree)) == OPR_LDID && WN_st(WN_kid0(tree)) == Return_Val_Preg)
06955 return lower_mstid(block, tree, actions);
06956
06957 if (Action(LOWER_BIT_FIELD_ID) && WN_desc(tree) == MTYPE_BS) {
06958 lower_bit_field_id(tree);
06959 if (Action(LOWER_BITS_OP) && WN_operator (tree) == OPR_STBITS)
06960 return lower_store_bits (block, tree, actions);
06961 }
06962
06963 if (Action(LOWER_COMPLEX) && MTYPE_is_complex(WN_desc(tree)))
06964 {
06965 WN *realexp, *imagexp;
06966 TYPE_ID realTY;
06967
06968 realTY = Mtype_complex_to_real( WN_desc(tree));
06969 lower_complex_expr(block, WN_kid0(tree), actions, &realexp, &imagexp);
06970
06971
06972
06973
06974
06975
06976 {
06977 WN_OFFSET offset = WN_store_offset(tree);
06978 PREG_NUM realexpN, imagexpN;
06979 WN *wn;
06980 WN *realexp_copy,*imagexp_copy;
06981
06982 if (WN_operator(realexp) == OPR_CONST) {
06983 realexp_copy = realexp;
06984 } else {
06985 realexpN = AssignExpr(block, realexp, realTY);
06986 realexp_copy = WN_LdidPreg(realTY, realexpN);
06987 }
06988
06989 if (WN_operator(imagexp) == OPR_CONST) {
06990 imagexp_copy = imagexp;
06991 } else {
06992 imagexpN = AssignExpr(block, imagexp, realTY);
06993 imagexp_copy = WN_LdidPreg(realTY, imagexpN);
06994 }
06995
06996 wn = WN_Stid(realTY,
06997 offset,
06998 coerceST(WN_st(tree), realTY),
06999 MTYPE_To_TY(realTY),
07000 realexp_copy);
07001
07002 realexp = lower_store(block, wn, actions);
07003 WN_Set_Linenum (realexp, WN_Get_Linenum(tree));
07004 WN_INSERT_BlockLast(block, realexp);
07005
07006 wn = WN_Stid(realTY,
07007 coerceOFFSET(tree, realTY, offset),
07008 coerceST(WN_st(tree), realTY),
07009 MTYPE_To_TY(realTY),
07010 imagexp_copy);
07011
07012 imagexp = lower_store(block, wn, actions);
07013
07014 lower_complex_maps(tree, realexp, imagexp, actions);
07015
07016 WN_Delete(tree);
07017
07018 return imagexp;
07019 }
07020 }
07021
07022 else if (Action(LOWER_QUAD) && MTYPE_is_quad(WN_desc(tree)))
07023 {
07024 WN_OFFSET offset = WN_store_offset(tree);
07025 WN *hiexp, *loexp, *wn, *hipart, *lopart;
07026 TYPE_ID realTY = MTYPE_F8;
07027
07028 lower_quad_expr(block, WN_kid0(tree), actions, &hiexp, &loexp);
07029
07030
07031
07032
07033 wn = WN_Stid(realTY,
07034 offset,
07035 coerceST(WN_st(tree), realTY),
07036 MTYPE_To_TY(realTY), hiexp);
07037
07038 hipart = lower_store(block, wn, actions);
07039 WN_Set_Linenum (hipart, WN_Get_Linenum(tree));
07040 WN_INSERT_BlockLast(block, hipart);
07041
07042 wn = WN_Stid(realTY,
07043 coerceOFFSET(tree, realTY, offset),
07044 coerceST(WN_st(tree), realTY),
07045 MTYPE_To_TY(realTY), loexp);
07046 lopart = lower_store(block, wn, actions);
07047
07048 lower_quad_maps(tree, hipart, lopart, actions);
07049
07050 WN_Delete(tree);
07051
07052 return lopart;
07053 }
07054
07055 if (Action(LOWER_SPLIT_SYM_ADDRS))
07056 {
07057
07058
07059
07060
07061
07062 WN *istore;
07063
07064 istore = lower_split_sym_addrs(tree, WN_store_offset(tree), actions);
07065 if (istore)
07066 {
07067 return lower_store(block, istore, actions);
07068 }
07069 }
07070
07071 if ( Action(LOWER_FORMAL_REF) && WN_class(tree) == CLASS_VAR)
07072 {
07073 WN *istore;
07074
07075 istore = lower_formal_ref(tree, WN_store_offset(tree),
07076 WN_st(tree), actions);
07077 if (istore)
07078 {
07079 return lower_store(block, istore, actions);
07080 }
07081 }
07082
07083 if ( Action(LOWER_UPLEVEL))
07084 {
07085 ST *sym = WN_st(tree);
07086
07087 if (ST_is_uplevelTemp(sym))
07088 {
07089 WN *istore;
07090
07091 istore = lower_uplevel_reference(tree, WN_store_offset(tree), actions);
07092 return lower_store(block, istore, actions);
07093 }
07094 }
07095
07096 if(Action(LOWER_UPC_TO_INTR)){
07097 INTRINSIC iop = INTRINSIC_LAST;
07098 if( TY_is_shared(ST_type(WN_st(tree)))) {
07099 WN_kid0(tree) = lower_expr(block, WN_kid0(tree), actions);
07100 if(WN_operator(WN_kid0(tree)) == OPR_COMMA)
07101 WN_kid0(tree) = Spill_Shared_Load(WN_kid0(tree));
07102 TY_IDX rhs_idx = WN_ty(WN_kid0(tree));
07103 bool both_shared = false;
07104
07105
07106
07107
07108 WN *ical = WN_Create_Shared_Store(tree, both_shared);
07109 WN_Delete(tree);
07110 kids_lowered = TRUE;
07111 return ical;
07112 } else if (TY_kind(WN_ty(tree)) == KIND_POINTER && TY_is_shared(TY_pointed(WN_ty(tree))) ||
07113 TY_kind(WN_ty(tree)) == KIND_ARRAY && TY_is_shared(TY_etype(WN_ty(tree))) ) {
07114
07115 TY_IDX base_idx = TY_kind(WN_ty(tree)) == KIND_POINTER ? TY_pointed(WN_ty(tree)) : TY_etype(WN_ty(tree));
07116 TY_IDX real_ty = TY_is_pshared(base_idx) ? pshared_ptr_idx : shared_ptr_idx;
07117
07118 WN *kid0 = WN_kid0(tree);
07119
07120 if(TY_kind(WN_ty(tree)) == KIND_POINTER && WN_operator(kid0) == OPR_TAS &&
07121 WN_operator(WN_kid0(kid0)) == OPR_INTCONST) {
07122 WN_kid0(tree) = kid0 = Strip_TAS(kid0);
07123 Is_True(WN_const_val(kid0) == 0, ("Setting a shared ptr to a constant different from NULL",""));
07124 return WN_SetNull_Sptr(tree);
07125 } else if(Type_Is_Shared_Ptr(WN_ty(kid0)) && Need_StoP_Cvt(WN_ty(kid0), WN_ty(tree), &iop)) {
07126 kids_lowered = TRUE;
07127 WN_kid0(tree) = WN_Create_StoP_Cvt(lower_expr(block, kid0,actions), iop);
07128 }
07129
07130 WN_set_ty(tree, real_ty);
07131 WN_set_desc (tree, TY_mtype(real_ty));
07132
07133 } else if (WN_Type_Is_Shared_Ptr(WN_kid0(tree)) || WN_operator(WN_kid0(tree)) == OPR_TAS)
07134 {
07135 TY_IDX src_idx = 0;
07136 WN *kid0 = WN_kid0(tree);
07137 if(WN_operator(kid0) == OPR_TAS || OPERATOR_is_load(WN_operator(kid0))) {
07138 src_idx = WN_ty(kid0);
07139 if(OPERATOR_is_load(WN_operator(kid0)) && WN_field_id(kid0)) {
07140 src_idx = Get_Field_Type(src_idx, WN_field_id(kid0));
07141 }
07142 }
07143 kid0 = lower_expr(block,
07144 WN_operator(WN_kid0(tree)) == OPR_TAS ? WN_kid0(WN_kid0(tree)) :
07145 WN_kid0(tree),
07146 actions);
07147 if (TY_kind(WN_object_ty(WN_kid0(tree))) == KIND_SCALAR)
07148 WN_kid0(tree) = kid0;
07149 else {
07150 if(OPERATOR_is_load(WN_operator(WN_kid0(tree))) && WN_field_id(WN_kid0(tree)))
07151 WN_kid0(tree) = kid0;
07152 else {
07153
07154 TY_IDX idx = WN_field_id(tree) ?
07155 get_field_type(WN_ty(tree), WN_field_id(tree)) :
07156 WN_ty(tree) ;
07157 if(!Type_Is_Shared_Ptr(idx)) {
07158 if(src_idx && !TY_is_shared(src_idx))
07159 WN_kid0(tree) = WN_Convert_Shared_To_Local(kid0, WN_ty(tree), 0);
07160 else
07161 WN_kid0(tree) = kid0;
07162 }
07163 else if(WN_field_id(tree) && !Type_Is_Shared_Ptr(WN_ty(tree)) &&
07164 Type_Is_Shared_Ptr(idx, TRUE)){
07165
07166
07167
07168
07169 TY_IDX dst_idx = TY_To_Sptr_Idx(idx);
07170 if(TY_mtype(dst_idx) == MTYPE_M) {
07171 WN_set_rtype(tree, MTYPE_V);
07172 WN_set_desc(tree, MTYPE_M);
07173 WN_store_offset(tree) = Adjust_Field_Offset(WN_ty(tree),
07174 WN_field_id(tree));
07175
07176 WN_kid0(tree) = kid0;
07177 }
07178 }
07179 }
07180
07181
07182 }
07183 return tree;
07184 } else if(WN_field_id(tree) > 1) {
07185 WN_store_offset(tree) = Adjust_Field_Offset(WN_ty(tree), WN_field_id(tree));
07186 } else if (WN_operator(WN_kid0(tree)) == OPR_ADD) {
07187
07188 WN* offset = WN_kid1(WN_kid0(tree));
07189 if (WN_operator(offset) == OPR_INTCONST) {
07190 TY_IDX obj_ty = struct_addr_ty(WN_kid0(WN_kid0(tree)));
07191 if (obj_ty != 0) {
07192 int field_id = find_field_from_offset(obj_ty, WN_const_val(offset));
07193 int real_ofst = Adjust_Field_Offset(obj_ty, field_id);
07194 WN_kid1(WN_kid0(tree)) = WN_CreateIntconst(OPR_INTCONST, Pointer_Mtype, MTYPE_V, real_ofst);
07195
07196 }
07197 }
07198 }
07199 }
07200
07201 break;
07202
07203 case OPR_ISTBITS:
07204 case OPR_STBITS:
07205 if (Action(LOWER_BITS_OP))
07206 return lower_store_bits (block, tree, actions);
07207 break;
07208
07209 case OPR_MSTORE:
07210 {
07211 WN *rhs = WN_kid0(tree);
07212 Is_True(!(WN_opcode(rhs) == OPC_MMLDID && WN_st(rhs) == Return_Val_Preg),
07213 ("MMLDID of Return_Val_Preg cannot be rhs of MSTORE"));
07214 }
07215
07216 if (Action(LOWER_UPC_TO_INTR)) {
07217 if((WN_ty(WN_kid1(tree)) && TY_is_shared(TY_pointed(WN_ty(WN_kid1(tree))))) ||
07218 (WN_ty(WN_kid0(tree)) && TY_is_shared(TY_pointed(WN_ty(WN_kid0(tree))))) ) {
07219
07220
07221
07222
07223
07224
07225
07226
07227
07228 BOOL src_shared = FALSE;
07229 if (TY_kind(WN_ty(WN_kid0(tree))) == KIND_POINTER &&
07230 TY_is_shared(TY_pointed(WN_ty(WN_kid0(tree)))))
07231 src_shared = TRUE;
07232 WN_OFFSET ld_xtra_oft = 0;
07233 WN_OFFSET st_xtra_oft = 0;
07234 TY_IDX dest_ty = 0;
07235 TY_IDX orig_ty = WN_ty(WN_kid1(tree));
07236
07237
07238 if (WN_operator(WN_kid0(tree)) == OPR_MLOAD ) {
07239 WN *kid0 = WN_kid0(tree);
07240 if(OPCODE_is_load(WN_opcode(WN_kid0(kid0))) ||
07241 OPCODE_is_store(WN_opcode(WN_kid0(kid0))))
07242 ld_xtra_oft = WN_offset(WN_kid0(kid0));
07243
07244 if (WN_field_id(kid0)) {
07245 UINT tmp_field_id = 0;
07246 dest_ty = FLD_type(FLD_get_to_field(TY_pointed(WN_object_ty(kid0)),
07247 WN_field_id(kid0), tmp_field_id));
07248 } else
07249 dest_ty = TY_pointed(WN_ty(kid0));
07250 WN_kid0(tree) = lower_expr(block, WN_kid0(WN_kid0(tree)), actions);
07251 } else
07252 WN_kid0(tree) = lower_expr(block, WN_kid0(tree), actions);
07253
07254 st_xtra_oft = WN_offset(WN_kid1(tree));
07255 WN_kid1(tree) = lower_expr(block, WN_kid1(tree), actions);
07256 WN_kid2(tree) = lower_expr(block, WN_kid2(tree), actions);
07257 if (src_shared && !Type_Is_Shared_Ptr(orig_ty)) {
07258
07259 return WN_Create_Shared_Load(WN_kid0(tree), WN_kid1(tree),
07260 TRUE, ld_xtra_oft);
07261 } else if (!src_shared) {
07262 return WN_Create_Shared_Store(tree, src_shared, st_xtra_oft);
07263 } else {
07264
07265
07266 ST *spill_st = Gen_Temp_Symbol(dest_ty, (char*) ".Mspill");
07267 WN *dest = WN_Lda(Pointer_Mtype, 0, spill_st, 0);
07268 dest = WN_Create_Shared_Load(WN_kid0(tree), dest, TRUE, 0, dest_ty);
07269 WN *wn0 = WN_CreateBlock();
07270 WN_INSERT_BlockLast(wn0, dest);
07271 wn0 = WN_CreateComma(OPR_COMMA, MTYPE_M, MTYPE_V, wn0,
07272 WN_Ldid(MTYPE_M, 0, spill_st, ST_type(spill_st)));
07273 WN_kid0(tree) = wn0;
07274 return WN_Create_Shared_Store(tree, FALSE, st_xtra_oft);
07275
07276 }
07277 }
07278 } else if(Action(LOWER_UPC_MFIELD)) {
07279 TY_IDX idx = TY_pointed(WN_ty(tree));
07280 WN *kid = WN_kid2(tree);
07281 if(WN_operator(kid) == OPR_INTCONST)
07282 WN_const_val(kid) =
07283 Adjusted_Type_Size(WN_field_id(tree) == 0 ? idx : Get_Field_Type(idx, WN_field_id(tree)));
07284 if(WN_field_id(tree) && WN_offset(tree))
07285 WN_offset(tree) = Adjust_Field_Offset(idx, WN_field_id(tree));
07286 }
07287
07288 if (Align_Object)
07289 {
07290 INT16 i;
07291 for (i = 0; i < WN_kid_count(tree); i++)
07292 WN_kid(tree,i) = lower_expr(block, WN_kid(tree,i), actions);
07293
07294 tree = improve_Malignment(tree, WN_kid1(tree), WN_kid2(tree),
07295 WN_store_offset(tree));
07296 }
07297
07298 if (Action(LOWER_MSTORE))
07299 {
07300 if (WN_StoreIsUnused(WN_kid1(tree)))
07301 {
07302 WN *eval;
07303
07304 eval = lower_eval(block, WN_CreateEval(WN_kid0(tree)), actions);
07305
07306 WN_Delete(tree);
07307
07308 return eval;
07309 }
07310
07311
07312
07313
07314
07315
07316 if (WN_opcode(WN_kid0(tree)) == OPC_MCSELECT)
07317 {
07318 WN *select, *expr, *mload0, *mload1, *cselect;
07319
07320 select = WN_kid0(tree);
07321 expr = WN_kid0(select);
07322 mload0 = WN_kid1(select);
07323 mload1 = WN_kid2(select);
07324
07325 Is_True(WN_operator_is(mload0, OPR_MLOAD),
07326 ("unexpected MSTORE (MCSELECT) pattern"));
07327 Is_True(WN_operator_is(mload1, OPR_MLOAD),
07328 ("unexpected MSTORE (MCSELECT) pattern"));
07329
07330 cselect = WN_Cselect(Pointer_type, expr, WN_kid0(mload0),
07331 WN_kid0(mload1));
07332 WN_kid0(mload0) = cselect;
07333 WN_kid0(tree) = mload0;
07334 }
07335 tree = lower_mstore(block, tree, actions);
07336 kids_lowered = TRUE;
07337 }
07338
07339
07340
07341 break;
07342
07343 }
07344
07345
07346 if (! kids_lowered)
07347 {
07348 INT16 i;
07349 for (i = 0; i < WN_kid_count(tree); i++)
07350 WN_kid(tree,i) = lower_expr(block, WN_kid(tree,i), actions);
07351 }
07352
07353 return tree;
07354 }
07355
07356
07357
07358
07359
07360
07361
07362
07363
07364
07365
07366
07367
07368 static WN *lower_eval(WN *block, WN *tree, LOWER_ACTIONS actions)
07369 {
07370 WN *child = WN_kid0(tree);
07371
07372 Is_True(WN_opcode(tree) == OPC_EVAL,
07373 ("expected EVAL node, not %s", OPCODE_name(WN_opcode(tree))));
07374
07375 if (Action(LOWER_COMPLEX) && MTYPE_is_complex(WN_rtype(child)))
07376 {
07377 WN *realexp, *imagexp, *eval;
07378
07379 lower_complex_expr(block, child, actions, &realexp, &imagexp);
07380
07381 realexp = lower_expr(block, realexp, actions);
07382 eval = WN_CreateEval(realexp);
07383 WN_INSERT_BlockLast(block, eval);
07384
07385 child = imagexp;
07386 }
07387 else if (Action(LOWER_QUAD) && MTYPE_is_quad(WN_rtype(child)))
07388 {
07389 WN *hi, *lo, *eval;
07390
07391 lower_quad_expr(block, child, actions, &hi, &lo);
07392
07393 hi = lower_expr(block, hi, actions);
07394 eval = WN_CreateEval(hi);
07395 WN_INSERT_BlockLast(block, eval);
07396
07397 child = lo;
07398 }
07399 else if (Action(LOWER_MSTORE) && WN_operator_is(child, OPR_MLOAD))
07400 {
07401 TY_IDX mloadTY = TY_pointed(Ty_Table[WN_ty(child)]);
07402
07403 if (TY_is_volatile(mloadTY))
07404 {
07405 DevWarn("eval of volatile (mload) seen. I hoped to never see this");
07406 }
07407 else if (Action(LOWER_TO_CG) && traceWoptFinishedOpt)
07408 {
07409 DevWarn("eval of (mload) processed (wopt should have removed this)");
07410 }
07411 block = lower_mload(block, child, actions);
07412 return block;
07413 }
07414
07415 {
07416 WN *eval;
07417
07418 child = lower_expr(block, child, actions);
07419 eval = WN_CreateEval(child);
07420 WN_Delete(tree);
07421
07422 return eval;
07423 }
07424
07425 }
07426
07427
07428
07429 static INT32
07430 calculateLoadStore(INT64 size, INT64 offset, TYPE_ID quantum, WN *src)
07431 {
07432 INT32 n = (size-offset) / MTYPE_RegisterSize(quantum);
07433
07434 return WN_operator_is(src, OPR_INTCONST) ? n : 2*n;
07435 }
07436
07437
07438
07439
07440
07441
07442
07443
07444
07445
07446
07447
07448
07449
07450
07451
07452
07453
07454
07455
07456
07457
07458
07459
07460
07461 static MSTORE_ACTIONS
07462 GenerateMstoreAction(WN *size, INT32 offset, TYPE_ID quantum, WN *expr)
07463 {
07464 MSTORE_ACTIONS action;
07465
07466 INT32 nMoves;
07467 BOOL sizeIsConstant = WN_operator_is(size, OPR_INTCONST);
07468
07469 if (sizeIsConstant)
07470 {
07471 nMoves = calculateLoadStore(WN_const_val(size), offset, quantum, expr);
07472 }
07473
07474 if (MinStructCopyMemIntrSize &&
07475 ((sizeIsConstant==FALSE) ||
07476 (sizeIsConstant==TRUE && MinStructCopyMemIntrSize <= nMoves)))
07477 {
07478 if (WN_operator_is(expr, OPR_INTCONST))
07479 {
07480 INT64 val= WN_const_val(expr);
07481
07482 if (val == 0)
07483 action = MSTORE_intrinsic_bzero;
07484 else
07485 {
07486 WN *i1con= WN_I1const(WN_rtype(expr), val);
07487
07488 action = (val == WN_const_val(i1con)) ? MSTORE_intrinsic_memset
07489 : MSTORE_loop;
07490 WN_Delete(i1con);
07491 }
07492 }
07493 else if (WN_operator_is(expr, OPR_MLOAD))
07494 {
07495 action = MSTORE_intrinsic_bcopy;
07496 }
07497 else
07498 {
07499 action = MSTORE_loop;
07500 }
07501 }
07502 else if (sizeIsConstant==TRUE &&
07503 MinStructCopyLoopSize &&
07504 MinStructCopyLoopSize <= nMoves)
07505 {
07506 action = MSTORE_loop;
07507 }
07508 else
07509 {
07510 action = (sizeIsConstant) ? MSTORE_aggregate : MSTORE_loop;
07511 }
07512
07513 if (traceMload)
07514 {
07515 if (sizeIsConstant) {
07516 DevWarn("GenerateMstoreAction: %s : line %d: quantum %d, "
07517 "size %lld, nMoves %d",
07518 MSTORE_ACTIONS_name(action),
07519 Srcpos_To_Line(current_srcpos),
07520 MTYPE_alignment(quantum),
07521 WN_const_val(size),
07522 nMoves);
07523 } else {
07524 DevWarn("GenerateMstoreAction: %s : line %d: quantum %d, "
07525 "size unknown",
07526 MSTORE_ACTIONS_name(action),
07527 Srcpos_To_Line(current_srcpos),
07528 MTYPE_alignment(quantum));
07529 }
07530 }
07531
07532 return action;
07533 }
07534
07535
07536
07537
07538 static inline TY_IDX
07539 struct_memop_type (TYPE_ID mtype, TY_IDX struct_type)
07540 {
07541 if (TY_size (struct_type) != MTYPE_byte_size (mtype))
07542 Set_TY_IDX_index (struct_type, TY_IDX_index(MTYPE_To_TY (mtype)));
07543 return struct_type;
07544 }
07545
07546
07547
07548
07549
07550
07551
07552
07553
07554
07555
07556
07557
07558
07559
07560
07561
07562
07563
07564
07565
07566
07567
07568
07569
07570
07571
07572
07573
07574
07575
07576
07577
07578
07579
07580
07581
07582
07583 static void
07584 copy_aggregate(WN *block, TY_IDX srcAlign, TY_IDX dstAlign, INT32 offset,
07585 INT32 size, TYPE_ID quantum, ST *preg, PREG_NUM srcPreg,
07586 PREG_NUM dstPreg, WN *origLoad, WN *origStore,
07587 INT32 copy_alignment, LOWER_ACTIONS actions)
07588 {
07589 INT32 stride = MTYPE_RegisterSize(quantum);
07590 INT32 nMoves = size / stride;
07591
07592 if (size <= 0)
07593 return;
07594
07595 if (nMoves>0)
07596 {
07597
07598
07599
07600 while(nMoves--)
07601 {
07602
07603
07604
07605
07606
07607
07608 WN *value, *addr, *store;
07609
07610 if (srcAlign)
07611 {
07612 value = WN_IloadLdid(quantum, offset,
07613 struct_memop_type (quantum, srcAlign),
07614 preg, srcPreg);
07615
07616 lower_copy_maps(origLoad, value, actions);
07617 }
07618 else
07619 {
07620 value = WN_LdidPreg(quantum, srcPreg);
07621 }
07622
07623 addr = WN_LdidPreg(Pointer_type, dstPreg);
07624
07625 store = WN_Istore(quantum,
07626 offset,
07627 Make_Pointer_Type (struct_memop_type (quantum,
07628 dstAlign)),
07629 addr,
07630 value);
07631 lower_copy_maps(origStore, store, actions);
07632
07633 WN_INSERT_BlockLast(block, store);
07634
07635 offset += stride;
07636 size -= stride;
07637 }
07638 }
07639 if (size > 0)
07640 {
07641
07642
07643
07644
07645 quantum = compute_next_copy_quantum(quantum, copy_alignment);
07646
07647 copy_aggregate(block,
07648 srcAlign, dstAlign,
07649 offset,
07650 size,
07651 quantum,
07652 preg,
07653 srcPreg, dstPreg,
07654 origLoad, origStore,
07655 copy_alignment,
07656 actions);
07657 }
07658 }
07659
07660
07661
07662
07663 static void
07664 copy_element_and_increment(WN *block, TY_IDX srcAlign, TY_IDX dstAlign,
07665 PREG_NUM offsetN, TYPE_ID quantum, PREG_NUM srcPreg,
07666 PREG_NUM dstPreg, WN *origLoad, WN *origStore,
07667 LOWER_ACTIONS actions)
07668 {
07669
07670
07671
07672
07673
07674
07675
07676
07677
07678 INT32 stride = MTYPE_RegisterSize(quantum);
07679 WN *value, *addr, *store, *add, *inc;
07680 ST *intPreg = MTYPE_To_PREG(Integer_type);
07681
07682 if (srcAlign)
07683 {
07684 addr = WN_Add(Pointer_type,
07685 WN_LdidPreg(Pointer_type, srcPreg),
07686 WN_LdidPreg(Integer_type, offsetN));
07687 value = WN_CreateIload (OPR_ILOAD, Mtype_comparison(quantum), quantum,
07688 0, struct_memop_type (quantum, srcAlign),
07689 Make_Pointer_Type (srcAlign), addr);
07690
07691 lower_copy_maps(origLoad, value, actions);
07692 }
07693 else
07694 {
07695 value = WN_LdidPreg(quantum, srcPreg);
07696 }
07697
07698 addr = WN_Add(Pointer_type,
07699 WN_LdidPreg(Pointer_type, dstPreg),
07700 WN_LdidPreg(Integer_type, offsetN));
07701 store = WN_Istore(quantum,
07702 0,
07703 Make_Pointer_Type(struct_memop_type (quantum, dstAlign)),
07704 addr,
07705 value);
07706
07707 lower_copy_maps(origStore, store, actions);
07708
07709 WN_INSERT_BlockLast(block, store);
07710
07711
07712
07713
07714
07715 add = WN_Add(Integer_type,
07716 WN_LdidPreg(Integer_type, offsetN),
07717 WN_Intconst(Integer_type, stride));
07718 inc = WN_StidIntoPreg(Integer_type, offsetN, intPreg, add);
07719 WN_INSERT_BlockLast(block, inc);
07720 }
07721
07722
07723
07724
07725
07726
07727
07728
07729
07730
07731
07732 static void
07733 copy_aggregate_loop_const(WN *block, TY_IDX srcAlign, TY_IDX dstAlign,
07734 INT32 offset, INT32 size, TYPE_ID quantum,
07735 PREG_NUM srcPreg, PREG_NUM dstPreg, WN *origLoad,
07736 WN *origStore, INT32 copy_alignment,
07737 LOWER_ACTIONS actions)
07738 {
07739
07740
07741
07742
07743
07744
07745
07746
07747
07748
07749
07750
07751
07752
07753
07754 PREG_NUM offsetN;
07755 ST *intPreg = MTYPE_To_PREG(Integer_type);
07756 INT32 stride = MTYPE_RegisterSize(quantum);
07757 INT64 nMoves = size / stride;
07758 INT64 residue = size - ( nMoves * stride );
07759
07760
07761
07762
07763 if ((nMoves <= 0) && residue == 0)
07764 return;
07765
07766 offsetN = AssignExpr(block, WN_Intconst(Integer_type, offset), Integer_type);
07767
07768
07769
07770
07771
07772 if (nMoves > 0)
07773 {
07774 PREG_NUM n;
07775 WN *body;
07776 WN *incr;
07777 WN *start;
07778 WN *test;
07779 WN *doLoop;
07780
07781 n = Create_Preg(Integer_type,"mstore_loopcount");
07782 body= WN_CreateBlock();
07783 start = WN_StidIntoPreg( Integer_type, n, intPreg,
07784 WN_Intconst(Integer_type, nMoves));
07785 incr = WN_StidIntoPreg( Integer_type, n, intPreg,
07786 WN_Sub(Integer_type,
07787 WN_LdidPreg(Integer_type, n),
07788 WN_Intconst(Integer_type, 1)));
07789 test = WN_GT(Integer_type,
07790 WN_LdidPreg(Integer_type, n),
07791 WN_Zerocon(Integer_type));
07792
07793
07794
07795
07796
07797
07798
07799
07800 copy_element_and_increment(body,
07801 srcAlign, dstAlign,
07802 offsetN,
07803 quantum,
07804 srcPreg, dstPreg,
07805 origLoad, origStore,
07806 actions);
07807 doLoop = WN_CreateDO(WN_CreateIdname(n, intPreg),
07808 start, test, incr, body, NULL);
07809 WN_INSERT_BlockLast(block, doLoop);
07810 if ( Cur_PU_Feedback )
07811 Cur_PU_Feedback->FB_lower_mstore_to_loop( origStore, doLoop, nMoves );
07812 }
07813
07814
07815
07816
07817
07818
07819
07820
07821
07822
07823
07824
07825
07826
07827
07828
07829
07830
07831
07832
07833
07834
07835 if (residue)
07836 {
07837 WN *residue_block= WN_CreateBlock();
07838
07839 while(residue>0)
07840 {
07841 quantum = compute_next_copy_quantum(quantum, copy_alignment);
07842
07843 while (residue >= MTYPE_alignment(quantum))
07844 {
07845 copy_element_and_increment(residue_block, srcAlign, dstAlign,
07846 offsetN, quantum, srcPreg, dstPreg,
07847 origLoad, origStore, actions);
07848 residue -= MTYPE_alignment(quantum);
07849 }
07850 }
07851 WN_INSERT_BlockLast(block, residue_block);
07852 }
07853 }
07854
07855
07856
07857
07858
07859
07860
07861
07862
07863
07864
07865
07866 static void
07867 copy_aggregate_loop_n(WN *block, TY_IDX srcAlign, TY_IDX dstAlign,
07868 INT32 offset, WN *size, TYPE_ID quantum,
07869 PREG_NUM srcPreg, PREG_NUM dstPreg, WN *origLoad,
07870 WN *origStore, INT32 copy_alignment,
07871 LOWER_ACTIONS actions)
07872 {
07873
07874
07875
07876
07877
07878
07879
07880
07881
07882
07883
07884
07885
07886 PREG_NUM offsetN, nMovesN, residueN;
07887 ST *intPreg = MTYPE_To_PREG(Integer_type);
07888 INT32 stride = MTYPE_RegisterSize(quantum);
07889
07890 Is_True((WN_operator(size)!=OPR_INTCONST),("unexpected const"));
07891
07892
07893
07894
07895
07896
07897
07898
07899 {
07900 WN *nMoves, *residue;
07901
07902 nMoves = WN_Div(Integer_type, WN_COPY_Tree(size),
07903 WN_Intconst(Integer_type, stride));
07904
07905 nMovesN = AssignExpr(block, nMoves, Integer_type);
07906
07907 residue = WN_Sub(Integer_type,
07908 WN_COPY_Tree(size),
07909 WN_Mpy(Integer_type,
07910 WN_LdidPreg(Integer_type, nMovesN),
07911 WN_Intconst(Integer_type, stride)));
07912
07913 residueN = AssignExpr(block, residue, Integer_type);
07914 }
07915
07916
07917
07918
07919
07920 #if 0
07921 n = AssignExpr(block, WN_LdidPreg(Integer_type, nMovesN), Integer_type);
07922
07923 offsetN = AssignExpr(block, WN_Intconst(Integer_type, offset), Integer_type);
07924
07925 {
07926 WN *body, *sub, *dec, *test, *whileDo;
07927
07928 body = WN_CreateBlock();
07929
07930
07931
07932
07933
07934
07935
07936
07937
07938
07939
07940
07941
07942 copy_element_and_increment(body,
07943 srcAlign, dstAlign,
07944 offsetN, quantum,
07945 srcPreg, dstPreg,
07946 origLoad, origStore,
07947 actions);
07948
07949 sub = WN_Sub(Integer_type,
07950 WN_LdidPreg(Integer_type, n),
07951 WN_Intconst(Integer_type, 1));
07952 dec = WN_StidIntoPreg(Integer_type, n, intPreg, sub);
07953 WN_INSERT_BlockLast(body, dec);
07954
07955
07956 test = WN_GT(Integer_type,
07957 WN_LdidPreg(Integer_type, n),
07958 WN_Zerocon(Integer_type));
07959
07960 whileDo = WN_CreateWhileDo(test, body);
07961
07962 WN_INSERT_BlockLast(block, whileDo);
07963 }
07964 #else
07965 {
07966 PREG_NUM n;
07967 WN *body;
07968 WN *incr;
07969 WN *start;
07970 WN *test;
07971 WN *doLoop;
07972
07973 n = Create_Preg(Integer_type,"mstore_loopcount");
07974 offsetN = AssignExpr(block, WN_Intconst(Integer_type, offset),
07975 Integer_type);
07976
07977 body= WN_CreateBlock();
07978 start = WN_StidIntoPreg(Integer_type, n, intPreg,
07979 WN_LdidPreg(Integer_type, nMovesN));
07980 incr = WN_StidIntoPreg(Integer_type, n, intPreg,
07981 WN_Sub(Integer_type,
07982 WN_LdidPreg(Integer_type, n),
07983 WN_Intconst(Integer_type, 1)));
07984 test = WN_GT(Integer_type,
07985 WN_LdidPreg(Integer_type, n),
07986 WN_Zerocon(Integer_type));
07987
07988
07989
07990
07991
07992
07993
07994
07995 copy_element_and_increment(body,
07996 srcAlign, dstAlign,
07997 offsetN,
07998 quantum,
07999 srcPreg, dstPreg,
08000 origLoad, origStore,
08001 actions);
08002 doLoop = WN_CreateDO(WN_CreateIdname(n,intPreg),start,test,incr,body,NULL);
08003 WN_INSERT_BlockLast(block, doLoop);
08004 }
08005
08006 #endif
08007
08008
08009
08010
08011
08012
08013
08014
08015
08016
08017
08018
08019
08020
08021
08022
08023
08024
08025
08026
08027
08028
08029
08030
08031
08032
08033
08034
08035 {
08036 WN *if_then, *unused, *cond, *IF;
08037
08038 if_then = WN_CreateBlock();
08039 unused = WN_CreateBlock();
08040
08041 cond = WN_GT(Integer_type,
08042 WN_LdidPreg(Integer_type, residueN),
08043 WN_Zerocon(Integer_type));
08044
08045 IF = WN_CreateIf(cond, if_then, unused);
08046
08047
08048 quantum = compute_next_copy_quantum(quantum,
08049 MTYPE_alignment(Max_Uint_Mtype));
08050
08051 while(MTYPE_alignment(quantum) > 0)
08052 {
08053 WN *if_residue_block, *unused, *test, *IF_residue;
08054
08055
08056 if_residue_block = WN_CreateBlock();
08057 unused = WN_CreateBlock();
08058
08059 test = WN_GE(Integer_type,
08060 WN_LdidPreg(Integer_type, residueN),
08061 WN_Intconst(Integer_type, MTYPE_alignment(quantum)));
08062
08063 IF_residue = WN_CreateIf(test, if_residue_block, unused);
08064
08065 lower_copy_maps(origStore, IF_residue, actions);
08066
08067 copy_element_and_increment(if_residue_block, srcAlign, dstAlign,
08068 offsetN, quantum, srcPreg, dstPreg,
08069 origLoad, origStore, actions);
08070
08071
08072
08073
08074 {
08075 WN *sub, *dec;
08076
08077 sub = WN_Sub(Integer_type,
08078 WN_LdidPreg(Integer_type, residueN),
08079 WN_Intconst(Integer_type, MTYPE_alignment(quantum)));
08080 dec = WN_StidIntoPreg(Integer_type, residueN, intPreg, sub);
08081 lower_copy_maps(origStore, dec, actions);
08082 WN_INSERT_BlockLast(if_residue_block, dec);
08083 }
08084
08085 WN_INSERT_BlockLast(if_then, IF_residue);
08086
08087 quantum = compute_next_copy_quantum(quantum,
08088 MTYPE_alignment(Max_Uint_Mtype));
08089 }
08090 WN_INSERT_BlockLast(block, IF);
08091 }
08092 }
08093
08094
08095
08096
08097
08098
08099
08100
08101
08102
08103
08104
08105
08106
08107
08108
08109
08110
08111
08112 static void
08113 copy_aggregate_loop(WN *block, TY_IDX srcTY, TY_IDX dstTY, INT32 offset,
08114 WN *size, TYPE_ID quantum, ST *preg, PREG_NUM srcPreg,
08115 PREG_NUM dstPreg, WN *origLoad, WN *origStore,
08116 INT32 copy_alignment, LOWER_ACTIONS actions)
08117 {
08118 if (WN_operator_is(size, OPR_INTCONST))
08119 {
08120 if (WN_const_val(size)>0)
08121 {
08122 copy_aggregate_loop_const(block,
08123 srcTY, dstTY,
08124 offset,
08125 WN_const_val(size),
08126 quantum,
08127 srcPreg, dstPreg,
08128 origLoad, origStore,
08129 copy_alignment,
08130 actions);
08131 }
08132 }
08133 else
08134 {
08135 copy_aggregate_loop_n(block,
08136 srcTY, dstTY,
08137 offset,
08138 size,
08139 quantum,
08140 srcPreg,
08141 dstPreg,
08142 origLoad, origStore,
08143 copy_alignment,
08144 actions);
08145 }
08146 }
08147
08148
08149
08150
08151
08152
08153 static void markAddrTakenPassed(WN *expr)
08154 {
08155 switch(WN_operator(expr))
08156 {
08157 case OPR_LDA:
08158 {
08159 ST *sym = WN_st(expr);
08160
08161
08162
08163
08164
08165
08166 }
08167 return;
08168 case OPR_ILOAD:
08169 case OPR_ILOADX:
08170 return;
08171 }
08172
08173 {
08174 INT32 i;
08175 for (i = 0; i < WN_kid_count(expr); i++)
08176 markAddrTakenPassed(WN_actual(expr,i));
08177 }
08178 }
08179
08180
08181
08182
08183
08184
08185
08186
08187
08188 inline WN *WN_Generate_Intrinsic_Call(WN *block, INTRINSIC id,
08189 INT32 nparm, WN *parm[])
08190 {
08191 WN *call = WN_Create_Intrinsic(OPC_VINTRINSIC_CALL, id, nparm, parm);
08192 return intrinsic_runtime(block, call);
08193 }
08194
08195
08196 static void copy_aggregate_bzero(WN *block, TY_IDX dstTY, WN *dst, WN *size)
08197 {
08198 WN *call, *parms[2];
08199
08200 markAddrTakenPassed(dst);
08201
08202 parms[0]= WN_CreateParm(Pointer_type,
08203 dst,
08204 dstTY,
08205 WN_PARM_BY_VALUE);
08206
08207 parms[1]= WN_CreateParm(WN_rtype(size),
08208 WN_COPY_Tree(size),
08209 MTYPE_To_TY(WN_rtype(size)),
08210 WN_PARM_BY_VALUE);
08211
08212 call= WN_Generate_Intrinsic_Call(block, INTRN_BZERO, 2, parms);
08213
08214 WN_INSERT_BlockLast(block, call);
08215 }
08216
08217 static void copy_aggregate_memset(WN *block, TY_IDX dstTY, WN *src, WN *dst,
08218 WN *size)
08219 {
08220 WN *call, *parms[3];
08221
08222 markAddrTakenPassed(dst);
08223 parms[0]= WN_CreateParm(Pointer_type,
08224 dst,
08225 dstTY,
08226 WN_PARM_BY_VALUE);
08227
08228 parms[1]= WN_CreateParm(WN_rtype(src),
08229 src,
08230 MTYPE_To_TY(WN_rtype(src)),
08231 WN_PARM_BY_VALUE);
08232
08233 parms[2]= WN_CreateParm(WN_rtype(size),
08234 WN_COPY_Tree(size),
08235 MTYPE_To_TY(WN_rtype(size)),
08236 WN_PARM_BY_VALUE);
08237
08238 call= WN_Generate_Intrinsic_Call(block, INTRN_MEMSET, 3, parms);
08239
08240 WN_INSERT_BlockLast(block, call);
08241 }
08242
08243 static void copy_aggregate_bcopy(WN *block, INT32 offset, TY_IDX srcTY,
08244 TY_IDX dstTY, WN *src, WN *dst, WN *size)
08245 {
08246 WN *call, *parms[3];
08247
08248 if (offset)
08249 {
08250 src = WN_Add(Pointer_type, src, WN_Intconst(Pointer_type, offset));
08251 dst = WN_Add(Pointer_type, dst, WN_Intconst(Pointer_type, offset));
08252 }
08253 markAddrTakenPassed(src);
08254 markAddrTakenPassed(dst);
08255
08256 parms[0]= WN_CreateParm(WN_rtype(src),
08257 src,
08258 srcTY ? srcTY : MTYPE_To_TY(WN_rtype(src)),
08259 WN_PARM_BY_VALUE);
08260
08261 parms[1]= WN_CreateParm(Pointer_type,
08262 dst,
08263 dstTY ? dstTY : MTYPE_To_TY(WN_rtype(dst)),
08264 WN_PARM_BY_VALUE);
08265
08266
08267 parms[2]= WN_CreateParm(WN_rtype(size),
08268 WN_COPY_Tree(size),
08269 MTYPE_To_TY(WN_rtype(size)),
08270 WN_PARM_BY_VALUE);
08271
08272 call= WN_Generate_Intrinsic_Call(block, INTRN_BCOPY, 3, parms);
08273
08274 WN_INSERT_BlockLast(block, call);
08275 }
08276
08277
08278
08279
08280
08281
08282
08283
08284
08285
08286
08287
08288
08289
08290
08291
08292
08293
08294
08295
08296
08297 extern INT32 compute_copy_alignment(TY_IDX src, TY_IDX dst, INT32 offset)
08298 {
08299 INT32 srcAlign, dstAlign, align;
08300 INT32 max= MTYPE_alignment(Max_Uint_Mtype);
08301
08302 srcAlign= (src) ? TY_align(src) : max;
08303 dstAlign= (dst) ? TY_align(dst) : max;
08304
08305 align= MIN(srcAlign, dstAlign);
08306 align= MIN(align, max);
08307
08308 Is_True((compute_offset_alignment(offset, align) == align),
08309 ("compute_copy_alignment: alignment not consistent with offset"));
08310
08311 return MIN(align, max);
08312 }
08313
08314
08315 extern TYPE_ID compute_copy_quantum(INT32 alignment)
08316 {
08317 if (UseAlignedCopyForStructs==FALSE)
08318 {
08319 INT32 maxAlign= MTYPE_alignment(Max_Uint_Mtype);
08320 INT32 ratio = Copy_Quantum_Ratio();
08321
08322 if (alignment*ratio < maxAlign)
08323 return Max_Uint_Mtype;
08324 }
08325
08326 return Mtype_AlignmentClass(alignment, MTYPE_CLASS_UNSIGNED_INTEGER);
08327 }
08328
08329 static TYPE_ID compute_next_copy_quantum(TYPE_ID quantum, INT32 alignment)
08330 {
08331 TYPE_ID next = Mtype_prev_alignment(quantum);
08332
08333 if (UseAlignedCopyForStructs==FALSE)
08334 {
08335 if ((MTYPE_alignment(next) > alignment) &&
08336 (next == MTYPE_U2 || next == MTYPE_I2))
08337 next = Mtype_prev_alignment(next);
08338 }
08339 return next;
08340 }
08341
08342
08343
08344
08345
08346
08347
08348
08349
08350
08351
08352
08353
08354
08355 static TY_IDX computeNewAlignmentTY(WN *addr, TY_IDX type, INT32 size,
08356 INT64 offset)
08357 {
08358 TY_IDX newType;
08359 INT32 align = TY_align(type);
08360 INT32 maxAlign = MTYPE_alignment(Max_Uint_Mtype);
08361
08362 if ((size <= align) || (align >= maxAlign))
08363 return TY_IDX_ZERO;
08364
08365
08366
08367
08368 newType = compute_alignment_type(addr, type, offset);
08369
08370 if (WN_operator_is(addr, OPR_LDA) && ST_class(WN_st(addr)) != CLASS_BLOCK)
08371 {
08372 ST *sym = WN_st(addr);
08373 TY_IDX symType = compute_alignment_type(addr, ST_type(sym), offset);
08374
08375
08376
08377
08378
08379
08380 if (ST_pu_defined(sym) && !Is_Allocated(sym))
08381 {
08382 INT32 stAlign;
08383
08384 stAlign = compute_offset_alignment(WN_lda_offset(addr), maxAlign);
08385 stAlign = compute_offset_alignment(offset, stAlign);
08386
08387 if (TY_align(symType) < stAlign)
08388 {
08389 if (traceAlignment)
08390 {
08391 DevWarn("realign ST %s (from %d to %d) line %d", ST_name(sym),
08392 TY_align(symType), stAlign, Srcpos_To_Line(current_srcpos));
08393 }
08394
08395
08396 symType = Make_Align_Type(symType, stAlign);
08397
08398 if ((ST_class(sym) == CLASS_CONST) &&
08399 (TCON_ty(STC_val(sym)) == MTYPE_STR) &&
08400 TY_is_pointer(Ty_Table[ST_type(sym)]))
08401 {
08402 symType = Make_Pointer_Type(newType);
08403 }
08404 Set_ST_type(sym, symType);
08405
08406 if (stAlign > align)
08407 {
08408 return Make_Align_Type(newType, stAlign);
08409 }
08410 return TY_IDX_ZERO;
08411 }
08412 }
08413 }
08414
08415 if (TY_align(newType) > align)
08416 return newType;
08417
08418 return TY_IDX_ZERO;
08419 }
08420
08421
08422
08423
08424 static WN *compute_new_size(WN *tree, WN *size, INT32 align)
08425 {
08426 if (Align_Padding)
08427 {
08428 INT64 sizeN = WN_const_val(size);
08429 INT64 residue = sizeN % align;
08430 INT32 popcnt = TARG_INT_Pop_Count(residue);
08431
08432 if (popcnt > 1)
08433 {
08434 INT64 newsize = sizeN + (align-residue);
08435
08436 return WN_Intconst(WN_rtype(size), newsize);
08437 }
08438 }
08439 return size;
08440 }
08441
08442
08443
08444
08445
08446
08447
08448
08449
08450
08451
08452
08453 static WN *improve_Malignment(WN *tree, WN *addr, WN *size, INT64 offset)
08454 {
08455 TY_IDX type, newType;
08456
08457 if (Align_Object == FALSE)
08458 return tree;
08459
08460 if (!WN_operator_is(size, OPR_INTCONST))
08461 {
08462 return tree;
08463 }
08464
08465 TY &tree_ty = Ty_Table[WN_ty(tree)];
08466
08467 if (TY_is_f90_pointer(tree_ty)) {
08468
08469 return tree;
08470 }
08471
08472 type = TY_pointed(tree_ty);
08473
08474 newType = computeNewAlignmentTY(addr, type, WN_const_val(size), offset);
08475
08476 if (newType)
08477 {
08478 if (traceAlignment)
08479 {
08480 DevWarn("realign OPCODE %s (from %d to %d) line %d",
08481 OPCODE_name(WN_opcode(tree)), TY_align(type), TY_align(newType),
08482 Srcpos_To_Line(current_srcpos));
08483 }
08484
08485 WN_set_ty(tree, Make_Pointer_Type(newType));
08486
08487 switch(WN_operator(tree))
08488 {
08489 case OPR_MSTORE:
08490 WN_kid2(tree)= compute_new_size(tree, size, TY_align(newType));
08491 break;
08492
08493 case OPR_MLOAD:
08494 WN_kid1(tree)= compute_new_size(tree, size, TY_align(newType));
08495 break;
08496 }
08497 }
08498
08499 return tree;
08500 }
08501
08502
08503
08504
08505
08506
08507
08508
08509
08510
08511
08512
08513
08514
08515
08516
08517
08518
08519
08520
08521
08522
08523
08524
08525 static WN *lower_mstore(WN * , WN *mstore, LOWER_ACTIONS actions)
08526 {
08527 WN *newblock;
08528 WN *load, *addr, *size;
08529 SRCPOS srcpos = WN_Get_Linenum(mstore);
08530 CURRENT_STATE mstate = pushCurrentState(mstore, actions);
08531
08532 load = WN_kid0(mstore);
08533 addr = WN_kid1(mstore);
08534 size = WN_kid2(mstore);
08535
08536 Is_True((WN_opcode(mstore) == OPC_MSTORE),
08537 ("expected MSTORE node, not %s", OPCODE_name(WN_opcode(mstore))));
08538
08539
08540 if (WN_field_id (mstore) != 0)
08541 lower_field_id (mstore);
08542
08543 newblock = WN_CreateBlock();
08544 {
08545 TY_IDX dstTY = TY_pointed(Ty_Table[WN_ty(mstore)]);
08546 TY_IDX srcTY = TY_IDX_ZERO;
08547 WN *expr = load;
08548
08549
08550
08551
08552
08553 if (WN_opcode(load) == OPC_MLOAD)
08554 {
08555 srcTY = TY_pointed(Ty_Table[WN_ty(load)]);
08556 expr = WN_kid0(load);
08557
08558
08559
08560 if (WN_load_offset(load))
08561 {
08562 expr = WN_Add(Pointer_type,
08563 expr,
08564 WN_Intconst(Pointer_type, WN_load_offset(load)));
08565 WN_kid0(load)= expr;
08566 }
08567 }
08568 else
08569 {
08570 load = NULL;
08571 }
08572
08573 {
08574 INT32 copy_alignment;
08575 PREG_NUM dstPreg, srcPreg;
08576 TYPE_ID quantum;
08577 ST *preg= MTYPE_To_PREG(Pointer_type);
08578
08579 if (WN_store_offset(mstore))
08580 {
08581 addr = WN_Add(Pointer_type,
08582 addr,
08583 WN_Intconst(Pointer_type, WN_store_offset(mstore)));
08584 }
08585
08586 copy_alignment = compute_copy_alignment(srcTY, dstTY,
08587 WN_store_offset(mstore));
08588 quantum = compute_copy_quantum(copy_alignment);
08589
08590 switch(GenerateMstoreAction(size, 0, quantum, WN_kid0(mstore)))
08591 {
08592 case MSTORE_intrinsic_bzero:
08593 copy_aggregate_bzero(newblock, WN_ty(mstore), addr, size);
08594 break;
08595
08596 case MSTORE_intrinsic_memset:
08597 copy_aggregate_memset(newblock, WN_ty(mstore), expr, addr, size);
08598 break;
08599
08600 case MSTORE_intrinsic_bcopy:
08601 copy_aggregate_bcopy(newblock, 0, TY_pointer(srcTY), TY_pointer(dstTY),
08602 expr, addr, size);
08603 break;
08604
08605 case MSTORE_loop:
08606 srcPreg = AssignExpr(newblock, expr, WN_rtype(expr));
08607 dstPreg = AssignExpr(newblock, addr, Pointer_type);
08608 copy_aggregate_loop(newblock,
08609 srcTY,
08610 dstTY,
08611 0,
08612 size,
08613 quantum,
08614 preg,
08615 srcPreg,
08616 dstPreg,
08617 load,
08618 mstore,
08619 copy_alignment,
08620 actions);
08621 break;
08622
08623 case MSTORE_aggregate:
08624 srcPreg = AssignExpr(newblock, expr, WN_rtype(expr));
08625 dstPreg = AssignExpr(newblock, addr, Pointer_type);
08626 copy_aggregate(newblock,
08627 srcTY,
08628 dstTY,
08629 0,
08630 WN_const_val(size),
08631 quantum,
08632 preg,
08633 srcPreg,
08634 dstPreg,
08635 load,
08636 mstore,
08637 copy_alignment,
08638 actions);
08639 break;
08640 }
08641 }
08642 }
08643
08644 WN_Delete( WN_kid2(mstore));
08645 WN_Delete(mstore);
08646
08647 newblock = lower_block(newblock, actions);
08648
08649 popCurrentState(mstate);
08650 return newblock;
08651 }
08652
08653
08654
08655
08656
08657
08658
08659
08660
08661
08662
08663
08664
08665 static WN *lower_mload(WN * , WN *mload, LOWER_ACTIONS actions)
08666 {
08667 PREG_NUM srcPreg;
08668 TYPE_ID quantum;
08669 INT32 size, copy_alignment;
08670 WN *newblock;
08671
08672 Is_True((WN_opcode(mload) == OPC_MLOAD),
08673 ("expected MLOAD node, not %s", OPCODE_name(WN_opcode(mload))));
08674 Is_True((WN_operator_is(WN_kid1(mload), OPR_INTCONST)),
08675 ("expected MLOAD size constant "));
08676
08677 if (WN_field_id (mload) != 0)
08678 lower_field_id (mload);
08679
08680 WN *addr = WN_kid0(mload);
08681 INT32 offset = WN_load_offset(mload);
08682 TY_IDX srcTY = TY_pointed(Ty_Table[WN_ty(mload)]);
08683
08684 newblock = WN_CreateBlock();
08685
08686 size = WN_const_val( WN_kid1(mload) );
08687 copy_alignment = compute_copy_alignment( srcTY, TY_IDX_ZERO, offset );
08688 quantum = compute_copy_quantum( copy_alignment );
08689
08690 srcPreg = AssignExpr(newblock, addr, WN_rtype(addr));
08691
08692 while (size > 0)
08693 {
08694 INT32 stride = MTYPE_RegisterSize(quantum);
08695 INT32 nMoves = size / stride;
08696
08697
08698
08699
08700 while (nMoves > 0)
08701 {
08702 WN *value, *eval;
08703
08704
08705 value = WN_IloadLdid(quantum, offset, MTYPE_To_TY(quantum),
08706 MTYPE_To_PREG(Pointer_type), srcPreg);
08707
08708 lower_copy_maps(mload, value, actions);
08709
08710 eval = WN_CreateEval(value);
08711
08712 WN_INSERT_BlockLast(newblock, eval);
08713
08714 offset += stride;
08715 size -= stride;
08716 nMoves--;
08717 }
08718
08719
08720
08721
08722 if (size > 0)
08723 {
08724 quantum = compute_next_copy_quantum(quantum, copy_alignment);
08725 }
08726 }
08727
08728 WN_Delete( WN_kid1(mload));
08729 WN_Delete(mload);
08730
08731 newblock = lower_block(newblock, actions);
08732
08733 return newblock;
08734 }
08735
08736
08737
08738
08739
08740
08741
08742
08743
08744
08745
08746
08747
08748
08749 static void lower_complex_actual (WN *block, WN *val, PLOC ploc,
08750 LOWER_ACTIONS actions)
08751 {
08752 WN *size, *mload, *addr;
08753 TY_IDX complexType = TY_Of_Expr(val);
08754
08755 size = WN_Intconst(Integer_type, TY_size(Ty_Table[complexType]));
08756
08757 addr = make_pointer_to_node(block, val);
08758
08759 mload = WN_CreateMload(0, Make_Pointer_Type(complexType), addr, size);
08760
08761 lower_mload_actual (block, mload, ploc, actions);
08762 }
08763
08764
08765
08766
08767
08768
08769
08770
08771
08772
08773
08774
08775
08776
08777 static void lower_mload_actual (WN *block, WN *mload, PLOC ploc,
08778 LOWER_ACTIONS actions)
08779 {
08780 ST *preg;
08781 INT32 size, mloadOffset = 0;
08782 PREG_NUM addrN;
08783
08784 if (WN_field_id(mload) != 0)
08785 lower_field_id (mload);
08786
08787 TY_IDX mloadTY = TY_pointed(Ty_Table[WN_ty(mload)]);
08788 WN *mloadSize = WN_kid1(mload);
08789
08790 if (WN_operator(mloadSize) != OPR_INTCONST) {
08791 DevWarn("mload_actual size is not INTCONST");
08792 if (WN_operator(mloadSize) == OPR_CVTL) {
08793 mloadSize = WN_kid0(mloadSize);
08794 }
08795 }
08796 size = WN_const_val(mloadSize);
08797 if (size<=0 || WN_operator(mloadSize) != OPR_INTCONST)
08798 {
08799 DevWarn("size of mload actual should be > 0");
08800 size = TY_size(Ty_Table[mloadTY]);
08801 DevWarn("adjusting size of (%s) to TY_size= %d",
08802 TY_name(Ty_Table[mloadTY]), size);
08803 mloadSize = WN_Intconst(Integer_type, size);
08804 }
08805
08806 Is_True((WN_opcode(mload) == OPC_MLOAD),
08807 ("expected MLOAD node, not %s", OPCODE_name(WN_opcode(mload))));
08808
08809 Setup_Struct_Output_Parameter_Locations(mloadTY);
08810 ploc = Get_Struct_Output_Parameter_Location(ploc);
08811
08812
08813
08814
08815
08816 preg = MTYPE_To_PREG(Pointer_type);
08817 {
08818 WN *addr = WN_COPY_Tree(WN_kid0(mload));
08819
08820 if (WN_load_offset(mload))
08821 {
08822 addr = WN_Add(Pointer_type,
08823 addr,
08824 WN_Intconst(Pointer_type, WN_load_offset(mload)));
08825 }
08826 addrN = AssignExpr(block, addr, Pointer_type);
08827 }
08828
08829 while (PLOC_is_nonempty(ploc))
08830 {
08831 if (PLOC_on_stack(ploc))
08832 {
08833 PREG_NUM dstPreg;
08834
08835
08836
08837
08838
08839
08840 {
08841 WN *add;
08842 INT64 offset;
08843
08844 offset = PLOC_offset(ploc) - Formal_Save_Area_Size
08845 + Stack_Offset_Adjustment - mloadOffset;
08846
08847 add = WN_Add(Pointer_type,
08848 WN_LdidPreg(Pointer_type, Stack_Pointer_Preg_Offset),
08849 WN_Intconst(Pointer_type, offset));
08850 dstPreg = AssignExpr(block, add, Pointer_type);
08851 }
08852 {
08853 TY_IDX srcTY = mloadTY;
08854 TY_IDX dstTY = MTYPE_To_TY(Max_Uint_Mtype);
08855 TYPE_ID quantum;
08856 WN *con;
08857 INT32 copy_alignment, nMoves;
08858 INT32 todo= size - mloadOffset;
08859
08860
08861
08862
08863 copy_alignment= compute_copy_alignment(srcTY, dstTY, 0);
08864 quantum = compute_copy_quantum(copy_alignment);
08865
08866
08867
08868
08869
08870 nMoves= calculateLoadStore(todo, mloadOffset, quantum, WN_kid0(mload));
08871
08872 if (MinStructCopyLoopSize && MinStructCopyLoopSize <= nMoves)
08873 {
08874 con = WN_Intconst(Integer_type, todo);
08875
08876 copy_aggregate_loop(block,
08877 srcTY,
08878 dstTY,
08879 mloadOffset,
08880 con,
08881 quantum,
08882 preg,
08883 addrN,
08884 dstPreg,
08885 mload,
08886 NULL,
08887 copy_alignment,
08888 actions);
08889 WN_Delete(con);
08890 }
08891 else
08892 {
08893 copy_aggregate(block,
08894 srcTY,
08895 dstTY,
08896 mloadOffset,
08897 todo,
08898 quantum,
08899 preg,
08900 addrN,
08901 dstPreg,
08902 mload,
08903 NULL,
08904 copy_alignment,
08905 actions);
08906 }
08907 }
08908 return;
08909 }
08910 else
08911 {
08912
08913
08914
08915 PREG_NUM regNo = PLOC_reg(ploc);
08916 ST *reg = Preg_Offset_Is_Float(regNo) ? Float_Preg : Int_Preg;
08917 TYPE_ID type = TY_mtype(Ty_Table[ST_type(reg)]);
08918
08919 {
08920 WN *load, *stid;
08921 INT32 todo = size - mloadOffset;
08922
08923 if (PLOC_size(ploc) < MTYPE_size_reg(type)
08924 && type == MTYPE_F8 && PLOC_size(ploc) == 4)
08925 {
08926
08927 DevWarn("actual_mload: switch from mtype_f8 to mtype_f4");
08928 type = MTYPE_F4;
08929 reg = MTYPE_To_PREG(type);
08930 }
08931
08932
08933
08934
08935
08936 if (todo < MTYPE_alignment(type))
08937 {
08938 TYPE_ID quantum;
08939 INT32 newAlign, shiftn;
08940
08941 Is_True(Preg_Offset_Is_Int(regNo),
08942 ("mload actual->reg(size/alignment problem"));
08943 newAlign = nearest_power_of_two(todo);
08944
08945 quantum = Mtype_AlignmentClass(newAlign, MTYPE_type_class(type));
08946
08947 load = WN_IloadLdid(quantum, mloadOffset,
08948 struct_memop_type (quantum, mloadTY), preg,
08949 addrN);
08950
08951 lower_copy_maps(mload, load, actions);
08952
08953 if (Target_Byte_Sex == BIG_ENDIAN) {
08954 shiftn = MTYPE_size_reg(type) - MTYPE_size_reg(quantum);
08955
08956 load = WN_Shl(type, load, WN_Intconst(type, shiftn));
08957 }
08958 }
08959 else
08960 {
08961 load = WN_IloadLdid(type, mloadOffset,
08962 struct_memop_type (type, mloadTY), preg,
08963 addrN);
08964
08965 lower_copy_maps(mload, load, actions);
08966 }
08967
08968 stid= WN_Stid(type, regNo, reg, ST_type(reg), load);
08969
08970 WN_INSERT_BlockLast(block, stid);
08971 }
08972 }
08973 mloadOffset += PLOC_size(ploc);
08974 ploc = Get_Struct_Output_Parameter_Location(ploc);
08975 }
08976 }
08977
08978
08979
08980
08981
08982
08983
08984
08985
08986
08987
08988 static void lower_mload_formal(WN *block, WN *mload, PLOC ploc,
08989 LOWER_ACTIONS actions)
08990 {
08991 INT32 size, offset = 0;
08992 ST *sym = WN_st(mload);
08993 TY_IDX symTY = ST_type(sym);
08994
08995 Setup_Struct_Input_Parameter_Locations(symTY);
08996 ploc = Get_Struct_Input_Parameter_Location(ploc);
08997 size = TY_size(Ty_Table[symTY]);
08998
08999 while (PLOC_is_nonempty(ploc))
09000 {
09001 if (PLOC_on_stack(ploc))
09002 {
09003
09004
09005
09006 return;
09007 }
09008 else
09009 {
09010
09011
09012
09013 PREG_NUM regNo = PLOC_reg(ploc);
09014 ST *reg = Preg_Offset_Is_Float(regNo) ? Float_Preg : Int_Preg;
09015 TYPE_ID type = TY_mtype(ST_type(reg));
09016 INT32 todo = size - offset;
09017 {
09018 WN *ldid, *store;
09019
09020 if (PLOC_size(ploc) < MTYPE_size_reg(type)
09021 && type == MTYPE_F8 && PLOC_size(ploc) == 4)
09022 {
09023
09024 DevWarn("formal_mload: switch from mtype_f8 to mtype_f4");
09025 type = MTYPE_F4;
09026 reg = MTYPE_To_PREG(type);
09027 }
09028
09029 ldid = WN_LdidPreg(type, regNo);
09030
09031
09032
09033
09034 if (todo < MTYPE_alignment(type))
09035 {
09036 TYPE_ID quantum;
09037 INT32 newAlign, shiftn;
09038
09039 Is_True(Preg_Offset_Is_Int(regNo),
09040 ("mload actual->reg(size/alignment problem"));
09041 newAlign = nearest_power_of_two(todo);
09042
09043 quantum = Mtype_AlignmentClass(newAlign, MTYPE_type_class(type));
09044
09045 shiftn = MTYPE_size_reg(type) - MTYPE_size_reg(quantum);
09046
09047 if (Target_Byte_Sex == BIG_ENDIAN) {
09048
09049
09050
09051
09052
09053 if (MTYPE_alignment(quantum) == 4)
09054 {
09055 ldid= WN_Ashr(type, ldid, WN_Intconst(type, shiftn));
09056 }
09057 else
09058 {
09059 ldid= WN_Lshr(type, ldid, WN_Intconst(type, shiftn));
09060 }
09061 }
09062
09063 store = WN_Stid (quantum, offset, sym,
09064 struct_memop_type (quantum, symTY) , ldid);
09065 }
09066 else
09067 {
09068 store = WN_Stid (type, offset, sym, struct_memop_type (type, symTY),
09069 ldid);
09070 }
09071 lower_copy_maps(mload, store, actions);
09072
09073 WN_INSERT_BlockLast(block, store);
09074 }
09075 offset += PLOC_size(ploc);
09076 }
09077 ploc = Get_Struct_Input_Parameter_Location(ploc);
09078 }
09079 }
09080
09081
09082
09083
09084
09085
09086
09087
09088
09089
09090
09091
09092
09093 static void lower_complex_emulation(WN *block, WN *tree, LOWER_ACTIONS actions,
09094 WN **realpart, WN **imagpart)
09095 {
09096 WN *wn;
09097 BOOL intrinsic_lowered;
09098
09099 Is_True(MTYPE_is_complex(WN_rtype(tree)),
09100 ("expected complex type in lower_complex_emulation"));
09101
09102
09103
09104
09105
09106
09107
09108
09109 wn = lower_emulation(block, tree, actions, intrinsic_lowered);
09110
09111
09112
09113 if (!intrinsic_lowered) {
09114 actions |= LOWER_INTRINSIC;
09115 }
09116 lower_complex_expr(block, wn, actions, realpart, imagpart);
09117 }
09118
09119
09120
09121
09122
09123
09124
09125
09126
09127
09128
09129
09130
09131
09132
09133 static WN *lower_emulation(WN *block, WN *tree, LOWER_ACTIONS actions,
09134 BOOL & intrinsic_lowered)
09135 {
09136 WN *wn, *emBlock;
09137 OPCODE op = WN_opcode(tree);
09138
09139 intrinsic_lowered = FALSE;
09140
09141
09142
09143
09144 {
09145 INT32 i;
09146
09147 for (i = 0; i < WN_kid_count(tree); i++)
09148 WN_actual(tree,i) = lower_expr(block, WN_actual(tree,i), actions);
09149 }
09150
09151
09152
09153
09154 wn = NULL;
09155 emBlock = WN_CreateBlock();
09156
09157 if (OPCODE_is_intrinsic(WN_opcode(tree)))
09158 {
09159 Is_True((INTRN_is_nary(WN_intrinsic(tree))==FALSE),("nary slipped by"));
09160 if (Action(LOWER_INLINE_INTRINSIC) || Action(LOWER_INL_STACK_INTRINSIC))
09161 {
09162 wn = emulate(emBlock , tree);
09163 }
09164 if (wn == NULL && NotAction(LOWER_INTRINSIC))
09165 {
09166 return tree;
09167 }
09168 intrinsic_lowered = TRUE;
09169 }
09170
09171
09172
09173 else
09174 {
09175 wn = emulate(emBlock , tree);
09176 }
09177
09178
09179 if (wn)
09180 {
09181 emBlock = lower_block(emBlock, actions);
09182 WN_INSERT_BlockLast(block, emBlock);
09183
09184
09185
09186
09187 if (OPCODE_is_stmt(WN_opcode(wn)))
09188 {
09189 wn = lower_stmt(block, wn, actions);
09190 }
09191 else if (OPCODE_is_expression(WN_opcode(wn)))
09192 {
09193 wn = lower_expr(block, wn, actions);
09194 }
09195 }
09196 else
09197 {
09198 WN_Delete(emBlock);
09199
09200 if (OPCODE_is_call(op))
09201 {
09202 wn = lower_intrinsic(block, tree, actions);
09203 }
09204 else
09205 {
09206
09207 if (WN_intrinsic(tree) == INTRN_TLD_ADDR) {
09208
09209 return tree;
09210 }
09211
09212 wn = lower_intrinsic_op(block, tree, actions);
09213 }
09214 }
09215 return wn;
09216 }
09217
09218
09219 #ifdef linux
09220
09221
09222
09223
09224
09225
09226
09227
09228
09229
09230
09231
09232
09233
09234
09235
09236
09237
09238
09239
09240
09241
09242
09243
09244 static WN *lower_cis_intrinsic(WN *block, WN *tree, LOWER_ACTIONS actions)
09245 {
09246 WN *callblock, *call, *parms[3];
09247 INTRINSIC sincos_id;
09248 TYPE_ID real_mtyp, complex_mtyp;
09249 TY_IDX real_ty, complex_ty;
09250 ST *return_sincos;
09251 WN *asinx, *acosx;
09252
09253 complex_mtyp = WN_rtype(tree);
09254 real_mtyp = Mtype_complex_to_real(complex_mtyp);
09255 complex_ty = MTYPE_To_TY(complex_mtyp);
09256 real_ty = MTYPE_To_TY(real_mtyp);
09257
09258 return_sincos = Gen_Temp_Symbol(complex_ty, ".sincos");
09259 acosx = WN_CreateLda(OPR_LDA, Pointer_Mtype, MTYPE_V,
09260 0,
09261 Make_Pointer_Type(real_ty), return_sincos);
09262 asinx = WN_CreateLda(OPR_LDA, Pointer_Mtype, MTYPE_V,
09263 MTYPE_byte_size(real_mtyp),
09264 Make_Pointer_Type(real_ty), return_sincos);
09265
09266 switch (real_mtyp) {
09267 case MTYPE_F4: sincos_id = INTRN_SINCOSF; break;
09268 case MTYPE_F8: sincos_id = INTRN_SINCOS; break;
09269 case MTYPE_F10: sincos_id = INTRN_SINCOSL; break;
09270 default: sincos_id = INTRINSIC_INVALID; break;
09271 }
09272
09273 parms[0] = WN_kid0(tree);
09274 parms[1] = WN_CreateParm(Pointer_type, asinx, MTYPE_To_TY(Pointer_type),
09275 WN_PARM_BY_VALUE);
09276 parms[2] = WN_CreateParm(Pointer_type, acosx, MTYPE_To_TY(Pointer_type),
09277 WN_PARM_BY_VALUE);
09278 call = WN_Create_Intrinsic(OPC_VINTRINSIC_CALL, sincos_id, 3, parms);
09279 WN_Delete(tree);
09280
09281 callblock = WN_CreateBlock();
09282 callblock = lower_block(callblock, actions);
09283 WN_INSERT_BlockLast(block, callblock);
09284
09285 call = lower_intrinsic_call(block, call, actions);
09286 WN_INSERT_BlockLast(block, call);
09287
09288 WN *ldid = WN_Ldid(complex_mtyp, 0, return_sincos, complex_ty);
09289 return lower_expr(block, ldid, actions);
09290 }
09291 #endif
09292
09293
09294
09295
09296
09297
09298
09299
09300
09301
09302
09303
09304
09305
09306
09307
09308
09309
09310
09311 static WN *lower_intrinsic_op(WN *block, WN *tree, LOWER_ACTIONS actions)
09312 {
09313 WN *wn;
09314 OPCODE op = WN_opcode(tree);
09315 INTRINSIC id = WN_intrinsic(tree);
09316
09317 Is_True(Action(LOWER_INTRINSIC),
09318 ("actions does not contain LOWER_INTRINSIC"));
09319 Is_True(OPCODE_is_intrinsic(op),
09320 ("expression is not intrinsic"));
09321
09322 #ifdef linux
09323 switch (id) {
09324 case INTRN_F4CIS:
09325 case INTRN_F8CIS:
09326
09327 return lower_cis_intrinsic(block, tree, actions);
09328 }
09329 #endif
09330
09331
09332
09333
09334
09335 wn = lower_intrinsic(block, tree, actions);
09336
09337 Is_True(OPCODE_is_call(WN_opcode(wn)),
09338 ("lowered instrinsic op is not a call"));
09339 WN_INSERT_BlockLast(block, wn);
09340
09341 {
09342 TYPE_ID ty1, ty2;
09343 PREG_NUM reg1, reg2;
09344 TYPE_ID type = WN_rtype(tree);
09345
09346 rename_preg(INTR_intrinsic_name(tree), ".return");
09347
09348 if (WHIRL_Return_Info_On) {
09349
09350 RETURN_INFO return_info = Get_Return_Info (MTYPE_To_TY(type),
09351 Complex_Not_Simulated);
09352
09353 if (RETURN_INFO_count(return_info) <= 2) {
09354
09355 ty1 = RETURN_INFO_mtype (return_info, 0);
09356 ty2 = RETURN_INFO_mtype (return_info, 1);
09357 reg1 = RETURN_INFO_preg (return_info, 0);
09358 reg2 = RETURN_INFO_preg (return_info, 1);
09359 }
09360
09361 else
09362 Fail_FmtAssertion("lower_intrinsic_op: more than 2 return registers");
09363
09364 }
09365
09366 else
09367 Get_Return_Mtypes(MTYPE_To_TY(type), Complex_Not_Simulated, &ty1, &ty2);
09368
09369 switch(type)
09370 {
09371 case MTYPE_C4:
09372 case MTYPE_C8:
09373 {
09374 PREG_NUM rzN, izN;
09375 TYPE_ID real = Mtype_complex_to_real(type);
09376
09377 if (!WHIRL_Return_Info_On)
09378 Get_Return_Pregs ( ty1, ty2, ®1, ®2 );
09379 Is_True((reg1 && reg2),
09380 ("expected complex return value from intrinsic_op"));
09381
09382 rzN = AssignExpr(block, WN_LdidPreg(real, reg1), real);
09383 izN = AssignExpr(block, WN_LdidPreg(real, reg2), real);
09384
09385 wn = WN_Complex(type,
09386 WN_LdidPreg(real, rzN),
09387 WN_LdidPreg(real, izN));
09388 }
09389 break;
09390
09391 case MTYPE_CQ:
09392
09393
09394
09395
09396
09397
09398 {
09399 TYPE_ID real = Mtype_complex_to_real(type);
09400 TY_IDX realTY = MTYPE_To_TY(real);
09401 WN *temp,*temp1, *actual = WN_kid0(wn);
09402
09403 if (WN_operator_is(actual, OPR_PARM))
09404 actual = WN_kid0(actual);
09405
09406 temp = lower_copy_tree( actual, actions);
09407 temp1 = lower_copy_tree( actual, actions);
09408
09409 Is_True((OPCODE_is_call(WN_opcode(wn))), ("expected call opcode"));
09410
09411 wn = WN_Complex(type,
09412 WN_Iload(real, 0, realTY, temp),
09413 WN_Iload(real, MTYPE_RegisterSize(real),
09414 realTY, temp1));
09415 }
09416 break;
09417
09418 default:
09419 {
09420 PREG_NUM retReg;
09421
09422 if (!WHIRL_Return_Info_On)
09423 Get_Return_Pregs ( ty1, ty2, ®1, ®2 );
09424
09425 Is_True((reg1 != 0), ("expected return value from intrinsic_op"));
09426 Is_True((reg2 == 0), ("cannot evaluate 2 regs into an expression"));
09427
09428 retReg = AssignExpr(block,
09429 WN_LdidPreg(ty1, reg1),
09430 type);
09431
09432 wn = WN_LdidPreg(type, retReg);
09433 }
09434 break;
09435 }
09436 rename_reset();
09437 }
09438
09439
09440
09441
09442
09443
09444
09445
09446
09447
09448 switch (id) {
09449 case INTRN_CEQEXPR:
09450 wn = WN_EQ(Boolean_type, wn, WN_Zerocon(Boolean_type));
09451 break;
09452 case INTRN_CNEEXPR:
09453 wn = WN_NE(Boolean_type, wn, WN_Zerocon(Boolean_type));
09454 break;
09455 case INTRN_CGEEXPR:
09456 wn = WN_GE(Boolean_type, wn, WN_Zerocon(Boolean_type));
09457 break;
09458 case INTRN_CGTEXPR:
09459 wn = WN_GT(Boolean_type, wn, WN_Zerocon(Boolean_type));
09460 break;
09461 case INTRN_CLEEXPR:
09462 wn = WN_LE(Boolean_type, wn, WN_Zerocon(Boolean_type));
09463 break;
09464 case INTRN_CLTEXPR:
09465 wn = WN_LT(Boolean_type, wn, WN_Zerocon(Boolean_type));
09466 break;
09467 }
09468
09469
09470
09471
09472 return lower_expr(block, wn, actions);
09473 }
09474
09475
09476
09477
09478
09479
09480
09481
09482
09483
09484
09485
09486
09487
09488 static WN *lower_intrinsic(WN *block, WN *tree, LOWER_ACTIONS actions)
09489 {
09490
09491 Is_True(Action(LOWER_INTRINSIC),
09492 ("actions does not contain LOWER_INTRINSIC"));
09493 Is_True(OPCODE_is_intrinsic(WN_opcode(tree)),
09494 ("expression is not intrinsic"));
09495
09496 {
09497 INTRINSIC id = (INTRINSIC) WN_intrinsic(tree);
09498
09499 if (INTRN_is_actual(id))
09500 {
09501
09502
09503
09504
09505 TYPE_ID rtype = WN_rtype(tree);
09506 WN *lda;
09507 {
09508 TY_IDX ty = Make_Function_Type(MTYPE_To_TY(rtype));
09509 ST *st = Gen_Intrinsic_Function(ty, INTRN_rt_name(id));
09510 lda = WN_Lda(Pointer_type, 0, st);
09511 }
09512
09513 WN_Delete(tree);
09514 return lower_expr(block, lda, actions);
09515 }
09516 }
09517 {
09518
09519
09520
09521
09522 WN *call, *callblock;
09523
09524 callblock = WN_CreateBlock();
09525
09526 call = intrinsic_runtime(callblock, tree);
09527
09528 callblock = lower_block(callblock, actions);
09529 WN_INSERT_BlockLast(block, callblock);
09530
09531 if (Action(LOWER_TO_CG))
09532 actions |= LOWER_CALL;
09533 call = lower_call(block, call, actions);
09534
09535 return call;
09536 }
09537 }
09538
09539
09540
09541
09542
09543
09544
09545
09546
09547
09548
09549
09550 static WN *lower_actual(WN *block, WN *actual, TYPE_ID parmType, INT32 reg)
09551 {
09552
09553
09554
09555 if (MTYPE_float(parmType) && Preg_Offset_Is_Int(reg))
09556 {
09557 TYPE_ID type = TY_mtype(ST_type(Int_Preg));
09558
09559 actual = WN_Tas(type, ST_type(Int_Preg), actual);
09560 }
09561
09562 {
09563 WN *stid;
09564 ST *regST;
09565
09566 if (Preg_Offset_Is_Int(reg))
09567 regST = Int_Preg;
09568 else
09569
09570 regST= MTYPE_To_PREG(parmType);
09571
09572 TYPE_ID type = TY_mtype(ST_type(regST));
09573
09574 stid = WN_StidIntoPreg (type, reg, regST, actual);
09575 WN_Set_Linenum(stid, current_srcpos);
09576 WN_INSERT_BlockLast(block, stid);
09577 }
09578
09579 return actual;
09580 }
09581
09582
09583
09584
09585
09586
09587
09588
09589
09590
09591 static WN *lower_profile_call(WN *block, WN *tree, INT32 state,
09592 LOWER_ACTIONS actions)
09593 {
09594 if (Gen_Profile && WN_has_sym(current_function))
09595 {
09596 WN *profcall;
09597 char *name;
09598
09599 {
09600 TY_IDX ty = Make_Function_Type(MTYPE_To_TY(MTYPE_V));
09601 ST *st = Gen_Intrinsic_Function(ty, Gen_Profile_Name);
09602
09603 Set_PU_no_side_effects(Pu_Table[ST_pu(st)]);
09604 Set_PU_is_pure(Pu_Table[ST_pu(st)]);
09605
09606 profcall = WN_Call(MTYPE_V, MTYPE_V, 5, st);
09607 }
09608
09609 ST *current_fcn_st = WN_st(current_function);
09610
09611 WN_actual(profcall, 0) = WN_Lda(Pointer_type, 0, current_fcn_st);
09612 name = ST_name(current_fcn_st);
09613 WN_actual(profcall, 2) = WN_LdaString(name, 0, strlen(name)+1);
09614 WN_actual(profcall, 4) = WN_Intconst(MTYPE_I4, state);
09615
09616 if (WN_has_sym(tree))
09617 {
09618 ST *st = WN_st(tree);
09619
09620 WN_actual(profcall, 1) = WN_Lda(Pointer_type, 0, st);
09621 name = ST_name(st);
09622 WN_actual(profcall, 3) = WN_LdaString(name, 0, strlen(name)+1);
09623 }
09624 else
09625 {
09626 Is_True((WN_operator_is(tree, OPR_ICALL)),
09627 ("expected icall node, not %s", OPCODE_name(WN_opcode(tree))));
09628
09629 WN_actual(profcall, 1)
09630 = lower_copy_tree(WN_actual(tree, WN_num_actuals(tree)), actions);
09631 WN_actual(profcall, 3) = WN_Zerocon(Pointer_type);
09632 }
09633
09634 Gen_Profile = FALSE;
09635 profcall = lower_call(block, profcall, actions);
09636 Gen_Profile = TRUE;
09637
09638 return profcall;
09639 }
09640 return NULL;
09641 }
09642
09643
09644
09645
09646
09647
09648
09649
09650
09651
09652
09653 static WN *lower_call(WN *block, WN *tree, LOWER_ACTIONS actions)
09654 {
09655 INT16 i;
09656 PLOC ploc;
09657 TY_IDX call_ty;
09658 WN *callblock;
09659 SRCPOS srcpos = WN_Get_Linenum(tree);
09660 INT num_actuals = WN_num_actuals(tree);
09661 ST *callee_st = NULL;
09662
09663 Is_True(OPERATOR_is_call(WN_operator(tree)),
09664 ("expected call node, not %s", OPERATOR_name(WN_operator(tree))));
09665
09666 for (i = 0; i < WN_kid_count(tree); i++)
09667 WN_actual(tree, i) = lower_expr(block, WN_actual(tree, i), actions);
09668
09669
09670 if (WN_has_sym(tree)) {
09671 callee_st = WN_st(tree);
09672 }
09673
09674 if (WHIRL_Return_Val_On && Action(LOWER_RETURN_VAL) &&
09675 WN_rtype(tree) == MTYPE_V &&
09676 (WN_operator(tree) == OPR_CALL || WN_operator(tree) == OPR_ICALL ||
09677 WN_operator(tree) == OPR_PICCALL)) {
09678
09679
09680 TY_IDX prototype;
09681 if (WN_operator(tree) == OPR_ICALL)
09682 prototype = WN_ty(tree);
09683 else {
09684 ST_IDX func_stidx = WN_st_idx(tree);
09685 PU_IDX puidx = ST_pu(St_Table[func_stidx]);
09686 prototype = PU_prototype(Pu_Table[puidx]);
09687 }
09688 RETURN_INFO return_info = Get_Return_Info(TY_ret_type(prototype),
09689 Complex_Not_Simulated);
09690 if (RETURN_INFO_return_via_first_arg(return_info)) {
09691 ST *return_st = Gen_Temp_Symbol(TY_ret_type(prototype), ".vcall");
09692 WN *awn = WN_CreateLda(OPR_LDA, Pointer_Mtype, MTYPE_V, 0,
09693 Make_Pointer_Type(TY_ret_type(prototype)),
09694 return_st);
09695 awn = lower_expr(block, awn, actions);
09696 WN *n_call = add_fake_parm(tree, awn, WN_ty(awn));
09697 WN_Delete(tree);
09698 tree = n_call;
09699 }
09700 }
09701
09702 if (Action(LOWER_PICCALL))
09703 {
09704
09705
09706
09707
09708
09709
09710
09711
09712 if (WN_operator_is(tree, OPR_CALL) &&
09713 (Force_Jalr ||
09714 PU_needs_t9(Pu_Table[ST_pu(callee_st)]) ||
09715 (Gen_PIC_Calls &&
09716 (Gen_PIC_Shared ||
09717 (Gen_PIC_Call_Shared &&
09718 ST_visible_outside_dso(*callee_st)) ))))
09719 {
09720 INT16 n = WN_kid_count(tree);
09721 WN *itree;
09722
09723
09724
09725
09726 itree = WN_Piccall( WN_rtype(tree), WN_desc(tree), n+1, callee_st);
09727
09728 Is_True(callee_st == WN_st(tree),
09729 ("lower_call: something changed that Robert didn't expect!"));
09730 WN_actual(itree, n) = WN_Lda(Pointer_type, 0, callee_st);
09731 WN_Set_Linenum(itree, srcpos);
09732 WN_Set_Flags(tree, itree);
09733
09734 while (--n >= 0)
09735 WN_actual(itree, n) = WN_actual(tree, n);
09736
09737 if (Cur_PU_Feedback) {
09738 Cur_PU_Feedback->FB_lower_call( tree, itree );
09739 }
09740 WN_Delete(tree);
09741 tree = itree;
09742 }
09743 }
09744
09745 if (NotAction(LOWER_CALL))
09746 return tree;
09747
09748
09749
09750
09751
09752 if (Gen_Profile)
09753 {
09754 WN *profcall = lower_profile_call(block, tree, 0, actions);
09755 WN_INSERT_BlockLast (block, profcall);
09756 }
09757
09758 callblock = WN_CreateBlock();
09759
09760
09761
09762
09763
09764
09765
09766
09767
09768
09769
09770
09771
09772
09773
09774
09775
09776
09777
09778
09779 call_ty = (WN_operator_is(tree,OPR_ICALL) ? WN_ty(tree) :
09780 ST_pu_type(callee_st));
09781 Is_True(WN_operator_is(tree, OPR_ICALL) ||
09782 callee_st == WN_st(tree),
09783 ("lower_call: something changed that Robert didn't expect!"));
09784 ploc = Setup_Output_Parameter_Locations(call_ty);
09785
09786 for (i = 0; i < num_actuals; i++)
09787 {
09788 WN *parm = WN_actual(tree, i);
09789 TYPE_ID parmType = WN_rtype(parm);
09790 WN *actual = WN_operator_is(parm, OPR_PARM) ? WN_kid0(parm)
09791 : parm;
09792
09793 if (MTYPE_is_m(parmType))
09794 {
09795
09796
09797
09798 ploc = Get_Output_Parameter_Location( TY_Of_Parameter(parm));
09799 lower_mload_actual (callblock, actual, ploc, actions);
09800 }
09801 else if (MTYPE_is_complex(parmType) && PU_ftn_lang(Get_Current_PU()))
09802 {
09803
09804
09805
09806
09807
09808
09809 ploc = Get_Output_Parameter_Location( TY_Of_Parameter(parm));
09810 lower_complex_actual (callblock, actual, ploc, actions);
09811 }
09812 else
09813 {
09814 ploc = Get_Output_Parameter_Location( MTYPE_To_TY(parmType));
09815 }
09816 }
09817
09818 ploc = Setup_Output_Parameter_Locations(call_ty);
09819 for (i = 0; i < num_actuals; i++)
09820 {
09821
09822
09823
09824
09825
09826
09827 WN *parm = WN_actual(tree, i);
09828 TYPE_ID parmType = WN_rtype(parm);
09829 WN *actual = WN_operator_is(parm, OPR_PARM) ? WN_kid0(parm) : parm;
09830 TY_IDX ty;
09831
09832 if (MTYPE_is_m(parmType)
09833 || (MTYPE_is_complex(parmType) && PU_ftn_lang(Get_Current_PU())) )
09834 {
09835
09836
09837
09838 ploc = Get_Output_Parameter_Location( TY_Of_Parameter(parm));
09839 continue;
09840 }
09841
09842 ty = TY_Of_Parameter(parm);
09843 ploc = Get_Output_Parameter_Location( MTYPE_To_TY(parmType));
09844 {
09845
09846
09847
09848 TYPE_ID type = Mtype_comparison( Fix_TY_mtype(ty));
09849
09850 if (parmType != type)
09851 {
09852 DevWarn("lower_call(): line %d, parm #%d type mismatch (WN_rtype(parm)"
09853 " = %s) (cannonical TY_mtype(parm))) %s)",
09854 Srcpos_To_Line(WN_Get_Linenum(tree)), i,
09855 Mtype_Name(parmType), Mtype_Name(type));
09856 }
09857 }
09858
09859 if (PLOC_on_stack(ploc))
09860 {
09861
09862
09863
09864
09865
09866 WN *wn;
09867
09868 wn = WN_Stid(parmType, PLOC_offset(ploc) - Formal_Save_Area_Size
09869 + Stack_Offset_Adjustment,
09870 SP_Sym, ty, actual);
09871 WN_Set_Linenum(wn, srcpos);
09872 WN_INSERT_BlockLast(callblock, wn);
09873 }
09874
09875
09876
09877
09878 else if (MTYPE_is_quad(parmType) && Preg_Offset_Is_Int(PLOC_reg(ploc)))
09879 {
09880 PREG_NUM qN;
09881
09882 qN = AssignExpr(callblock, actual, parmType);
09883
09884 lower_actual(callblock, WN_LdidPreg(MTYPE_F8, qN), MTYPE_F8,
09885 PLOC_reg(ploc));
09886
09887 lower_actual(callblock, WN_LdidPreg(MTYPE_F8, qN+1), MTYPE_F8,
09888 PLOC_reg(ploc)+1);
09889 }
09890 else
09891 {
09892 actual = lower_actual(callblock, actual, parmType, PLOC_reg(ploc));
09893
09894 if (WN_operator_is(parm, OPR_PARM))
09895 WN_kid0(parm) = actual;
09896 else
09897 WN_actual(tree, i) = actual;
09898
09899 if (! TY_has_prototype(call_ty) &&
09900 DEBUG_Varargs_Prototypes == FALSE &&
09901 Preg_Offset_Is_Float(PLOC_reg(ploc)))
09902 {
09903 actual = lower_copy_tree(actual, actions);
09904
09905 if (MTYPE_is_quad(parmType))
09906 {
09907 PREG_NUM qN;
09908
09909 qN = AssignExpr(callblock, actual, parmType);
09910
09911 lower_actual(callblock, WN_LdidPreg(MTYPE_F8, qN), MTYPE_F8,
09912 PLOC_vararg_reg(ploc));
09913 lower_actual(callblock, WN_LdidPreg(MTYPE_F8, qN+1), MTYPE_F8,
09914 PLOC_vararg_reg(ploc)+1);
09915 }
09916 else
09917 {
09918 lower_actual(callblock, actual, parmType, PLOC_vararg_reg(ploc));
09919 }
09920 }
09921 }
09922 }
09923
09924
09925
09926
09927
09928 if (num_actuals > 0 &&
09929 TY_has_prototype(call_ty) &&
09930 Get_PU_arg_area_size(call_ty) == 0 &&
09931 ! TY_is_varargs(call_ty))
09932 {
09933 Set_PU_arg_area_size(call_ty, PLOC_total_size(ploc));
09934 }
09935
09936
09937
09938
09939
09940
09941
09942 {
09943 INT16 n= num_actuals;
09944
09945 while (--n >= 0)
09946 WN_actual(tree, n) = lower_copy_tree( WN_actual(tree, n), actions);
09947 }
09948
09949 if (MTYPE_is_complex(WN_rtype(tree)))
09950 {
09951 INT16 n = WN_kid_count(tree);
09952 WN *itree;
09953 TYPE_ID rtype, desc;
09954
09955 rtype = Mtype_complex_to_real(WN_rtype(tree));
09956 desc = Mtype_complex_to_real(WN_desc(tree));
09957
09958
09959
09960
09961
09962 if (WN_operator_is(tree, OPR_CALL))
09963 {
09964 itree = WN_Call( rtype, desc, n, WN_st(tree));
09965 }
09966 else if (WN_operator_is(tree, OPR_ICALL))
09967 {
09968 itree = WN_Icall( rtype, desc, n, WN_ty(tree));
09969 }
09970 WN_Set_Linenum(itree, srcpos);
09971 WN_Set_Flags(tree, itree);
09972
09973 while (--n >= 0)
09974 WN_actual(itree, n) = WN_actual(tree, n);
09975
09976 if (Cur_PU_Feedback) {
09977 Cur_PU_Feedback->FB_lower_call( tree, itree );
09978 }
09979 WN_Delete(tree);
09980 tree = itree;
09981 }
09982
09983
09984
09985
09986
09987 if (Action(LOWER_UPLEVEL))
09988 {
09989 if (callee_st && PU_is_nested_func(Pu_Table[ST_pu(callee_st)]))
09990 {
09991 WN *wn, *link;
09992
09993
09994
09995
09996
09997
09998 if (PU_lexical_level(&St_Table[WN_st_idx(current_function)]) <
09999 PU_lexical_level(callee_st))
10000 {
10001 link = WN_LdidPreg(Pointer_type, Frame_Pointer_Preg_Offset);
10002 }
10003
10004
10005
10006
10007
10008 else
10009 {
10010 ST *slink = Find_Slink_For_Scope(WN_st(current_function),
10011 callee_st);
10012
10013 link = WN_Ldid (Pointer_type, 0, slink, ST_type(slink));
10014 }
10015
10016 wn = WN_StidIntoPreg(Pointer_type,
10017 Static_Link_Preg_Offset,
10018 MTYPE_To_PREG(Pointer_type), link);
10019
10020 WN_Set_Linenum(wn, srcpos);
10021 WN_INSERT_BlockLast(callblock, wn);
10022 }
10023 }
10024
10025
10026
10027
10028
10029 Check_Actual_Stack_Size (tree);
10030
10031 callblock = lower_block(callblock, actions);
10032 WN_INSERT_BlockLast (block, callblock);
10033
10034
10035
10036
10037
10038
10039
10040
10041
10042
10043
10044
10045 return tree;
10046 }
10047
10048
10049
10050
10051
10052
10053
10054
10055
10056
10057
10058
10059
10060
10061
10062 static WN *lower_compgoto(WN *block, WN *tree, LOWER_ACTIONS actions)
10063 {
10064 INT32 pointerSize = MTYPE_RegisterSize(Pointer_type);
10065 INT32 num_entries = WN_num_entries(tree);
10066 WN *index, *add;
10067 ST *table_st;
10068 LEAF indexN, addN;
10069
10070 Is_True(WN_opcode(tree) == OPC_COMPGOTO,
10071 ("expected COMPGOTO node, not %s", OPCODE_name(WN_opcode(tree))));
10072 Is_True(WN_num_entries(tree) > 0,
10073 ("expected COMPGOTO nu,_entries > 0 not %d", WN_num_entries(tree)));
10074
10075 WN_kid0(tree) = lower_expr(block,
10076 WN_Coerce(Pointer_type, WN_kid0(tree)),
10077 actions);
10078
10079 if (NotAction(LOWER_COMPGOTO))
10080 return tree;
10081
10082 index = WN_kid0(tree);
10083
10084 indexN = Make_Leaf(block, WN_Coerce(Pointer_type, index), Pointer_type);
10085
10086
10087
10088
10089
10090
10091
10092
10093
10094
10095 {
10096 TY_IDX table;
10097 WN *mpy;
10098
10099 table = Make_Array_Type(Pointer_type, 1, num_entries);
10100
10101 table_st = Gen_Read_Only_Symbol (table, "jump_table");
10102 Set_ST_is_initialized(table_st);
10103
10104 mpy = WN_Mpy(Pointer_type,
10105 Load_Leaf(indexN),
10106 WN_Intconst(Pointer_type, pointerSize));
10107
10108 add = WN_Add(Pointer_type,
10109 WN_Lda (Pointer_type, 0, table_st),
10110 mpy);
10111 addN = Make_Leaf(block, add, Pointer_type);
10112 }
10113
10114
10115
10116
10117 WN *wn_truebr = NULL;
10118 if (WN_kid_count(tree) == 3)
10119 {
10120
10121
10122
10123
10124
10125 WN *ge, *truebr;
10126 WN *def = WN_kid2(tree);
10127
10128 ge = WN_GE(Pointer_type,
10129 Load_Leaf(indexN),
10130 WN_Intconst(Pointer_type, num_entries));
10131
10132 truebr = lower_truebr(WN_label_number(def), ge, &wn_truebr, actions);
10133 WN_INSERT_BlockLast(block, truebr);
10134 }
10135
10136
10137
10138
10139
10140
10141
10142 {
10143 WN *xgoto;
10144 WN *gotoTable = WN_kid1(tree);
10145
10146 index = WN_Iload(Pointer_type,
10147 0,
10148 MTYPE_To_TY(Pointer_type),
10149 Load_Leaf(addN));
10150
10151 index = lower_expr(block, index, actions);
10152
10153 xgoto = WN_CreateXgoto(num_entries, index, gotoTable, table_st);
10154 WN_Set_Linenum (xgoto, WN_Get_Linenum(tree));
10155
10156
10157 if ( Cur_PU_Feedback )
10158 Cur_PU_Feedback->FB_lower_compgoto( tree, xgoto, wn_truebr );
10159
10160 return xgoto;
10161 }
10162 }
10163
10164
10165
10166
10167
10168
10169
10170
10171
10172
10173
10174
10175
10176 static WN *lower_assert(WN *block, WN *tree, LOWER_ACTIONS actions)
10177 {
10178 WN *if_else, *if_then, *IF, *trap, *cond;
10179
10180 Is_True(WN_opcode(tree) == OPC_ASSERT,
10181 ("expected ASSERT node, not %s", OPCODE_name(WN_opcode(tree))));
10182
10183 WN_kid0(tree) = lower_expr(block, WN_kid0(tree), actions);
10184
10185 if (NotAction(LOWER_ASSERT))
10186 return tree;
10187
10188 if_then = WN_CreateBlock();
10189 if_else = WN_CreateBlock();
10190 cond = lower_expr(block, WN_kid0(tree), actions);
10191
10192
10193
10194
10195 switch ( WN_offset(tree) ) {
10196 case WN_TRAP_F77_BOUNDS_ERROR:
10197 {
10198 char *name;
10199 WN **kids = (WN **) alloca(4 * sizeof(WN *));
10200
10201
10202 kids[0] = WN_LdaString ( "? ", 0, 2 );
10203 kids[1] = WN_Intconst ( MTYPE_I4, -1 );
10204
10205
10206 name = ST_name(&St_Table[PU_Info_proc_sym(Current_PU_Info)]);
10207 kids[2] = WN_LdaString ( name, 0, strlen(name)+1 );
10208
10209 kids[3] = WN_Intconst(MTYPE_I4, Srcpos_To_Line(WN_Get_Linenum(tree)));
10210 trap = WN_Create_Intrinsic ( OPC_VINTRINSIC_CALL,
10211 INTRN_F77_BOUNDS_ERR, 4, kids );
10212 }
10213 break;
10214
10215 case WN_TRAP_C_BOUNDS_ERROR:
10216
10217
10218
10219
10220
10221
10222 if ( DEBUG_Verbose_Runtime ) {
10223 char *name;
10224 WN **kids = (WN **) alloca(4 * sizeof(WN *));
10225
10226
10227
10228
10229
10230 #if defined(__sgi)
10231 kids[0] = WN_Intconst ( MTYPE_I4, BRK_RANGE );
10232 #else
10233 fprintf(stderr, "Don't know how to do BRK_RANGE\n");
10234 exit(-1);
10235 #endif
10236
10237
10238 name = ST_name(&St_Table[PU_Info_proc_sym(Current_PU_Info)]);
10239 kids[1] = WN_LdaString ( name, 0, strlen(name)+1 );
10240
10241
10242 kids[2] = WN_Intconst ( MTYPE_I4,
10243 Srcpos_To_Line(WN_Get_Linenum(tree)) );
10244
10245
10246
10247
10248
10249 kids[3] = WN_LdaString ( "unknown array", 0, 14 );
10250
10251
10252 trap = WN_Create_Intrinsic ( OPC_VINTRINSIC_CALL,
10253 INTRN_RT_ERR, 4, kids );
10254 } else {
10255
10256
10257 #if defined(__sgi)
10258 trap = WN_CreateTrap ( BRK_RANGE );
10259 #else
10260 fprintf(stderr, "Don't know how to do BRK_RANGE\n");
10261 exit(-1);
10262 #endif
10263
10264
10265 }
10266 break;
10267
10268 default:
10269 trap = WN_CreateTrap ( WN_offset(tree) );
10270
10271 break;
10272 }
10273
10274 WN_Set_Linenum(trap, WN_Get_Linenum(tree));
10275 WN_INSERT_BlockLast(if_else, trap);
10276
10277 IF = WN_CreateIf(cond, if_then, if_else);
10278
10279 WN_Set_Linenum(IF, WN_Get_Linenum(tree));
10280 WN_Delete(tree);
10281
10282 IF = lower_scf(block, IF, actions);
10283 return IF;
10284 }
10285
10286
10287 static WN *lower_branch(WN *block, WN *tree, LOWER_ACTIONS actions)
10288 {
10289 Is_True((WN_opcode(tree) == OPC_TRUEBR || WN_opcode(tree) == OPC_FALSEBR),
10290 ("expected true/false"));
10291
10292 WN * const kid = lower_expr(block, WN_kid0(tree), actions);
10293 WN_kid0(tree) = kid;
10294
10295 if (WN_operator(kid) == OPR_LNOT)
10296 {
10297 switch(WN_opcode(tree))
10298 {
10299 case OPC_TRUEBR:
10300 WN_set_opcode(tree, OPC_FALSEBR);
10301 break;
10302
10303 case OPC_FALSEBR:
10304 WN_set_opcode(tree, OPC_TRUEBR);
10305 break;
10306
10307 default:
10308 break;
10309 }
10310
10311 WN_kid0(tree) = WN_kid0(kid);
10312 WN_Delete(kid);
10313 }
10314
10315 return tree;
10316 }
10317
10318
10319
10320
10321
10322
10323
10324
10325
10326
10327
10328
10329 static WN *lower_return_val(WN *block, WN *tree, LOWER_ACTIONS actions)
10330 {
10331 PREG_NUM preg;
10332 ST *preg_st;
10333 TYPE_ID mtype;
10334 RETURN_INFO return_info;
10335 WN *wn;
10336
10337 Is_True((WN_operator(tree) == OPR_RETURN_VAL),
10338 ("expected RETURN_VAL node, not %s", OPCODE_name(WN_opcode(tree))));
10339
10340 TYPE_ID return_mtype = WN_rtype(tree);
10341
10342 if (return_mtype != MTYPE_M) {
10343 TY_IDX return_ty_idx = Be_Type_Tbl(return_mtype);
10344 return_info = Get_Return_Info (return_ty_idx, Use_Simulated);
10345
10346 WN_kid0(tree) = lower_expr (block, WN_kid0(tree), actions);
10347 if (RETURN_INFO_return_via_first_arg(return_info)) {
10348
10349
10350
10351 WN *first_formal = WN_formal(current_function, 0);
10352 TY_IDX tidx = ST_type(WN_st(first_formal));
10353 OPCODE const_op = OPCODE_make_op(OPR_INTCONST, MTYPE_I8, MTYPE_V);
10354
10355 WN *awn = WN_CreateLdid(OPR_LDID,
10356 TY_mtype(Ty_Table[tidx]),
10357 TY_mtype(Ty_Table[tidx]),
10358 WN_idname_offset(first_formal),
10359 WN_st(first_formal),
10360 tidx);
10361
10362 wn = WN_CreateIstore(OPR_ISTORE, MTYPE_V,
10363 return_mtype, 0, tidx, WN_kid0(tree), awn);
10364 } else {
10365 Is_True(RETURN_INFO_count(return_info) == 1,
10366 ("expected return_info count to be 1"));
10367
10368 mtype = RETURN_INFO_mtype (return_info, 0);
10369 preg = RETURN_INFO_preg (return_info, 0);
10370 preg_st = (MTYPE_is_float(mtype) ? Float_Preg :
10371 ((mtype==MTYPE_I8 || mtype==MTYPE_U8) ? MTYPE_To_PREG(mtype) :
10372 Int_Preg));
10373
10374 wn = WN_CreateStid (OPR_STID, MTYPE_V, Promoted_Mtype[mtype],
10375 preg, preg_st, Be_Type_Tbl(mtype), WN_kid0(tree));
10376 }
10377 WN_INSERT_BlockLast (block, wn);
10378 }
10379 else {
10380 WN *o_rhs = WN_kid0(tree);
10381 OPERATOR rhs_opr = WN_operator(o_rhs);
10382 TY_IDX ty_idx = WN_ty(o_rhs);
10383 if (OPERATOR_is_load(rhs_opr) && WN_field_id(o_rhs) != 0) {
10384 if (rhs_opr == OPR_ILOAD || rhs_opr == OPR_LDID)
10385 ty_idx = get_field_type(ty_idx, WN_field_id(o_rhs));
10386 else {
10387 ty_idx = TY_pointed(Ty_Table[ty_idx]);
10388 ty_idx = get_field_type(ty_idx, WN_field_id(o_rhs));
10389 }
10390 }
10391 return_info = Get_Return_Info(ty_idx, Complex_Not_Simulated);
10392
10393 if (RETURN_INFO_return_via_first_arg(return_info)) {
10394 Is_True(RETURN_INFO_count(return_info) == 0,
10395 ("expected RETURN_INFO to have 0 count"));
10396 WN *n_rhs;
10397
10398
10399 if (WN_operator(o_rhs) == OPR_LDID)
10400 n_rhs = lower_mldid(block, o_rhs, LOWER_MLDID_MSTID);
10401 else if (WN_operator(o_rhs) == OPR_ILOAD)
10402 n_rhs = lower_miload(block, o_rhs, LOWER_MLDID_MSTID);
10403 else n_rhs = o_rhs;
10404
10405
10406 WN *first_formal = WN_formal(current_function, 0);
10407 TY_IDX tidx = ST_type(WN_st(first_formal));
10408 WN *awn = WN_CreateLdid(OPR_LDID,
10409 TY_mtype(Ty_Table[tidx]),
10410 TY_mtype(Ty_Table[tidx]),
10411 WN_idname_offset(first_formal),
10412 WN_st(first_formal),
10413 tidx);
10414 WN *swn = WN_CopyNode(WN_kid1(n_rhs));
10415 wn = WN_CreateMstore (0, tidx, n_rhs, awn, swn);
10416
10417 WN_INSERT_BlockLast (block, wn);
10418 }
10419 else {
10420 INT32 i;
10421 WN *n_rhs;
10422 UINT algn;
10423 TY_IDX ty_idx_used;
10424
10425 if (WN_operator(o_rhs) == OPR_LDID) {
10426 Is_True(WN_rtype(o_rhs) == MTYPE_M,
10427 ("expected RETURN_VAL kid not type M"));
10428
10429 algn = TY_align(ty_idx);
10430 for (i = 0; i < RETURN_INFO_count(return_info); i++) {
10431 mtype = RETURN_INFO_mtype(return_info, i);
10432 ty_idx_used = Be_Type_Tbl(mtype);
10433 Set_TY_align(ty_idx_used, algn);
10434 n_rhs = WN_CreateLdid (OPR_LDID, mtype, mtype,
10435 WN_load_offset(o_rhs)
10436 + i * MTYPE_byte_size(mtype),
10437 WN_st_idx(o_rhs), ty_idx_used);
10438 preg = RETURN_INFO_preg (return_info, i);
10439 preg_st = MTYPE_is_float(mtype) ? Float_Preg : Int_Preg;
10440 wn = WN_CreateStid(OPR_STID, MTYPE_V, mtype, preg, preg_st,
10441 Be_Type_Tbl(mtype), n_rhs);
10442 WN_INSERT_BlockLast (block, wn);
10443 }
10444 }
10445 else if (WN_operator(o_rhs) == OPR_ILOAD) {
10446 Is_True(WN_rtype(o_rhs) == MTYPE_M,
10447 ("expected RETURN_VAL kid not type M"));
10448
10449 algn = TY_align(ty_idx);
10450 for (i = 0; i < RETURN_INFO_count(return_info); i++) {
10451 mtype = RETURN_INFO_mtype(return_info, i);
10452 ty_idx_used = Be_Type_Tbl(mtype);
10453 Set_TY_align(ty_idx_used, algn);
10454 if (i == 0)
10455 n_rhs = WN_kid0(o_rhs);
10456 else n_rhs = WN_COPY_Tree(WN_kid0(o_rhs));
10457 n_rhs = WN_CreateIload(OPR_ILOAD, mtype, mtype,
10458 WN_load_offset(o_rhs)
10459 + i * MTYPE_byte_size(mtype),
10460 ty_idx_used,
10461 Make_Pointer_Type(ty_idx_used), n_rhs);
10462 n_rhs = lower_expr(block, n_rhs, actions);
10463 preg = RETURN_INFO_preg (return_info, i);
10464 preg_st = MTYPE_is_float(mtype) ? Float_Preg : Int_Preg;
10465 wn = WN_CreateStid(OPR_STID, MTYPE_V, mtype, preg, preg_st,
10466 Be_Type_Tbl(mtype), n_rhs);
10467 WN_INSERT_BlockLast (block, wn);
10468 }
10469 }
10470 else {
10471 Is_True(WN_operator(WN_kid1(o_rhs)) == OPR_INTCONST,
10472 ("expected RETURN_VAL's MLOAD kid to be of constant size"));
10473 algn = TY_align(TY_pointed(WN_load_addr_ty(o_rhs)));
10474 for (i = 0; i < RETURN_INFO_count(return_info); i++) {
10475 mtype = RETURN_INFO_mtype(return_info, i);
10476 ty_idx_used = Be_Type_Tbl(mtype);
10477 Set_TY_align(ty_idx_used, algn);
10478 if (i == 0)
10479 n_rhs = WN_kid0(o_rhs);
10480 else n_rhs = WN_COPY_Tree(WN_kid0(o_rhs));
10481 n_rhs = WN_CreateIload(OPR_ILOAD, mtype, mtype,
10482 WN_load_offset(o_rhs)
10483 + i * MTYPE_byte_size(mtype),
10484 ty_idx_used,
10485 Make_Pointer_Type(ty_idx_used), n_rhs);
10486 n_rhs = lower_expr(block, n_rhs, actions);
10487 preg = RETURN_INFO_preg (return_info, i);
10488 preg_st = MTYPE_is_float(mtype) ? Float_Preg : Int_Preg;
10489 wn = WN_CreateStid(OPR_STID, MTYPE_V, mtype, preg, preg_st,
10490 Be_Type_Tbl(mtype), n_rhs);
10491 WN_INSERT_BlockLast (block, wn);
10492 }
10493 }
10494
10495 WN_Delete (o_rhs);
10496 }
10497 }
10498
10499 WN *wn_return = WN_CreateReturn ();
10500 if ( Cur_PU_Feedback )
10501 Cur_PU_Feedback->FB_lower_return_val( tree, wn_return );
10502 tree = wn_return;
10503 return tree;
10504 }
10505
10506
10507
10508
10509 static TYPE_ID get_parm_type(int rtype) {
10510
10511 if (rtype == MTYPE_I1 || rtype == MTYPE_I2) {
10512 return MTYPE_I4;
10513 }
10514 if (rtype == MTYPE_U1 || rtype == MTYPE_U2) {
10515 return MTYPE_U4;
10516 }
10517 return rtype;
10518 }
10519
10520
10521
10522
10523
10524
10525
10526
10527
10528
10529
10530
10531
10532
10533 static WN* get_TLD_call(TYPE_ID rtype, WN* param, TY_IDX ty_idx) {
10534
10535 WN* kids[1];
10536 WN* var = WN_CreateParm(rtype, param, ty_idx, WN_PARM_BY_VALUE);
10537 kids[0] = var;
10538 return WN_Create_Intrinsic(OPR_INTRINSIC_OP, TY_mtype(Make_Pointer_Type(ty_idx)), MTYPE_V, INTRN_TLD_ADDR, 1, kids);
10539 }
10540
10541 static bool TY_not_shared(TY_IDX idx) {
10542
10543 return !(TY_is_shared(idx) || idx == shared_ptr_idx || idx == pshared_ptr_idx);
10544 }
10545
10546
10547
10548
10549 static WN* lower_TLD(WN* block, WN* wn, LOWER_ACTIONS actions) {
10550
10551 if (!Action(LOWER_UPC_TO_INTR)) {
10552 return wn;
10553 }
10554
10555 ST_IDX idx = WN_st_idx(wn);
10556 ST st = St_Table[idx];
10557 TY_IDX ty_idx = ST_type(idx);
10558 TYPE_ID rtype = TY_mtype(ty_idx);
10559
10560 int sclass = ST_sclass(st);
10561 if (TY_not_shared(ty_idx) &&
10562 ST_class(st) != CLASS_CONST &&
10563 (sclass == SCLASS_PSTATIC || sclass == SCLASS_FSTATIC ||
10564 sclass == SCLASS_COMMON || sclass == SCLASS_EXTERN ||
10565 sclass == SCLASS_UGLOBAL || sclass == SCLASS_DGLOBAL)) {
10566
10567
10568
10569 TY_IDX ptr_ty = Make_Pointer_Type(ty_idx);
10570 if (WN_field_id(wn) != 0) {
10571
10572 TY_IDX fld_idx = get_field_type(ty_idx, WN_field_id(wn));
10573 ptr_ty = Make_Pointer_Type(fld_idx);
10574 rtype = TY_mtype(fld_idx);
10575 }
10576
10577 rtype = get_parm_type(rtype);
10578 WN* res;
10579 WN* ld = WN_Ldid(rtype, WN_offset(wn), idx, ty_idx, WN_field_id(wn));
10580 res = get_TLD_call(rtype, ld, ty_idx);
10581 switch (WN_operator(wn)) {
10582 case OPR_STID: {
10583 WN* val = lower_expr(block, WN_kid(wn, 0), actions);
10584
10585 return WN_CreateIstore(OPR_ISTORE, MTYPE_V, WN_rtype(val), 0, ptr_ty, val, res, 0);
10586 }
10587 case OPR_LDID:
10588
10589 return WN_CreateIload(OPR_ILOAD, rtype, rtype, 0, TY_pointed(ptr_ty), ptr_ty, res, 0);
10590 default:
10591 Is_True(0, ("Unexpected Operator in lower_TLD: %d", WN_operator(wn)));
10592 }
10593 }
10594 return wn;
10595 }
10596
10597 static WN* lower_TLD_lda(WN* block, WN* wn, LOWER_ACTIONS actions) {
10598
10599 if (!Action(LOWER_UPC_TO_INTR)) {
10600 return wn;
10601 }
10602
10603 ST_IDX idx = WN_st_idx(wn);
10604 ST st = St_Table[idx];
10605 TY_IDX ty_idx = ST_type(idx);
10606 TYPE_ID rtype = TY_mtype(ty_idx);
10607 int sclass = ST_sclass(st);
10608 if (TY_not_shared(ty_idx) &&
10609 ST_class(st) != CLASS_CONST &&
10610 (sclass == SCLASS_PSTATIC || sclass == SCLASS_FSTATIC ||
10611 sclass == SCLASS_COMMON || sclass == SCLASS_EXTERN ||
10612 sclass == SCLASS_UGLOBAL || sclass == SCLASS_DGLOBAL)) {
10613 WN* res;
10614 WN* ld = WN_Ldid(rtype, WN_offset(wn), idx, ST_type(st));
10615 res = get_TLD_call(rtype, ld, ty_idx);
10616
10617 return res;
10618 }
10619 return wn;
10620 }
10621
10622
10623
10624
10625
10626
10627
10628
10629
10630
10631
10632
10633
10634 static WN *lower_stmt(WN *block, WN *tree, LOWER_ACTIONS actions)
10635 {
10636 CURRENT_STATE stmtState = pushCurrentState(tree, actions);
10637
10638 Is_True(OPCODE_is_stmt(WN_opcode(tree)),
10639 ("expected statement node, not %s", OPCODE_name(WN_opcode(tree))));
10640 switch(WN_operator(tree))
10641 {
10642
10643 case OPR_PRAGMA:
10644 if (Action(LOWER_UPC_TO_INTR)) {
10645 switch(WN_pragma(tree)) {
10646 case WN_PRAGMA_UPC_STRICT_CONSISTENCY_START:
10647 consistency_stack.push(STRICT_CONSISTENCY);
10648 break;
10649 case WN_PRAGMA_UPC_RELAXED_CONSISTENCY_START:
10650 consistency_stack.push(RELAXED_CONSISTENCY);
10651 break;
10652 case WN_PRAGMA_UPC_STRICT_CONSISTENCY_STOP:
10653 case WN_PRAGMA_UPC_RELAXED_CONSISTENCY_STOP:
10654 consistency_stack.pop();
10655 break;
10656 }
10657 return tree;
10658 }
10659 break;
10660 case OPR_CALL:
10661 case OPR_ICALL:
10662 case OPR_PICCALL:
10663 tree = lower_call(block, tree, actions);
10664 break;
10665
10666 case OPR_INTRINSIC_CALL:
10667 tree = lower_intrinsic_call(block, tree, actions);
10668 break;
10669
10670 case OPR_ISTORE:
10671 case OPR_STID:
10672 case OPR_MSTORE: {
10673 if (WN_operator(tree) == OPR_STID) {
10674
10675
10676
10677
10678
10679 }
10680
10681 tree = lower_store(block, tree, actions);
10682 break;
10683 }
10684
10685 case OPR_COMPGOTO:
10686 tree = lower_compgoto(block, tree, actions);
10687 break;
10688
10689 case OPR_IO:
10690 if (Action(LOWER_IO_STATEMENT))
10691 {
10692 if (traceIO)
10693 {
10694 fputs(DBar, TFile);
10695 fprintf(TFile, "Io Lower: Before Lowering\n");
10696 fdump_tree(TFile, tree);
10697 fputs(DBar, TFile);
10698 }
10699
10700 tree = lower_io_statement(tree, actions);
10701
10702 if (traceIO)
10703 {
10704 fputs(DBar, TFile);
10705 fprintf(TFile, "Io Lower: After Lowering\n");
10706 fdump_tree(TFile, tree);
10707 fputs(DBar, TFile);
10708 }
10709 }
10710 break;
10711 case OPR_ALTENTRY:
10712 tree = lower_entry(tree, actions);
10713 break;
10714
10715 case OPR_EVAL:
10716 tree = lower_eval(block, tree, actions);
10717 break;
10718
10719 case OPR_LABEL:
10720
10721
10722
10723 if (WN_label_loop_info(tree))
10724 {
10725 WN *infoblock= WN_CreateBlock();
10726 WN *info= WN_label_loop_info(tree);
10727
10728 info = lower_expr(infoblock, info, actions);
10729 WN_set_label_loop_info(tree, info);
10730 }
10731 break;
10732
10733 case OPR_EXC_SCOPE_BEGIN:
10734
10735
10736
10737
10738 break;
10739
10740 case OPR_REGION_EXIT:
10741
10742
10743
10744 if (Action(LOWER_REGION_EXITS))
10745 WN_set_opcode(tree, OPC_GOTO);
10746 break;
10747
10748 case OPR_ASSERT:
10749 tree = lower_assert(block, tree, actions);
10750 break;
10751
10752 case OPR_TRUEBR:
10753 case OPR_FALSEBR:
10754 tree = lower_branch(block, tree, actions);
10755 break;
10756
10757 case OPR_RETURN_VAL:
10758 if (Action(LOWER_RETURN_VAL))
10759 tree = lower_return_val(block, tree, actions);
10760 else
10761 WN_kid0(tree) = lower_expr(block, WN_kid0(tree), actions);
10762 break;
10763
10764 case OPR_ASM_STMT:
10765 {
10766
10767 INT16 i;
10768 for (i = 2; i < WN_kid_count(tree); i++) {
10769 WN_kid0(WN_kid(tree,i)) = lower_expr(block, WN_kid0(WN_kid(tree,i)), actions);
10770 }
10771 break;
10772 }
10773
10774 default:
10775 {
10776 INT16 i;
10777 for (i = 0; i < WN_kid_count(tree); i++)
10778 WN_kid(tree,i) = lower_expr(block, WN_kid(tree,i), actions);
10779 }
10780 }
10781
10782 popCurrentState(stmtState);
10783 return tree;
10784 }
10785
10786
10787
10788
10789
10790
10791
10792
10793
10794
10795
10796
10797 static WN *replace_ldidPreg(WN *expr, PREG_NUM reg, WN *replacement)
10798 {
10799 INT16 i;
10800
10801 if (expr==NULL)
10802 return NULL;
10803
10804 for (i = 0; i < WN_kid_count(expr); i++)
10805 {
10806 WN *child= WN_kid(expr, i);
10807
10808 if ((WN_operator_is(child, OPR_LDID)) &&
10809 (WN_class(child) == CLASS_PREG) &&
10810 (WN_load_offset(child) == reg))
10811 {
10812 if (replacement)
10813 {
10814 WN_kid(expr, i) = replacement;
10815 }
10816 return child;
10817 }
10818
10819 {
10820 WN *tree;
10821 if (tree = replace_ldidPreg(child, reg, replacement))
10822 return tree;
10823 }
10824 }
10825 return NULL;
10826 }
10827
10828
10829
10830
10831
10832
10833
10834
10835
10836
10837
10838
10839
10840
10841
10842
10843
10844 static WN *lower_intrinsic_call(WN *block, WN *tree, LOWER_ACTIONS actions)
10845 {
10846 WN *next, *em, *newBlock;
10847 INTRINSIC id = (INTRINSIC) WN_intrinsic(tree);
10848 SRCPOS srcpos = WN_Get_Linenum(tree);
10849 TYPE_ID type;
10850 PREG_NUM reg1, reg2;
10851 BOOL intrinsic_lowered;
10852
10853 Is_True(OPCODE_is_stmt(WN_opcode(tree)),
10854 ("expected statement node, not %s", OPCODE_name(WN_opcode(tree))));
10855 {
10856
10857
10858
10859 INT16 i;
10860 for (i = 0; i < WN_kid_count(tree); i++)
10861 WN_kid(tree,i) = lower_expr(block, WN_kid(tree,i), actions);
10862 }
10863
10864 if (INTRN_cg_intrinsic(id))
10865 return tree;
10866
10867 if (NotAction(LOWER_INTRINSIC |
10868 LOWER_INLINE_INTRINSIC |
10869 LOWER_INL_STACK_INTRINSIC)) {
10870 return tree;
10871 }
10872 else if (NotAction(LOWER_INL_STACK_INTRINSIC)) {
10873 INTRINSIC intr = (INTRINSIC) WN_intrinsic(tree);
10874 if (intr == INTRN_U4I4SETSTACKPOINTER ||
10875 intr == INTRN_U8I8SETSTACKPOINTER ||
10876 intr == INTRN_U4READSTACKPOINTER ||
10877 intr == INTRN_U8READSTACKPOINTER ||
10878 intr == INTRN_U4I4ALLOCA ||
10879 intr == INTRN_U8I8ALLOCA) {
10880 return tree;
10881 }
10882 }
10883
10884 next = WN_next(tree);
10885 type = WN_rtype(tree);
10886 newBlock = WN_CreateBlock();
10887
10888
10889
10890
10891
10892 {
10893 TYPE_ID ty1, ty2;
10894 BOOL returnValueUnused = FALSE;
10895
10896 if (WHIRL_Return_Info_On) {
10897
10898 RETURN_INFO return_info = Get_Return_Info (MTYPE_To_TY(type),
10899 Complex_Not_Simulated);
10900
10901 if (RETURN_INFO_count(return_info) <= 2) {
10902
10903 ty1 = RETURN_INFO_mtype (return_info, 0);
10904 ty2 = RETURN_INFO_mtype (return_info, 1);
10905 reg1 = RETURN_INFO_preg (return_info, 0);
10906 reg2 = RETURN_INFO_preg (return_info, 1);
10907 }
10908
10909 else
10910 ErrMsg (EC_Unimplemented,
10911 "lower_intrinsic_call: more than 2 return registers");
10912 }
10913
10914 else {
10915 Get_Return_Mtypes(MTYPE_To_TY(type), Complex_Not_Simulated, &ty1, &ty2);
10916 Get_Return_Pregs(ty1, ty2, ®1, ®2);
10917 }
10918
10919 if (MTYPE_is_void(type))
10920 {
10921 returnValueUnused = TRUE;
10922 }
10923 if (replace_ldidPreg(next, reg1, NULL)==NULL)
10924 {
10925 returnValueUnused = TRUE;
10926 }
10927 if (returnValueUnused && INTRN_has_no_side_effects(id))
10928 {
10929 DevWarn("lower_intrinsic_call(): function %s is void or unused and has"
10930 " no_side_effects. It will be removed", get_intrinsic_name(id));
10931
10932 return newBlock;
10933 }
10934 }
10935
10936 em = lower_emulation(newBlock, tree, actions, intrinsic_lowered);
10937
10938
10939
10940
10941
10942 if ((Action(LOWER_INLINE_INTRINSIC) ||
10943 Action(LOWER_INL_STACK_INTRINSIC)) &&
10944 NotAction(LOWER_INTRINSIC) &&
10945 tree == em)
10946 {
10947 WN_Delete(newBlock);
10948 return tree;
10949 }
10950
10951 WN_Delete(tree);
10952
10953 if (OPCODE_is_call(WN_opcode(em)))
10954 {
10955 WN_Set_Linenum (em, srcpos);
10956 WN_INSERT_BlockLast(block, newBlock);
10957 return em;
10958 }
10959 else if (WN_is_block(em))
10960 {
10961 WN_INSERT_BlockLast(block, newBlock);
10962 return em;
10963 }
10964 else if (MTYPE_is_void(type))
10965 {
10966 if (OPCODE_is_stmt(WN_opcode(em)))
10967 {
10968 WN_INSERT_BlockLast(newBlock, em);
10969 }
10970 return newBlock;
10971 }
10972 else
10973 {
10974
10975
10976
10977
10978 Is_True((reg1 != 0), ("expected return value from intrinsic_call"));
10979 Is_True((reg2 == 0), ("cannot evaluate 2 regs into an expression"));
10980 Is_True((OPCODE_is_expression(WN_opcode(em))), ("expected expression"));
10981 {
10982 WN *replaced = NULL;
10983
10984
10985
10986
10987
10988
10989
10990
10991 replaced = replace_ldidPreg(next, reg1, em);
10992
10993 if (replaced)
10994 {
10995 Is_True(Types_are_compatible(WN_rtype(replaced),type),
10996 ("return reg mismatch type"));
10997 }
10998 return newBlock;
10999 }
11000 }
11001 }
11002
11003
11004
11005
11006
11007
11008
11009
11010
11011
11012
11013
11014
11015 WN *lower_block(WN *tree, LOWER_ACTIONS actions)
11016 {
11017 WN *out, *node, *next_node;
11018 CURRENT_STATE blockState;
11019
11020 Is_True(WN_opcode(tree) == OPC_BLOCK,
11021 ("expected BLOCK node, not %s", OPCODE_name(WN_opcode(tree))));
11022
11023 blockState = pushCurrentState(tree, actions);
11024
11025 out = WN_CreateBlock();
11026 WN_Set_Linenum (out, current_srcpos);
11027
11028 for (node = WN_first(tree); node; node = next_node)
11029 {
11030
11031
11032
11033
11034
11035
11036
11037
11038
11039
11040
11041
11042
11043
11044
11045
11046
11047
11048
11049 while (Action(LOWER_MP) && node &&
11050 ((((WN_opcode(node) == OPC_PRAGMA) || (WN_opcode(node) == OPC_XPRAGMA))
11051 && (WN_pragmas[WN_pragma(node)].users & PUSER_MP)) ||
11052 ((WN_opcode(node) == OPC_REGION) && WN_first(WN_region_pragmas(node)) &&
11053 ((WN_opcode(WN_first(WN_region_pragmas(node))) == OPC_PRAGMA) ||
11054 (WN_opcode(WN_first(WN_region_pragmas(node))) == OPC_XPRAGMA)) &&
11055 (WN_pragmas[WN_pragma(WN_first(WN_region_pragmas(node)))].users &
11056 PUSER_MP))))
11057 node = lower_mp(out, node, actions);
11058 if (node == NULL) break;
11059
11060
11061
11062
11063 next_node = WN_next(node);
11064 setCurrentState(node, actions);
11065
11066 if (OPCODE_is_stmt(WN_opcode(node)))
11067 {
11068 node = lower_stmt(out, node, actions);
11069 }
11070 else if (OPCODE_is_scf(WN_opcode(node)))
11071 {
11072 node = lower_scf(out, node, actions);
11073 }
11074 else
11075 {
11076 Fail_FmtAssertion("expected statement or SCF node, not %s",
11077 OPCODE_name(WN_opcode(tree)));
11078
11079 }
11080
11081 if (node == NULL)
11082 continue;
11083
11084 WN_INSERT_BlockLast(out, node);
11085
11086
11087 if ( Action(LOWER_INL_STACK_INTRINSIC) && DEBUG_Trap_Uv
11088 && WN_operator(node) == OPR_STID
11089 && WN_operator(WN_kid0(node)) == OPR_ALLOCA)
11090 {
11091 lower_trapuv_alloca (out, WN_kid0(node), actions);
11092 }
11093 }
11094
11095
11096
11097
11098
11099
11100
11101
11102
11103
11104 if (NotAction(LOWER_TOP_LEVEL_ONLY))
11105 {
11106 for (node = WN_first(out); node; node = next_node)
11107 {
11108 next_node = WN_next(node);
11109
11110 if (WN_unconditional_goto(node))
11111 {
11112 for(node = next_node; node; node = next_node)
11113 {
11114 next_node = WN_next(node);
11115
11116 if (WN_operator_is(node, OPR_LABEL))
11117 break;
11118 else if (WN_operator_is(node, OPR_ALTENTRY))
11119 break;
11120 else if (WN_operator_is(node, OPR_EXC_SCOPE_BEGIN))
11121 continue;
11122 else if (WN_operator_is(node, OPR_EXC_SCOPE_END))
11123 continue;
11124 else if (WN_operator_is(node, OPR_PRAGMA))
11125 continue;
11126 else if (WN_operator_is(node, OPR_XPRAGMA))
11127 continue;
11128 else if (WN_operator_is(node, OPR_REGION_EXIT))
11129 continue;
11130 if (OPCODE_is_stmt(WN_opcode(node)))
11131 {
11132 WN_DELETE_FromBlock(out, node);
11133 }
11134 else
11135 break;
11136 }
11137 }
11138 }
11139 }
11140
11141 WN_Delete(tree);
11142
11143 popCurrentState(blockState);
11144 return out;
11145 }
11146
11147
11148
11149
11150
11151
11152
11153
11154
11155
11156
11157 static WN *lower_speculate(WN *block, WN *tree, LOWER_ACTIONS actions)
11158 {
11159 INT32 n;
11160 BOOL speculate = TRUE;
11161
11162 if (OPT_Lower_Speculate == FALSE)
11163 return tree;
11164
11165 switch(WN_operator(tree))
11166 {
11167 case OPR_CAND:
11168 case OPR_CIOR:
11169 case OPR_CSELECT:
11170 for (n = 0; n < WN_kid_count(tree); n++)
11171 {
11172 WN_kid(tree, n) = lower_speculate(block, WN_kid(tree, n), actions);
11173 speculate &= expr_is_speculative(WN_kid(tree, n));
11174 }
11175
11176 if (speculate)
11177 {
11178 if (WN_operator_is(tree, OPR_CAND))
11179 {
11180 WN *land = WN_LAND( WN_kid0(tree), WN_kid1(tree) );
11181 WN_Delete(tree);
11182 return land;
11183 }
11184 else if (WN_operator_is(tree, OPR_CIOR))
11185 {
11186 WN *lior = WN_LIOR( WN_kid0(tree), WN_kid1(tree) );
11187 WN_Delete(tree);
11188 return lior;
11189 }
11190 else if (WN_operator_is(tree, OPR_CSELECT))
11191 {
11192 WN *select = WN_Select(WN_rtype(tree), WN_kid0(tree), WN_kid1(tree),
11193 WN_kid2(tree));
11194
11195 WN_Delete(tree);
11196 return select;
11197 }
11198 }
11199 break;
11200 }
11201
11202 return tree;
11203 }
11204
11205
11206
11207
11208
11209
11210
11211
11212
11213
11214 static WN *
11215 lower_conditional(WN *block, WN *tree, LABEL_IDX trueLabel,
11216 LABEL_IDX falseLabel, BOOL branchType,
11217 LOWER_ACTIONS actions)
11218 {
11219 WN *shortcircuit, *left_branch = NULL, *right_branch = NULL;
11220
11221 switch(WN_operator(tree))
11222 {
11223 case OPR_CAND:
11224
11225
11226
11227
11228 if (WN_operator_is(WN_kid0(tree), OPR_CAND) ||
11229 WN_operator_is(WN_kid0(tree), OPR_CIOR))
11230 {
11231 shortcircuit = WN_NewLabel();
11232
11233 lower_conditional(block, WN_kid0(tree), WN_label_number(shortcircuit),
11234 falseLabel, FALSE, actions);
11235 WN_INSERT_BlockLast(block, shortcircuit);
11236 }
11237 else
11238 {
11239 left_branch = WN_Falsebr(falseLabel, WN_kid0(tree));
11240 WN_INSERT_BlockLast(block, left_branch);
11241 }
11242
11243
11244
11245
11246 if (WN_operator_is(WN_kid1(tree), OPR_CAND) ||
11247 WN_operator_is(WN_kid1(tree), OPR_CIOR))
11248 {
11249 lower_conditional(block, WN_kid1(tree), trueLabel, falseLabel,
11250 branchType, actions);
11251 }
11252 else {
11253 if ( branchType ) {
11254 right_branch = WN_Truebr(trueLabel, WN_kid1(tree));
11255 WN_INSERT_BlockLast(block, right_branch);
11256 }
11257 else {
11258
11259 right_branch = WN_Falsebr(falseLabel, WN_kid1(tree));
11260 WN_INSERT_BlockLast(block, right_branch);
11261 }
11262 }
11263 if (Cur_PU_Feedback) {
11264 Cur_PU_Feedback->FB_lower_circuit( tree, left_branch, right_branch );
11265 }
11266 return NULL;
11267
11268 case OPR_CIOR:
11269
11270
11271
11272
11273 if (WN_operator_is(WN_kid0(tree), OPR_CAND) ||
11274 WN_operator_is(WN_kid0(tree), OPR_CIOR))
11275 {
11276 shortcircuit = WN_NewLabel();
11277
11278 lower_conditional(block, WN_kid0(tree), trueLabel,
11279 WN_label_number(shortcircuit), TRUE, actions);
11280 WN_INSERT_BlockLast(block, shortcircuit);
11281 }
11282 else
11283 {
11284 left_branch = WN_Truebr(trueLabel, WN_kid0(tree));
11285 WN_INSERT_BlockLast(block, left_branch);
11286 }
11287
11288
11289
11290
11291 if (WN_operator_is(WN_kid1(tree), OPR_CAND) ||
11292 WN_operator_is(WN_kid1(tree), OPR_CIOR))
11293 {
11294 lower_conditional(block, WN_kid1(tree), trueLabel, falseLabel,
11295 branchType, actions);
11296 }
11297 else {
11298 if ( branchType ) {
11299 right_branch = WN_Truebr(trueLabel, WN_kid1(tree));
11300 WN_INSERT_BlockLast(block, right_branch);
11301 }
11302 else {
11303
11304 right_branch = WN_Falsebr(falseLabel, WN_kid1(tree));
11305 WN_INSERT_BlockLast(block, right_branch);
11306 }
11307 }
11308 if (Cur_PU_Feedback) {
11309 Cur_PU_Feedback->FB_lower_circuit( tree, left_branch, right_branch );
11310 }
11311 return NULL;
11312
11313 default:
11314 tree = lower_expr(block, tree, actions);
11315 break;
11316 }
11317
11318 return tree;
11319 }
11320
11321 static WN *lower_branch_condition(BOOL branchType, LABEL_IDX label, WN *cond,
11322 WN **branch, LOWER_ACTIONS actions)
11323 {
11324 WN *condBlock = WN_CreateBlock();
11325
11326 cond = lower_speculate(condBlock, cond, actions);
11327
11328 *branch = NULL;
11329
11330 switch(WN_operator(cond))
11331 {
11332 case OPR_CAND:
11333 case OPR_CIOR:
11334 {
11335 LABEL_IDX shortcircuit_lbl;
11336 shortcircuit_lbl = NewLabel();
11337
11338 if (branchType == TRUE)
11339 {
11340 cond = lower_conditional(condBlock, cond, label, shortcircuit_lbl,
11341 branchType, actions);
11342 }
11343 else
11344 {
11345 cond = lower_conditional(condBlock, cond, shortcircuit_lbl, label,
11346 branchType, actions);
11347 }
11348
11349 condBlock = lower_block(condBlock, actions);
11350 WN_INSERT_BlockLast(condBlock, WN_Label(shortcircuit_lbl));
11351 }
11352 break;
11353 default:
11354 {
11355 cond = lower_expr(condBlock, cond, actions);
11356
11357 if (branchType)
11358 *branch = WN_Truebr(label, cond);
11359 else
11360 *branch = WN_Falsebr(label, cond);
11361 WN_INSERT_BlockLast(condBlock, *branch);
11362 }
11363 }
11364 return condBlock;
11365 }
11366
11367 #ifdef SHORTCIRCUIT_HACK
11368
11369
11370
11371 static BOOL tree_has_cand_cior (WN *tree)
11372 {
11373 WN_ITER *wni;
11374 WN *wn;
11375
11376 for (wni = WN_WALK_TreeIter (tree);
11377 wni != NULL;
11378 wni = WN_WALK_TreeNext (wni))
11379 {
11380 wn = WN_ITER_wn (wni);
11381
11382 if (WN_operator_is(wn, OPR_CAND) ||
11383 WN_operator_is(wn, OPR_CIOR) ||
11384 WN_operator_is(wn, OPR_CSELECT))
11385 return TRUE;
11386 }
11387 return FALSE;
11388 }
11389 #endif
11390
11391
11392
11393
11394
11395
11396
11397
11398
11399
11400
11401 static WN *lower_if(WN *block, WN *tree, LOWER_ACTIONS actions)
11402 {
11403 Is_True(WN_opcode(tree) == OPC_IF,
11404 ("expected IF node, not %s", OPCODE_name(WN_opcode(tree))));
11405
11406 if (WN_Is_If_MpVersion(tree))
11407 return lower_block(lower_mp(block, tree, actions), actions);
11408
11409 #ifndef SHORTCIRCUIT_HACK
11410 if (Action(LOWER_IF))
11411 #else
11412 if (Action(LOWER_IF) ||
11413 (Action(LOWER_SHORTCIRCUIT) && tree_has_cand_cior(WN_if_test(tree))))
11414 #endif
11415 {
11416
11417
11418
11419
11420
11421
11422 WN *body = WN_CreateBlock();
11423 WN *wn_branch = NULL;
11424 LABEL_IDX cont_lbl;
11425 cont_lbl = NewLabel();
11426
11427 if (Action(LOWER_TOP_LEVEL_ONLY))
11428 {
11429 actions = RemoveScfAction(actions);
11430 }
11431
11432 if (WN_block_nonempty(WN_then(tree)))
11433 {
11434 if (WN_block_nonempty(WN_else(tree)))
11435 {
11436
11437
11438
11439
11440
11441
11442
11443
11444
11445 LABEL_IDX else_lbl;
11446 else_lbl = NewLabel();
11447
11448 WN *falsebr_block = lower_falsebr(else_lbl, WN_if_test(tree),
11449 &wn_branch, actions);
11450 WN_INSERT_BlockFirst(body, falsebr_block);
11451
11452 setCurrentStateBlockLast(WN_then(tree), actions);
11453 WN_INSERT_BlockLast(body, lower_block(WN_then(tree), actions));
11454 WN *wn_goto = WN_Goto(cont_lbl);
11455 WN_INSERT_BlockLast(body, wn_goto);
11456
11457 WN *wn_else_lbl = WN_Label(else_lbl);
11458 WN_INSERT_BlockLast(body, wn_else_lbl);
11459 setCurrentStateBlockLast(WN_else(tree), actions);
11460 WN_INSERT_BlockLast(body, lower_block(WN_else(tree), actions));
11461 WN *wn_cont_lbl = WN_Label(cont_lbl);
11462 WN_INSERT_BlockLast(body, wn_cont_lbl);
11463 }
11464 else
11465 {
11466
11467
11468
11469
11470
11471
11472 WN *falsebr_block = lower_falsebr(cont_lbl, WN_if_test(tree),
11473 &wn_branch, actions);
11474 WN_INSERT_BlockFirst(body, falsebr_block);
11475
11476 setCurrentStateBlockLast(WN_then(tree), actions);
11477 WN_INSERT_BlockLast(body, lower_block(WN_then(tree), actions));
11478 WN *wn_cont_lbl = WN_Label(cont_lbl);
11479 WN_INSERT_BlockLast(body, wn_cont_lbl);
11480 }
11481
11482 if (Cur_PU_Feedback) {
11483 Cur_PU_Feedback->FB_lower_branch( tree, wn_branch );
11484 }
11485
11486 WN_Delete(tree);
11487 return body;
11488 }
11489 else if (WN_block_nonempty(WN_else(tree)))
11490 {
11491
11492
11493
11494
11495
11496
11497 WN *truebr_block = lower_truebr(cont_lbl, WN_if_test(tree),
11498 &wn_branch, actions);
11499 WN_INSERT_BlockFirst(body, truebr_block);
11500
11501 setCurrentStateBlockLast(WN_else(tree), actions);
11502 WN_INSERT_BlockLast(body, lower_block(WN_else(tree), actions));
11503 WN *wn_cont_lbl = WN_Label(cont_lbl);
11504 WN_INSERT_BlockLast(body, wn_cont_lbl);
11505
11506 if (Cur_PU_Feedback) {
11507 Cur_PU_Feedback->FB_lower_branch( tree, wn_branch );
11508 }
11509
11510 WN_Delete(tree);
11511 return body;
11512 }
11513 else
11514 {
11515
11516
11517
11518
11519 WN *eval;
11520
11521 eval = WN_CreateExp1(OPC_EVAL, lower_expr(block, WN_if_test(tree),
11522 actions));
11523 WN_Set_Linenum (eval, current_srcpos);
11524
11525 if (Cur_PU_Feedback) {
11526 Cur_PU_Feedback->FB_lower_branch( tree, NULL );
11527 }
11528
11529 WN_DELETE_Tree(WN_then(tree));
11530 WN_DELETE_Tree(WN_else(tree));
11531 WN_Delete(tree);
11532 return eval;
11533 }
11534 }
11535 else if (NotAction(LOWER_TOP_LEVEL_ONLY))
11536 {
11537 WN_if_test(tree) = lower_expr(block, WN_if_test(tree),
11538 RemoveShortCircuitAction(actions));
11539 WN_then(tree) = lower_block(WN_then(tree), actions);
11540 WN_else(tree) = lower_block(WN_else(tree), actions);
11541 }
11542
11543 return tree;
11544 }
11545
11546
11547
11548
11549
11550
11551
11552
11553
11554
11555
11556
11557
11558
11559 static WN *lower_do_loop(WN *block, WN *tree, LOWER_ACTIONS actions)
11560 {
11561 WN *loop_info;
11562
11563 Is_True(WN_opcode(tree) == OPC_DO_LOOP,
11564 ("expected DO_LOOP node, not %s", OPCODE_name(WN_opcode(tree))));
11565
11566 loop_info = WN_do_loop_info(tree);
11567 loop_nest_depth = loop_info ? WN_loop_depth(loop_info) : loop_nest_depth+1;
11568
11569 if (Action(LOWER_DO_LOOP))
11570 {
11571
11572
11573
11574
11575
11576
11577
11578
11579
11580
11581 BOOL nz_trip = loop_info && WN_Loop_Nz_Trip(loop_info);
11582 WN *wn_top_branch = NULL, *wn_back_branch = NULL;
11583 WN *body = WN_CreateBlock();
11584
11585 if (Action(LOWER_TOP_LEVEL_ONLY))
11586 {
11587 actions = RemoveScfAction(actions);
11588 }
11589
11590 contains_a_loop = FALSE;
11591
11592
11593
11594
11595 if (loop_info == NULL)
11596 {
11597 WN *infoblock = WN_CreateBlock();
11598 WN *trip_count = WN_LOOP_TripCount(tree);
11599
11600
11601 if (trip_count && WN_operator_is(trip_count, OPR_INTCONST) &&
11602 WN_const_val(trip_count) > 0) {
11603 nz_trip = TRUE;
11604 }
11605 loop_info = WN_CreateLoopInfo(WN_index(tree),
11606 trip_count,
11607 0,
11608 loop_nest_depth,
11609 contains_a_loop ? 0 : WN_LOOP_INNERMOST);
11610 loop_info = lower_expr(infoblock, loop_info, actions);
11611 WN_Set_Loop_Nz_Trip(loop_info);
11612 WN_DELETE_Tree(infoblock);
11613 }
11614 else if (WN_loop_induction(loop_info) != WN_index(tree))
11615 {
11616 WN_DELETE_Tree(WN_index(tree));
11617 }
11618
11619 WN_INSERT_BlockLast(body, lower_stmt(block, WN_start(tree), actions));
11620
11621 WN *cont_lbl;
11622 if (nz_trip == FALSE)
11623 {
11624 WN *end = lower_copy_tree(WN_end(tree), actions);
11625
11626 if (Cur_PU_Feedback)
11627 Cur_PU_Feedback->FB_clone_loop_test( WN_end(tree), end, tree );
11628
11629 cont_lbl = WN_NewLabel();
11630 WN *top_branch_block = lower_falsebr(WN_label_number(cont_lbl), end,
11631 &wn_top_branch, actions);
11632 WN_INSERT_BlockLast(body, top_branch_block);
11633 }
11634
11635 setCurrentState(WN_do_body(tree), actions);
11636
11637 LABEL_IDX top_lbl_idx;
11638 top_lbl_idx = NewLabel();
11639
11640 WN *top_lbl = WN_CreateLabel(ST_IDX_ZERO, top_lbl_idx, 0, loop_info);
11641 WN_INSERT_BlockLast(body, top_lbl);
11642
11643 WN_INSERT_BlockLast(body, lower_block(WN_do_body(tree), actions));
11644
11645 setCurrentState(WN_step(tree), actions);
11646 WN_INSERT_BlockLast(body, lower_stmt(block, WN_step(tree), actions));
11647 WN *back_branch_block = lower_truebr(WN_label_number(top_lbl),
11648 WN_end(tree), &wn_back_branch,
11649 actions);
11650 WN_INSERT_BlockLast(body, back_branch_block);
11651
11652 if (nz_trip == FALSE) {
11653 WN_INSERT_BlockLast(body, cont_lbl);
11654 }
11655
11656 if ( Cur_PU_Feedback )
11657 Cur_PU_Feedback->FB_lower_loop( tree, wn_top_branch, wn_back_branch );
11658
11659 WN_Delete(tree);
11660
11661 tree = body;
11662 }
11663 else if (NotAction(LOWER_TOP_LEVEL_ONLY))
11664 {
11665 WN_start(tree) = lower_stmt(block, WN_start(tree), actions);
11666 WN_end(tree) = lower_expr(block, WN_end(tree), actions);
11667 WN_step(tree) = lower_stmt(block, WN_step(tree), actions);
11668 WN_do_body(tree) = lower_block(WN_do_body(tree), actions);
11669 }
11670
11671 --loop_nest_depth;
11672 contains_a_loop = TRUE;
11673 return tree;
11674 }
11675
11676
11677
11678
11679
11680
11681
11682
11683
11684
11685
11686
11687
11688 static WN *lower_do_while(WN *block, WN *tree, LOWER_ACTIONS actions)
11689 {
11690 Is_True(WN_opcode(tree) == OPC_DO_WHILE,
11691 ("expected DO_WHILE node, not %s", OPCODE_name(WN_opcode(tree))));
11692
11693 ++loop_nest_depth;
11694 #ifndef SHORTCIRCUIT_HACK
11695 if (Action(LOWER_DO_WHILE))
11696 #else
11697 if (Action(LOWER_DO_WHILE) ||
11698 (Action(LOWER_SHORTCIRCUIT) && tree_has_cand_cior (WN_while_test(tree))))
11699 #endif
11700 {
11701
11702
11703
11704
11705
11706
11707 WN *body = WN_CreateBlock();
11708 WN *top_lbl = WN_NewLabel();
11709
11710 if (Action(LOWER_TOP_LEVEL_ONLY))
11711 {
11712 actions = RemoveScfAction(actions);
11713 }
11714 WN_INSERT_BlockFirst(body, top_lbl);
11715 WN_INSERT_BlockLast(body, lower_block(WN_while_body(tree), actions));
11716
11717 WN *wn_back_branch = NULL;
11718 WN *back_branch_block
11719 = lower_truebr(WN_label_number(top_lbl), WN_while_test(tree),
11720 &wn_back_branch, actions);
11721 WN_INSERT_BlockLast(body, back_branch_block);
11722
11723 if ( Cur_PU_Feedback )
11724 Cur_PU_Feedback->FB_lower_loop( tree, NULL, wn_back_branch );
11725
11726 WN_Delete(tree);
11727 tree = body;
11728 }
11729 else if (NotAction(LOWER_TOP_LEVEL_ONLY))
11730 {
11731 WN *testBlock = WN_CreateBlock();
11732
11733 WN_while_body(tree) = lower_block(WN_while_body(tree), actions);
11734
11735 WN_while_test(tree) = lower_expr(testBlock, WN_while_test(tree), actions);
11736
11737 WN_INSERT_BlockLast(WN_while_body(tree), testBlock);
11738 }
11739
11740 --loop_nest_depth;
11741 contains_a_loop = TRUE;
11742 return tree;
11743 }
11744
11745
11746 static map<int, int> label_map;
11747 #if defined(USING_HASH_SET)
11748 static hash_set<int> labels;
11749 #else
11750 static set<int> labels;
11751 #endif
11752
11753 static WN *lower_while_do(WN *block, WN *tree, LOWER_ACTIONS actions);
11754
11761 static WN* rename_labels(WN* wn) {
11762
11763 WN* result;
11764 switch ( WN_operator(wn) ) {
11765
11766 case OPR_BLOCK: {
11767 result = WN_CreateBlock();
11768 WN* next = WN_first(wn);
11769 while (next != NULL) {
11770 WN_INSERT_BlockLast(result, rename_labels(next));
11771 next = WN_next(next);
11772 }
11773 break;
11774 }
11775
11776 case OPR_DO_WHILE:
11777 result = WN_CreateDoWhile(WN_COPY_Tree(WN_while_test(wn)), rename_labels(WN_while_body(wn)));
11778 break;
11779
11780 case OPR_WHILE_DO:
11781 result = WN_CreateWhileDo(WN_COPY_Tree(WN_while_test(wn)), rename_labels(WN_while_body(wn)));
11782 break;
11783
11784 case OPR_IF:
11785 result = WN_CreateIf(WN_COPY_Tree(WN_if_test(wn)), rename_labels(WN_then(wn)), rename_labels(WN_else(wn)));
11786 break;
11787
11788 case OPR_CASEGOTO:
11789 case OPR_TRUEBR:
11790 case OPR_FALSEBR:
11791 case OPR_GOTO:
11792 case OPR_LABEL: {
11793 result = WN_COPY_Tree(wn);
11794 int label = WN_label_number(wn);
11795 if (WN_operator(wn) == OPR_GOTO) {
11796
11797 if (labels.find(label) == labels.end()) {
11798
11799 break;
11800
11801 }
11802 }
11803
11804 if (label_map[label] == 0) {
11805 LABEL_IDX new_label;
11806 LABEL_Init (New_LABEL (CURRENT_SYMTAB, new_label), 0, LKIND_DEFAULT);
11807 label_map[label] = new_label;
11808 }
11809
11810 WN_label_number(result) = label_map[label];
11811 break;
11812 }
11813
11814 case OPR_SWITCH:
11815 result = WN_COPY_Tree(wn);
11816 for (int i = 0; i < WN_kid_count(result); i++) {
11817 WN_kid(result, i) = rename_labels(WN_kid(result, i));
11818 }
11819 break;
11820
11821 default:
11822 result = WN_COPY_Tree(wn);
11823 }
11824
11825 return result;
11826 }
11827
11832 static void find_labels(WN* wn) {
11833
11834 switch ( WN_operator(wn) ) {
11835
11836 case OPR_BLOCK: {
11837 WN* next = WN_first(wn);
11838 while (next != NULL) {
11839 find_labels(next);
11840 next = WN_next(next);
11841 }
11842 break;
11843 }
11844
11845 case OPR_DO_WHILE:
11846 find_labels(WN_while_body(wn));
11847 break;
11848
11849 case OPR_WHILE_DO:
11850 find_labels(WN_while_body(wn));
11851 break;
11852
11853 case OPR_IF:
11854 find_labels(WN_then(wn));
11855 find_labels(WN_else(wn));
11856 break;
11857
11858 case OPR_SWITCH:
11859 for (int i = 0; i < WN_kid_count(wn); i++) {
11860 find_labels(WN_kid(wn, i));
11861 }
11862 break;
11863
11864 case OPR_LABEL:
11865 labels.insert(WN_label_number(wn));
11866 break;
11867 default:
11868 break;
11869 }
11870 }
11871
11906 static WN* lower_forall_ctrl(WN* block, WN* tree, WN* prag, LOWER_ACTIONS actions) {
11907
11908
11909 label_map.clear();
11910 labels.clear();
11911
11912 WN* test = WN_while_test(tree);
11913
11914
11915
11916 WN* aff_body = WN_prev(prag);
11917 Is_True(WN_opcode(aff_body) == OPC_IF,
11918 ("expected IF node for affinity test, not %s", OPCODE_name(WN_opcode(tree))));
11919 WN* loop_body = WN_then(aff_body);
11920 WN* label = WN_next(WN_next(aff_body));
11921 WN* incr = WN_next(label);
11922
11923 WN* if_expr = WN_Ldid(MTYPE_I4, 0, upc_forall_control_st, ST_type(upc_forall_control_st));
11924
11925
11926 find_labels(tree);
11927 loop_body = rename_labels(loop_body);
11928
11929 label = WN_COPY_Tree(label);
11930 int label_num = WN_label_number(label);
11931 if (label_map[label_num] == 0) {
11932 LABEL_IDX new_label;
11933 LABEL_Init (New_LABEL (CURRENT_SYMTAB, new_label), 0, LKIND_DEFAULT);
11934 label_map[label_num] = new_label;
11935 }
11936
11937 WN_label_number(label) = label_map[label_num];
11938
11939 WN_INSERT_BlockLast(loop_body, label);
11940 for (; incr != NULL; incr = WN_next(incr)) {
11941 WN_INSERT_BlockLast(loop_body, WN_COPY_Tree(incr));
11942 }
11943
11944 WN* new_loop = WN_CreateWhileDo(WN_COPY_Tree(test), loop_body);
11945 new_loop = lower_while_do(block, new_loop, actions);
11946 WN* then_body = WN_CreateBlock();
11947 WN_INSERT_BlockLast(then_body, new_loop);
11948
11949 WN* else_body = WN_CreateBlock();
11950 WN* control_val = WN_CreateIntconst(OPR_INTCONST, MTYPE_I4, MTYPE_V, 1);
11951 WN* set_control = WN_Stid(MTYPE_I4, 0, upc_forall_control_st, TY_align(ST_type(upc_forall_control_st)), control_val);
11952 WN_INSERT_BlockLast(else_body, set_control);
11953 WN_INSERT_BlockLast(else_body, tree);
11954 control_val = WN_CreateIntconst(OPR_INTCONST, MTYPE_I4, MTYPE_V, 0);
11955 set_control = WN_Stid(MTYPE_I4, 0, upc_forall_control_st, TY_align(ST_type(upc_forall_control_st)), control_val);
11956 WN_INSERT_BlockLast(else_body, set_control);
11957
11958 return WN_CreateIf(if_expr, then_body, else_body);
11959
11960 }
11961
11962
11963
11964
11965
11966
11967
11968
11969
11970
11971
11972
11973
11974
11975
11976
11977
11978
11979
11980
11981 static WN *lower_while_do(WN *block, WN *tree, LOWER_ACTIONS actions)
11982 {
11983 Is_True(WN_opcode(tree) == OPC_WHILE_DO,
11984 ("expected WHILE_DO node, not %s", OPCODE_name(WN_opcode(tree))));
11985
11986 ++loop_nest_depth;
11987
11988
11989 if (Action(LOWER_UPC_FORALL)) {
11990 WN* body = WN_while_body(tree);
11991 for (WN* prag = WN_last(body); prag != NULL; prag = WN_prev(prag)) {
11992 if (WN_opcode(prag) == OPC_PRAGMA &&
11993 WN_pragma(prag) == WN_PRAGMA_UPC_FORALL_AFFINITY) {
11994 tree = lower_forall_ctrl(block, tree, prag, actions);
11995 break;
11996 }
11997 }
11998 }
11999
12000 #ifndef SHORTCIRCUIT_HACK
12001 if (Action(LOWER_WHILE_DO))
12002 #else
12003 if (Action(LOWER_WHILE_DO) ||
12004 (Action(LOWER_SHORTCIRCUIT) && tree_has_cand_cior (WN_while_test(tree))))
12005 #endif
12006 {
12007
12008
12009
12010
12011
12012
12013
12014 LABEL_IDX top_lbl, cont_lbl;
12015 top_lbl = NewLabel();
12016 cont_lbl = NewLabel();
12017
12018 WN *test = lower_copy_tree( WN_while_test(tree), actions);
12019 WN *body = WN_CreateBlock();
12020 if (Cur_PU_Feedback)
12021 Cur_PU_Feedback->FB_clone_loop_test( WN_while_test(tree), test, tree );
12022
12023 if (Action(LOWER_TOP_LEVEL_ONLY))
12024 {
12025 actions = RemoveScfAction(actions);
12026 }
12027
12028 WN *wn_top_branch = NULL;
12029 WN *top_branch_block = lower_falsebr(cont_lbl, test, &wn_top_branch,
12030 actions);
12031 WN_INSERT_BlockLast(block, top_branch_block);
12032
12033 setCurrentState(WN_while_body(tree), actions);
12034 WN *wn_top_lbl = WN_Label(top_lbl);
12035 WN_INSERT_BlockLast(body, wn_top_lbl);
12036
12037 setCurrentStateBlockLast(WN_while_body(tree), actions);
12038 WN_INSERT_BlockLast(body, lower_block(WN_while_body(tree), actions));
12039
12040 WN *wn_back_branch = NULL;
12041 WN *back_branch_block = lower_truebr(top_lbl, WN_while_test(tree),
12042 &wn_back_branch, actions);
12043 WN_INSERT_BlockLast(body, back_branch_block);
12044 WN *wn_cont_lbl = WN_Label(cont_lbl);
12045 WN_INSERT_BlockLast(body, wn_cont_lbl);
12046
12047 if ( Cur_PU_Feedback )
12048 Cur_PU_Feedback->FB_lower_loop( tree, wn_top_branch, wn_back_branch );
12049
12050 WN_Delete(tree);
12051
12052 tree = body;
12053 }
12054
12055
12056
12057
12058
12059
12060 else if (NotAction(LOWER_TOP_LEVEL_ONLY))
12061 {
12062 WN *copytestBlock;
12063 WN *testBlock = WN_CreateBlock();
12064
12065 WN_while_body(tree) = lower_block(WN_while_body(tree), actions);
12066
12067 WN_while_test(tree) = lower_expr(testBlock, WN_while_test(tree), actions);
12068 copytestBlock = lower_copy_tree(testBlock, actions);
12069
12070 if (Cur_PU_Feedback)
12071 Cur_PU_Feedback->FB_clone_loop_test( testBlock, copytestBlock, tree );
12072
12073 WN_INSERT_BlockLast(block, copytestBlock);
12074 WN_INSERT_BlockLast(WN_while_body(tree), testBlock);
12075 }
12076
12077 --loop_nest_depth;
12078 contains_a_loop = TRUE;
12079 return tree;
12080 }
12081
12082
12083
12084
12085
12086
12087
12088
12089
12090
12091
12092
12093
12094 static WN *lower_promoted_formal(PLOC ploc, ST *formalST)
12095 {
12096 WN *ldid, *cvt;
12097 TYPE_ID regType, formalType;
12098
12099 formalType = TY_mtype(Ty_Table[ST_type(formalST)]);
12100
12101 regType = Mtype_comparison(TY_mtype(Promoted_Parm_Type(formalST)));
12102
12103 if (!PLOC_on_stack(ploc))
12104 {
12105 formalST = MTYPE_To_PREG(regType);
12106 }
12107
12108 ldid = WN_Ldid(regType, PLOC_reg(ploc), formalST, ST_type(formalST));
12109
12110 cvt = WN_Type_Conversion(ldid, formalType);
12111
12112 return cvt;
12113 }
12114
12115
12116
12117
12118
12119
12120
12121
12122
12123 static void lower_formals(WN *block, WN *formal, PLOC ploc,
12124 LOWER_ACTIONS actions)
12125 {
12126 BOOL altentry = PU_has_altentry(Get_Current_PU());
12127 ST *sym = WN_st(formal);
12128 TY_IDX formalTY = WN_type(formal);
12129
12130 if (PLOC_on_stack(ploc))
12131 {
12132
12133 if (altentry)
12134 {
12135 ST *upformal;
12136 WN *ldid, *stid;
12137
12138 upformal = Get_Altentry_UpFormal_Symbol (sym, ploc);
12139
12140 ldid = WN_Ldid(TY_mtype(Ty_Table[formalTY]), 0, upformal, formalTY);
12141
12142 stid = WN_Stid(TY_mtype(Ty_Table[formalTY]), 0, sym, formalTY, ldid);
12143
12144 stid = lower_store(block, stid, actions);
12145 WN_Set_Linenum (stid, current_srcpos);
12146 WN_INSERT_BlockLast(block, stid);
12147 }
12148 else if (ST_promote_parm(sym))
12149 {
12150 if (MTYPE_is_float(TY_mtype(Ty_Table[formalTY])))
12151 {
12152 WN *cvt;
12153 WN *stid;
12154
12155 cvt = lower_promoted_formal(ploc, sym);
12156 stid = WN_Stid(TY_mtype(Ty_Table[formalTY]), 0, sym,
12157 formalTY, cvt);
12158
12159 WN_Set_Linenum (stid, current_srcpos);
12160 WN_INSERT_BlockLast(block, stid);
12161 }
12162 }
12163 }
12164 else if (MTYPE_is_m(TY_mtype(Ty_Table[formalTY])))
12165 {
12166
12167 lower_mload_formal (block, formal, ploc, actions);
12168 }
12169 else
12170 {
12171 WN *cvt, *stid;
12172
12173 cvt = lower_promoted_formal(ploc, sym);
12174
12175 stid = WN_Stid(TY_mtype(Ty_Table[formalTY]), 0, sym, formalTY, cvt);
12176
12177 WN_Set_Linenum (stid, current_srcpos);
12178 WN_INSERT_BlockLast(block, stid);
12179 }
12180 }
12181
12182
12183
12184
12185
12186
12187
12188
12189
12190
12191
12192
12193
12194
12195
12196
12197 static PLOC lower_entry_formals(WN *block, WN *tree, LOWER_ACTIONS actions)
12198 {
12199 PLOC ploc;
12200 INT32 i, n;
12201
12202 ploc = Setup_Input_Parameter_Locations(ST_pu_type(WN_st(tree)));
12203
12204 if (WN_opcode(tree) == OPC_ALTENTRY)
12205 {
12206 n = WN_kid_count(tree);
12207 Reset_UPFORMAL_Segment();
12208 }
12209 else
12210 {
12211 n = WN_num_formals(tree);
12212 }
12213
12214 for (i = 0; i < n; i++)
12215 {
12216 WN *formal = WN_formal(tree, i);
12217
12218 if (WN_sclass(formal) == SCLASS_FORMAL_REF)
12219 {
12220 ST *base;
12221
12222 base = Get_ST_formal_ref_base(WN_st(formal));
12223 ploc = Get_Input_Parameter_Location(ST_type(base));
12224
12225 if (NotAction(LOWER_ENTRY_FORMAL_REF))
12226 {
12227 continue;
12228 }
12229 else
12230 {
12231 formal = WN_CreateIdname(WN_idname_offset(formal), base);
12232 }
12233 }
12234 else
12235 {
12236 ploc = Get_Input_Parameter_Location(WN_type(formal));
12237
12238 if (NotAction(LOWER_ENTRY_EXIT))
12239 {
12240 continue;
12241 }
12242 }
12243 lower_formals(block, formal, ploc, actions);
12244 }
12245
12246 return ploc;
12247 }
12248
12249 static WN *
12250 Create_Mcount_Call (void)
12251 {
12252
12253
12254
12255 return NULL;
12256 }
12257
12258
12259
12260
12261
12262
12263
12264
12265
12266
12267
12268
12269
12270
12271
12272
12273
12274
12275
12276
12277
12278
12279 static WN *lower_entry(WN *tree, LOWER_ACTIONS actions)
12280 {
12281 PLOC ploc;
12282 WN *block;
12283
12284 Is_True(((WN_opcode(tree) == OPC_FUNC_ENTRY)
12285 || (WN_opcode(tree) == OPC_ALTENTRY)),
12286 ("expected ENTRY/ALTENTRY node, not %s",
12287 OPCODE_name(WN_opcode(tree))));
12288
12289 if (WHIRL_Return_Val_On && Action(LOWER_RETURN_VAL) &&
12290 WN_operator(tree) == OPR_FUNC_ENTRY)
12291 {
12292 ST_IDX func_stidx = WN_st_idx(tree);
12293 PU_IDX puidx = ST_pu(St_Table[func_stidx]);
12294 TY_IDX prototype = PU_prototype(Pu_Table[puidx]);
12295 RETURN_INFO return_info = Get_Return_Info(TY_ret_type(prototype),
12296 Complex_Not_Simulated);
12297 if (RETURN_INFO_return_via_first_arg(return_info)) {
12298 ST *return_st = Gen_Temp_Symbol(
12299 Make_Pointer_Type(TY_ret_type(prototype), FALSE),
12300 Index_To_Str(Save_Str2(".return.",
12301 ST_name(func_stidx))));
12302 Set_ST_sclass(return_st, SCLASS_FORMAL);
12303 Set_ST_is_value_parm(return_st);
12304 WN *idname = WN_CreateIdname(0, return_st);
12305
12306 WN *n_tree = WN_CreateEntry(WN_num_formals(tree)+1, func_stidx,
12307 WN_func_body(tree), WN_func_pragmas(tree),
12308 WN_func_varrefs(tree));
12309 WN_Set_Linenum(n_tree, WN_Get_Linenum(tree));
12310 WN_map_id(n_tree) = WN_map_id(tree);
12311 WN_kid0(n_tree) = idname;
12312 for (INT32 i = 0; i < WN_kid_count(tree); i++)
12313 WN_kid(n_tree, i+1) = WN_kid(tree, i);
12314
12315 if (RID_map != WN_MAP_UNDEFINED) {
12316 RID *rid = (RID *)WN_MAP_Get(RID_map, tree);
12317 if (RID_rwn(rid) == tree)
12318 RID_rwn(rid) = n_tree;
12319 }
12320 WN_Delete(tree);
12321 tree = n_tree;
12322 }
12323 }
12324
12325 setCurrentState(tree, actions);
12326 block = WN_CreateBlock();
12327
12328 if (Action(LOWER_ENTRY_EXIT))
12329 {
12330 ploc = lower_entry_formals(block, tree, actions);
12331
12332 if (TY_is_varargs(Ty_Table[PU_prototype(Pu_Table[ST_pu(WN_st(tree))])]))
12333 {
12334
12335
12336
12337
12338 TYPE_ID type = Def_Int_Mtype;
12339
12340 if (PLOC_is_nonempty(ploc) && !PLOC_on_stack(ploc)) {
12341
12342 ploc = Get_Vararg_Input_Parameter_Location (ploc);
12343 }
12344
12345 while (!PLOC_on_stack(ploc))
12346 {
12347
12348
12349
12350 WN *wn;
12351 ST *st;
12352
12353 wn = WN_Ldid (type, PLOC_reg(ploc), Int_Preg, ST_type(Int_Preg));
12354
12355
12356
12357 st = Get_Vararg_Symbol (ploc);
12358
12359 wn = WN_Stid (type, 0, st, ST_type(st), wn);
12360 WN_Set_Linenum (wn, current_srcpos);
12361 WN_INSERT_BlockLast(block, wn);
12362
12363 ploc = Get_Vararg_Input_Parameter_Location (ploc);
12364 }
12365 }
12366
12367
12368
12369
12370 {
12371 WN *trapuvBlock = WN_CreateBlock();
12372
12373 trapuvBlock = lower_trapuv(trapuvBlock, tree, actions);
12374
12375 trapuvBlock= lower_block(trapuvBlock, actions);
12376
12377 WN_INSERT_BlockLast(block, trapuvBlock);
12378 }
12379 }
12380 else if (Action(LOWER_ENTRY_FORMAL_REF))
12381 {
12382 ploc = lower_entry_formals(block, tree, actions);
12383 }
12384
12385 if (Action(LOWER_SPLIT_SYM_ADDRS))
12386 {
12387
12388
12389
12390 ST *slink = Find_Slink_Symbol(CURRENT_SYMTAB);
12391 if (slink)
12392 {
12393 WN *ld, *wn;
12394
12395 ld = WN_LdidPreg(Pointer_type, Static_Link_Preg_Offset);
12396
12397 wn = WN_Stid (Pointer_type, 0, slink, ST_type(slink), ld);
12398
12399 WN_Set_Linenum (wn, current_srcpos);
12400 WN_INSERT_BlockFirst(block, wn);
12401 }
12402 }
12403
12404 if (WN_opcode(tree) == OPC_FUNC_ENTRY)
12405 {
12406
12407 if (WN_func_pragmas(tree) && Action(LOWER_MP)) {
12408 WN *wn;
12409 for (wn = WN_first(WN_func_pragmas(tree)); wn; wn = WN_next(wn)) {
12410 if (((WN_opcode(wn) == OPC_PRAGMA) || (WN_opcode(wn) == OPC_XPRAGMA))
12411 && (WN_pragmas[WN_pragma(wn)].users & PUSER_MP)) {
12412 (void) lower_mp(NULL, wn, actions);
12413 }
12414 }
12415 }
12416
12417 if (Call_Mcount && Action(LOWER_ENTRY_EXIT)) {
12418 WN *profcall = Create_Mcount_Call ();
12419 if (profcall) {
12420 WN_Set_Linenum (profcall, current_srcpos);
12421 WN_INSERT_BlockLast(block, profcall);
12422 }
12423 }
12424
12425 WN_INSERT_BlockFirst(WN_func_body(tree), block);
12426
12427
12428 WN_func_body(tree) = lower_block(WN_func_body(tree), actions);
12429 return tree;
12430 }
12431 else
12432 {
12433 block = lower_block(block, actions);
12434 WN_INSERT_BlockFirst(block, tree);
12435 }
12436 return block;
12437 }
12438
12439
12440
12441
12442
12443
12444
12445
12446
12447
12448
12449
12450
12451 static WN *lower_region(WN *tree, LOWER_ACTIONS actions)
12452 {
12453 Is_True(WN_opcode(WN_region_body(tree)) == OPC_BLOCK,
12454 ("kid of REGION should be OPC_BLOCK, not %s",
12455 OPCODE_name(WN_opcode(WN_region_body(tree)))));
12456
12457 setCurrentState(tree, actions);
12458 if (current_function == NULL) {
12459
12460 current_function = PU_Info_tree_ptr(Current_PU_Info);
12461 }
12462
12463 if (Action(LOWER_REGION))
12464 {
12465 RID *rid = REGION_get_rid( tree );
12466
12467 Is_True(rid, ("expected valid region id"));
12468
12469 max_region++;
12470
12471
12472
12473
12474
12475 if (RID_lowered(rid) == (LOWER_ACTIONS) NULL)
12476 {
12477 RID_lowered(rid) = actions;
12478 }
12479 else
12480 {
12481 actions ^= (RID_lowered(rid) & (LOWER_CALL | LOWER_ENTRY_EXIT));
12482 }
12483
12484 if (actions)
12485 {
12486 WN_region_body(tree) = lower_block(WN_region_body(tree),
12487 actions | LOWER_REGION);
12488 }
12489 }
12490 else
12491 {
12492 WN_region_body(tree) = lower_block(WN_region_body(tree), actions);
12493 }
12494
12495 return tree;
12496 }
12497
12498 WN *lower_scf_non_recursive(WN *block, WN *tree, LOWER_ACTIONS actions)
12499 {
12500 return lower_scf(block,tree,actions | LOWER_TOP_LEVEL_ONLY);
12501 }
12502
12503
12504
12505
12506
12507
12508
12509
12510
12511
12512
12513 static WN *lower_scf(WN *block, WN *tree, LOWER_ACTIONS actions)
12514 {
12515 CURRENT_STATE scfState = pushCurrentState(tree, actions);
12516
12517 switch (WN_opcode(tree))
12518 {
12519 case OPC_DO_WHILE:
12520 block = lower_do_while(block, tree, actions);
12521 break;
12522
12523 case OPC_WHILE_DO:
12524 block = lower_while_do(block, tree, actions);
12525 break;
12526
12527 case OPC_DO_LOOP:
12528 block = lower_do_loop(block, tree, actions);
12529 break;
12530
12531 case OPC_IF:
12532 block = lower_if(block, tree, actions);
12533 break;
12534
12535 case OPC_BLOCK:
12536 block = lower_block(tree, actions);
12537 break;
12538
12539 case OPC_REGION:
12540 block = lower_region(tree, actions);
12541 break;
12542 }
12543
12544 popCurrentState(scfState);
12545 return block;
12546 }
12547
12548
12549
12550
12551
12552
12553
12554
12555
12556
12557 static WN *lower_trapuv(WN *block, WN *tree, LOWER_ACTIONS actions)
12558 {
12559 if ( DEBUG_Trap_Uv == FALSE)
12560 return block;
12561
12562 {
12563 ST *st;
12564 ST *slink = Find_Slink_Symbol(CURRENT_SYMTAB);
12565
12566 INT32 i;
12567 FOREACH_SYMBOL(CURRENT_SYMTAB, st, i)
12568 {
12569 TY_IDX type;
12570 TYPE_ID btype;
12571 INT32 size;
12572
12573 if (ST_class(st) != CLASS_VAR)
12574 continue;
12575
12576 if (ST_sclass(st) != SCLASS_AUTO)
12577 continue;
12578
12579 if (Has_Base_Block(st))
12580 continue;
12581
12582 if (ST_is_uplevelTemp(st) || st == slink)
12583 continue;
12584
12585 if (ST_is_not_used(st))
12586 continue;
12587 if (Is_Allocated(st))
12588 continue;
12589
12590 type = ST_type(st);
12591 btype = TY_mtype(Ty_Table[type]);
12592 size = TY_size(type);
12593
12594 Is_True(ST_pu_defined(st), ("trapuv auto or temp not ST_pu_defined"));
12595
12596 switch(TY_kind(type))
12597 {
12598 case KIND_SCALAR:
12599 case KIND_POINTER:
12600 case KIND_FUNCTION:
12601 {
12602 WN *con, *stid;
12603
12604 Is_True((MTYPE_RegisterSize(btype) == size),
12605 ("bad size for scalar/pointer"));;
12606
12607 con = WN_UVConst(btype);
12608
12609 stid = WN_Stid(btype, 0, st, type, con);
12610 WN_Set_Linenum(stid, WN_Get_Linenum(tree));
12611 WN_INSERT_BlockLast(block, stid);
12612 }
12613 break;
12614
12615 case KIND_ARRAY:
12616 case KIND_STRUCT:
12617 {
12618
12619
12620
12621
12622
12623
12624
12625
12626
12627
12628
12629
12630
12631
12632
12633
12634
12635
12636
12637
12638
12639 TY_IDX ptype = Make_Pointer_Type(type);
12640 WN *conUV4 = NULL;
12641 INT32 todo = size;
12642 INT32 offset = 0;
12643 UINT32 ncon;
12644 TYPE_ID q;
12645
12646 for (q= Max_Uint_Mtype; q!=MTYPE_UNKNOWN; q= Mtype_prev_alignment(q))
12647 {
12648 WN *con, *lda, *num, *store;
12649 INT32 qSize = MTYPE_RegisterSize(q);
12650 INT32 qBits = MTYPE_size_reg(q);
12651 INT32 nMoves = todo / qSize;
12652 INT32 residue = todo % qSize;
12653
12654 if (q >= MTYPE_U4)
12655 {
12656 if (nMoves)
12657 {
12658 con = WN_UVConst(q);
12659
12660 if ( DEBUG_Trap_Uv_Rjustify )
12661 {
12662 con = WN_RotateIntconst(con, residue*8);
12663 }
12664
12665 lda = WN_Lda(Pointer_type, 0, st);
12666 num = WN_Intconst(MTYPE_I4, nMoves * qSize);
12667
12668 store = WN_CreateMstore(offset, ptype, con, lda, num);
12669
12670 WN_Set_Linenum(store, WN_Get_Linenum(tree));
12671 WN_INSERT_BlockLast(block, store);
12672
12673 todo -= (nMoves * qSize);
12674 offset += (nMoves * qSize);
12675 }
12676 }
12677 else
12678 {
12679
12680
12681
12682 if (todo > 0)
12683 {
12684 if (conUV4==NULL)
12685 {
12686 conUV4 = WN_UVConst(MTYPE_U4);
12687 ncon = WN_const_val(conUV4);
12688 }
12689 if (nMoves)
12690 {
12691 if ( DEBUG_Trap_Uv_Rjustify )
12692 {
12693 con = WN_Intconst(MTYPE_U4, ncon>>(todo*8 - qBits));
12694 }
12695 else
12696 {
12697 con = WN_Intconst(MTYPE_U4,
12698 ncon>>(MTYPE_size_reg(MTYPE_U4)-qBits));
12699 ncon <<= qBits;
12700 }
12701
12702 store = WN_Stid(q, offset, st, type, con);
12703 WN_Set_Linenum(store, WN_Get_Linenum(tree));
12704 WN_INSERT_BlockLast(block, store);
12705
12706 todo -= (nMoves * qSize);
12707 offset += (nMoves * qSize);
12708 }
12709 }
12710 }
12711 }
12712 if (conUV4)
12713 WN_Delete(conUV4);
12714
12715 }
12716 break;
12717 }
12718 }
12719 }
12720 return block;
12721 }
12722
12723
12724 static void lower_actions_fprintf(FILE *f, LOWER_ACTIONS actions)
12725 {
12726 LOWER_ACTIONS i = 1;
12727
12728 while (actions)
12729 {
12730 if (Action(i))
12731 {
12732 fprintf(f, "%s ", LOWER_ACTIONS_name(i));
12733 actions = actions ^ i;
12734 }
12735 i <<= 1;
12736 }
12737 fprintf(f, "\n");
12738 }
12739
12740
12741
12742
12743
12744
12745
12746
12747
12748 const char * LOWER_ACTIONS_name(LOWER_ACTIONS actions)
12749 {
12750 if ((actions-1) & actions)
12751 {
12752 DevWarn("LOWER_ACTION_name(0x%llx): expected only one flag at a time",
12753 actions);
12754 }
12755
12756 switch(actions)
12757 {
12758 case LOWER_NULL: return "LOWER_NULL";
12759 case LOWER_DO_LOOP: return "LOWER_DO_LOOP";
12760 case LOWER_DO_WHILE: return "LOWER_DO_WHILE";
12761 case LOWER_WHILE_DO: return "LOWER_WHILE_DO";
12762 case LOWER_IF: return "LOWER_IF";
12763 case LOWER_COMPLEX: return "LOWER_COMPLEX";
12764 case LOWER_ARRAY: return "LOWER_ARRAY";
12765 case LOWER_SPLIT_CONST_OFFSETS: return "LOWER_SPLIT_CONST_OFFSETS";
12766 case LOWER_ENTRY_EXIT: return "LOWER_ENTRY_EXIT";
12767 case LOWER_CALL: return "LOWER_CALL";
12768 case LOWER_SPLIT_SYM_ADDRS: return "LOWER_SPLIT_SYM_ADDRS";
12769 case LOWER_IO_STATEMENT: return "LOWER_IO_STATEMENT";
12770 case LOWER_MSTORE: return "LOWER_MSTORE";
12771 case LOWER_CVT: return "LOWER_CVT";
12772 case LOWER_MP: return "LOWER_MP";
12773 case LOWER_8X_ARRAY: return "LOWER_8X_ARRAY";
12774 case LOWER_INTRINSIC: return "LOWER_INTRINSIC";
12775 case LOWER_INLINE_INTRINSIC: return "LOWER_INLINE_INTRINSIC";
12776 case LOWER_INL_STACK_INTRINSIC: return "LOWER_INL_STACK_INTRINSIC";
12777 case LOWER_REGION: return "LOWER_REGION";
12778 case LOWER_QUAD: return "LOWER_QUAD";
12779 case LOWER_COMPGOTO: return "LOWER_COMPGOTO";
12780 case LOWER_MADD: return "LOWER_MADD";
12781 case LOWER_TOP_LEVEL_ONLY: return "LOWER_TOP_LEVEL_ONLY";
12782 case LOWER_PREFETCH_MAPS: return "LOWER_PREFETCH_MAPS";
12783 case LOWER_ALIAS_MAPS: return "LOWER_ALIAS_MAPS";
12784 case LOWER_DEPGRAPH_MAPS: return "LOWER_DEPGRAPH_MAPS";
12785 case LOWER_PARITY_MAPS: return "LOWER_PARITY_MAPS";
12786
12787 case LOWER_FREQUENCY_MAPS: return "LOWER_FREQUENCY_MAPS";
12788 case LOWER_PICCALL: return "LOWER_PICCALL";
12789 case LOWER_BASE_INDEX: return "LOWER_BASE_INDEX";
12790 case LOWER_TO_CG: return "LOWER_TO_CG";
12791 case LOWER_ASSERT: return "LOWER_ASSERT";
12792 case LOWER_FORMAL_REF: return "LOWER_FORMAL_REF";
12793 case LOWER_UPLEVEL: return "LOWER_UPLEVEL";
12794 case LOWER_ENTRY_FORMAL_REF: return "LOWER_ENTRY_FORMAL_REF";
12795 case LOWER_SHORTCIRCUIT: return "LOWER_SHORTCIRCUIT";
12796 case LOWER_TREEHEIGHT: return "LOWER_TREEHEIGHT";
12797 case LOWER_RETURN_VAL: return "LOWER_RETURN_VAL";
12798 case LOWER_MLDID_MSTID: return "LOWER_MLDID_MSTID";
12799 case LOWER_BIT_FIELD_ID: return "LOWER_BIT_FIELD_ID";
12800 case LOWER_BITS_OP: return "LOWER_BITS_OP";
12801 default: return "<unrecognized>";
12802 }
12803 }
12804
12805 static const char * MSTORE_ACTIONS_name(MSTORE_ACTIONS actions)
12806 {
12807 switch(actions)
12808 {
12809 case MSTORE_aggregate: return "scalar moves ";
12810 case MSTORE_loop: return "generate loop ";
12811 case MSTORE_intrinsic_bzero: return "intrinsic bzero ";
12812 case MSTORE_intrinsic_memset: return "intrinsic memset";
12813 case MSTORE_intrinsic_bcopy: return "intrinsic bcopy";
12814 default: return "<unrecognized>";
12815 }
12816 }
12817
12818
12819 void WN_Lower_Checkdump(char *msg, WN *tree, LOWER_ACTIONS actions)
12820 {
12821 traceAlignment = Get_Trace(TP_LOWER, 0x004);
12822 traceSplitSymOff = Get_Trace(TP_LOWER, 0x010);
12823 traceIO = Get_Trace(TP_LOWER, 0x020);
12824 traceSpeculate = Get_Trace(TP_LOWER, 0x040);
12825 traceTreeHeight = Get_Trace(TP_LOWER, 0x080);
12826 traceMload = Get_Trace(TP_LOWER, 0x100);
12827
12828
12829 if (Get_Trace(TP_LOWER, 0x008))
12830 {
12831 enable_tree_freq_display();
12832 }
12833
12834 if (Get_Trace(TKIND_IR, TP_LOWER))
12835 {
12836 fputs(DBar, TFile);
12837 fprintf(TFile, "WN_Lower: \"%s\"\n", msg);
12838 if (actions)
12839 {
12840 fprintf(TFile, "flags are:\n");
12841 lower_actions_fprintf(TFile, actions);
12842 }
12843 fdump_tree(TFile, tree);
12844 fputs(DBar, TFile);
12845 }
12846
12847 if (Get_Trace(TP_LOWER, 0x001))
12848 {
12849 IR_dump_map_info = TRUE;
12850
12851 fprintf(TFile, "WN_Lower: LNO DEP GRAPH\n");
12852 LNOPrintDepGraph(TFile);
12853 }
12854 if (Get_Trace(TP_LOWER, 0x002))
12855 {
12856 IR_dump_map_info = TRUE;
12857
12858 fprintf(TFile, "WN_Lower: WOPT ALIAS INFO\n");
12859 fdump_dep_tree(TFile, tree, alias_manager);
12860 }
12861
12862 if (Get_Trace(TKIND_SYMTAB,TP_LOWER)) {
12863 fprintf(TFile,"\n\n========== Symbol tables after Lowering ==========\n");
12864 Print_symtab (TFile, GLOBAL_SYMTAB);
12865 Print_symtab (TFile, CURRENT_SYMTAB);
12866 }
12867
12868
12869
12870
12871 if (Action(LOWER_SPLIT_SYM_ADDRS))
12872 {
12873 if (Enable_WN_Simp && WN_Simp_Fold_ILOAD)
12874 {
12875 DevWarn("disabling option WN_Simp_Fold_ILOAD"
12876 " while lowering action LOWER_SPLIT_SYM_ADDRS");
12877 WN_Simp_Fold_ILOAD = FALSE;
12878 }
12879 }
12880
12881
12882
12883
12884 {
12885 WN *pragma= NULL;
12886
12887 traceWoptFinishedOpt= FALSE;
12888
12889 switch(WN_operator(tree))
12890 {
12891 case OPR_FUNC_ENTRY:
12892 pragma= WN_func_pragmas(tree);
12893 break;
12894 case OPR_REGION:
12895 pragma= WN_region_pragmas(tree);
12896 break;
12897 }
12898 if (pragma)
12899 {
12900 WN *wn;
12901 for(wn= WN_first(pragma); wn; wn= WN_next(wn))
12902 {
12903 if (WN_pragma(wn) == WN_PRAGMA_WOPT_FINISHED_OPT)
12904 traceWoptFinishedOpt= TRUE;
12905 }
12906 }
12907 }
12908 }
12909
12910
12911
12912
12913
12914
12915
12916
12917
12918
12919
12920
12921
12922
12923
12924 static LOWER_ACTIONS lower_actions(WN *pu, LOWER_ACTIONS actions)
12925 {
12926 if (OPT_Lower_Treeheight && Action(LOWER_TO_CG))
12927 actions |= LOWER_TREEHEIGHT;
12928
12929 if (Action(LOWER_TO_CG))
12930 {
12931
12932
12933
12934 actions |= lowering_actions ^ (LOWER_ENTRY_EXIT |
12935 LOWER_ENTRY_FORMAL_REF |
12936 LOWER_FORMAL_REF |
12937 LOWER_UPLEVEL |
12938 LOWER_SPLIT_SYM_ADDRS |
12939 LOWER_CALL |
12940 LOWER_RETURN_VAL);
12941
12942
12943
12944
12945
12946
12947
12948 actions &= ~(LOWER_BASE_INDEX | LOWER_SPLIT_CONST_OFFSETS);
12949
12950
12951
12952
12953 actions |= LOWER_SCF |
12954 LOWER_ARRAY |
12955 LOWER_MP |
12956 LOWER_IO_STATEMENT |
12957 LOWER_MSTORE |
12958 LOWER_CVT |
12959 LOWER_COMPGOTO |
12960 LOWER_COMPLEX |
12961 LOWER_QUAD |
12962 LOWER_MADD |
12963 LOWER_INTRINSIC |
12964 LOWER_ASSERT |
12965 LOWER_PICCALL |
12966 LOWER_ALL_MAPS |
12967 LOWER_SHORTCIRCUIT |
12968 LOWER_INL_STACK_INTRINSIC |
12969 LOWER_INLINE_INTRINSIC |
12970 LOWER_BIT_FIELD_ID;
12971
12972
12973
12974 save_Div_Split_Allowed = Div_Split_Allowed;
12975 Div_Split_Allowed = FALSE;;
12976 }
12977 if (WN_opcode(pu) == OPC_FUNC_ENTRY)
12978 {
12979 lowering_actions |= actions;
12980 }
12981
12982 if (Action(LOWER_BITS_OP))
12983 actions |= LOWER_BIT_FIELD_ID;
12984
12985 current_actions = actions;
12986
12987 lower_maps_init(actions);
12988
12989 setCurrentState(pu, actions);
12990
12991 return actions;
12992 }
12993
12994
12995
12996
12997
12998
12999
13000
13001
13002
13003
13004 void Lower_Init(void)
13005 {
13006 static CURRENT_STATE current_state_NULL;
13007
13008
13009
13010 lowering_parity_map = WN_MAP32_Create(MEM_pu_pool_ptr);
13011
13012 lowering_actions = 0;
13013 current_state = current_state_NULL;
13014
13015
13016 parity_map_index++;
13017 FmtAssert(0 <= parity_map_index && parity_map_index < PARITY_MAP_ARRAY_SIZE,
13018 ("Lower_Init: Index into parity map array is out of range"));
13019 parity_map_array[parity_map_index] = lowering_parity_map;
13020 }
13021
13022 void Lowering_Finalize(void)
13023 {
13024
13025 WN_MAP_Delete(lowering_parity_map);
13026
13027 parity_map_index--;
13028 if (parity_map_index >= 0) {
13029
13030 lowering_parity_map = parity_map_array[parity_map_index];
13031 }
13032 else {
13033
13034 lowering_parity_map = WN_MAP_UNDEFINED;
13035 }
13036 }
13037
13038
13039
13040
13041 static void lower_end(WN *tree, LOWER_ACTIONS actions)
13042 {
13043 lower_maps_reset(actions);
13044
13045 if (Action(LOWER_TO_CG))
13046 {
13047 Div_Split_Allowed = save_Div_Split_Allowed;
13048 }
13049
13050 popCurrentState(current_state);
13051 }
13052
13053
13054
13055
13056
13057
13058
13059
13060
13061 WN *WN_Lower(WN *tree, LOWER_ACTIONS actions, struct ALIAS_MANAGER *alias,
13062 char *msg)
13063 {
13064 #ifdef BACK_END
13065 Start_Timer(T_Lower_CU);
13066 #endif
13067 alias_manager = alias;
13068 loop_nest_depth = 0;
13069
13070
13071
13072 if (WN_operator(tree) == OPR_FUNC_ENTRY &&
13073 ST_asm_function_st(*WN_st(tree))) {
13074 return tree;
13075 }
13076
13077 actions = lower_actions(tree, actions);
13078
13079 if (Action(LOWER_MP)) {
13080
13081
13082
13083
13084 LowerMP_PU_Init ();
13085 }
13086
13087 if (Action(LOWER_UPC_CONSISTENCY)) {
13088 LowerUPC_Init_Consistency();
13089 }
13090
13091 WN_Lower_Checkdump(msg, tree, actions);
13092
13093 if (WN_opcode(tree) == OPC_FUNC_ENTRY)
13094 {
13095 tree = lower_entry(tree, actions);
13096 }
13097 else if (OPCODE_is_scf(WN_opcode(tree)))
13098 {
13099 tree = lower_scf(NULL, tree, actions);
13100 }
13101 else if (OPCODE_is_stmt(WN_opcode(tree)))
13102 {
13103 tree = lower_stmt(NULL, tree, actions);
13104 }
13105 else if (OPCODE_is_expression(WN_opcode(tree)))
13106 {
13107 tree = lower_expr(NULL, tree, actions);
13108 }
13109
13110 lower_end(tree, actions);
13111
13112 WN_Lower_Checkdump("After lowering", tree, 0);
13113
13114 #ifdef BACK_END
13115 Stop_Timer(T_Lower_CU);
13116 #endif
13117
13118 if(!Action(LOWER_UPC_TO_INTR) && !Action(LOWER_UPC_MFIELD))
13119 WN_verifier(tree);
13120
13121 return tree;
13122 }