00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042 #define __STDC_LIMIT_MACROS
00043 #include <stdint.h>
00044
00045 #ifndef FRONT_END
00046
00047 #include "defs.h"
00048 #include "config.h"
00049 #include "config_opt.h"
00050 #include "mempool.h"
00051 #include "wn.h"
00052 #include "wn_util.h"
00053 #include "opcode.h"
00054 #include <stdlib.h>
00055 #include "flags.h"
00056 #include "pu_info.h"
00057 #include "vho_lower.h"
00058 #include "f90_lower.h"
00059 #include "fb_whirl.h"
00060 #include "wn_simp.h"
00061 #include "topcode.h"
00062 #include "callutil.h"
00063 #include "targ_sim.h"
00064 #include "cxx_template.h"
00065 #include "prompf.h"
00066 #include "wb_f90_lower.h"
00067 #include "wn_lower.h"
00068 #include "be_util.h"
00069 #include "glob.h"
00070 #ifdef KEY
00071 #include "w2op.h"
00072 #endif
00073 #include "config_clist.h"
00074
00075 typedef enum {
00076 ADDRESS_USED,
00077 ADDRESS_PASSED,
00078 ADDRESS_SAVED
00079 } ADDRESS_INFO_TYPE;
00080
00081 #endif
00082
00083 #include "tracing.h"
00084 #include "ir_reader.h"
00085 #include "config_vho.h"
00086 #include "targ_const.h"
00087 #include "erbe.h"
00088
00089 #define DO_VHO_LOWERING 1
00090 #define IS_POWER_OF_2(x) (((x)!=0) && ((x) & ((x)-1))==0)
00091
00092 #define ST_addr_taken_passed(st) ST_addr_passed(st)
00093 #define Set_ST_addr_taken_passed(st) Set_ST_addr_passed(st)
00094 #define Reset_ST_addr_taken_passed(st) Reset_ST_addr_passed(st)
00095 #define ST_addr_taken_saved(st) ST_addr_saved(st)
00096 #define Set_ST_addr_taken_saved(st) Set_ST_addr_saved(st)
00097 #define Reset_ST_addr_taken_saved(st) Reset_ST_addr_saved(st)
00098
00099 #pragma set woff 1172
00100 #ifdef KEY
00101 static INT current_pu_id = -1;
00102 static void Misc_Loop_Fusion ( WN * , WN * );
00103 #endif
00104
00105 static BOOL
00106 VHO_WN_is_zero ( WN * wn )
00107 {
00108 return ( ( WN_operator(wn) == OPR_INTCONST
00109 && WN_const_val(wn) == 0 )
00110 || ( WN_operator(wn) == OPR_CONST
00111 && Targ_Is_Zero(STC_val(WN_st(wn))) ) );
00112 }
00113
00114
00115 static BOOL
00116 VHO_WN_has_side_effects ( WN * wn )
00117 {
00118 INT32 nkids;
00119 INT32 i;
00120 OPERATOR wn_operator;
00121 BOOL has_side_effects;
00122
00123 wn_operator = WN_operator(wn);
00124 nkids = WN_kid_count(wn);
00125
00126 switch ( wn_operator ) {
00127
00128 case OPR_LDID:
00129
00130 has_side_effects = TY_is_volatile(WN_ty(wn));
00131 break;
00132
00133 case OPR_ILOAD:
00134
00135 has_side_effects = TY_is_volatile(WN_ty(wn))
00136 || VHO_WN_has_side_effects ( WN_kid0(wn) );
00137 break;
00138
00139 default:
00140
00141 has_side_effects = FALSE;
00142
00143 for ( i = 0; i < nkids; i++ ) {
00144
00145 if ( VHO_WN_has_side_effects ( WN_kid(wn,i) ) ) {
00146
00147 has_side_effects = TRUE;
00148 break;
00149 }
00150 }
00151 break;
00152 }
00153
00154 return has_side_effects;
00155 }
00156
00157
00158 typedef struct bool_expr_info_t {
00159 OPCODE opcode;
00160 BOOL used_true_label;
00161 BOOL used_false_label;
00162 LABEL_IDX true_label;
00163 LABEL_IDX false_label;
00164 } BOOL_INFO;
00165
00166 static WN * vho_lower ( WN * wn, WN * block );
00167 static WN * vho_lower_stmt ( WN * stmt, WN * block );
00168 static WN * vho_lower_block ( WN * wn );
00169 static WN * vho_lower_expr ( WN * expr, WN * block, BOOL_INFO * bool_info, BOOL is_return=FALSE );
00170
00171
00172
00173
00174
00175 TYPE_ID Promoted_Mtype [MTYPE_LAST + 1] = {
00176 MTYPE_UNKNOWN,
00177 MTYPE_UNKNOWN,
00178 MTYPE_I4,
00179 MTYPE_I4,
00180 MTYPE_I4,
00181 MTYPE_I8,
00182 MTYPE_U4,
00183 MTYPE_U4,
00184 MTYPE_U4,
00185 MTYPE_U8,
00186 MTYPE_F4,
00187 MTYPE_F8,
00188 MTYPE_F10,
00189 MTYPE_UNKNOWN,
00190 MTYPE_UNKNOWN,
00191 MTYPE_FQ,
00192 MTYPE_M,
00193 MTYPE_C4,
00194 MTYPE_C8,
00195 MTYPE_CQ,
00196 MTYPE_V,
00197 #if defined(TARG_IA64)
00198 MTYPE_UNKNOWN,
00199 MTYPE_UNKNOWN,
00200 MTYPE_UNKNOWN,
00201 MTYPE_C10,
00202 #endif
00203 };
00204
00205 #ifdef VHO_DEBUG
00206 static BOOL VHO_Switch_Debug = TRUE;
00207 static BOOL VHO_Struct_Debug = TRUE;
00208 static char * VHO_Switch_Format;
00209 #endif
00210
00211 static SRCPOS VHO_Srcpos;
00212
00213
00214
00215 INT32 VHO_Switch_Distance = 128;
00216 INT32 VHO_Switch_Default_Label_Count = 16;
00217 BOOL VHO_Give_Preg_Names = FALSE;
00218
00219 static const char * vho_lower_mstore_name = "__lower_mstore";
00220 static const char * vho_lower_cand_cior_name = "__cand_cior";
00221 static const char * vho_lower_cselect_name = "__cselect";
00222 static const char * vho_lower_rcomma_name = "__rcomma";
00223 static const char * vho_lower_comma_name = "__comma";
00224
00225 static TY_IDX vho_u4a1_ty_idx = (TY_IDX) 0;
00226 static TY_IDX vho_u8a1_ty_idx = (TY_IDX) 0;
00227
00228 typedef struct switch_case_table_entry_t {
00229 WN * wn;
00230 INT32 count;
00231 FB_FREQ freq;
00232 } VHO_SWITCH_ITEM;
00233
00234 static VHO_SWITCH_ITEM * VHO_Switch_Case_Table;
00235
00236 #define VHO_SWITCH_wn(i) (VHO_Switch_Case_Table[i].wn)
00237 #define VHO_SWITCH_count(i) (VHO_Switch_Case_Table[i].count)
00238 #define VHO_SWITCH_freq(i) (VHO_Switch_Case_Table[i].freq)
00239
00240 static BOOL VHO_Switch_Signed;
00241 static OPCODE VHO_Switch_Int_Opcode;
00242 static OPCODE VHO_Switch_Sub_Opcode;
00243 static OPCODE VHO_Switch_EQ_Opcode;
00244 static OPCODE VHO_Switch_LT_Opcode;
00245 static OPCODE VHO_Switch_GT_Opcode;
00246
00247 static LABEL_IDX VHO_Switch_Default_Label;
00248 static INT32 VHO_Switch_Last_Label;
00249 static INT32 * VHO_Switch_Cluster_Table;
00250 static INT32 VHO_Switch_Ncases;
00251 static INT32 VHO_Switch_Nclusters;
00252 static WN * VHO_Switch_Index;
00253 static WN * VHO_Switch_Default_Goto;
00254 static WN * VHO_Switch_Stmt;
00255 static FB_FREQ VHO_Switch_Default_Freq;
00256
00257 #ifdef KEY
00258 static BOOL VHO_In_MP_Region_Pragma = FALSE;
00259 #endif // KEY
00260
00261
00262
00263 #if defined(TARG_X8664) || defined(TARG_IA64)
00264 INT32 VHO_Struct_Limit = 8;
00265 #elif defined(TARG_NVISA)
00266 INT32 VHO_Struct_Limit = 24;
00267 #else
00268 INT32 VHO_Struct_Limit = 4;
00269 #endif
00270
00271
00272 static BOOL VHO_Struct_Can_Be_Lowered;
00273 static INT32 VHO_Struct_Nfields;
00274 static TY_IDX VHO_Struct_Fld_Table [255];
00275 static INT32 VHO_Struct_Offset_Table [255];
00276
00277
00278
00279
00280
00281 static INT32 VHO_Struct_Field_Id_Table[255];
00282 static BOOL VHO_Struct_Field_Is_Array_Table[255];
00283 static INT32 VHO_Struct_Last_Field_Offset;
00284 static INT32 VHO_Struct_Last_Field_Size;
00285
00286 #define LESS -1
00287 #define EQUAL 0
00288 #define GREATER 1
00289
00290 #define SWITCH_key(i) (VHO_Switch_Signed ? WN_const_val(VHO_SWITCH_wn(i)) : (UINT64) WN_const_val(VHO_SWITCH_wn(i)))
00291
00292 INT32
00293 VHO_Switch_Compare_Value ( const void *v_item1, const void *v_item2 )
00294 {
00295 INT32 compare_code;
00296 WN * case1;
00297 WN * case2;
00298
00299 case1 = (( VHO_SWITCH_ITEM * ) v_item1)->wn;
00300 case2 = (( VHO_SWITCH_ITEM * ) v_item2)->wn;
00301
00302 if ( VHO_Switch_Signed ) {
00303
00304 if ( WN_const_val(case1) < WN_const_val(case2) )
00305 compare_code = LESS;
00306
00307 else
00308 if ( WN_const_val(case1) > WN_const_val(case2) )
00309 compare_code = GREATER;
00310
00311 else
00312 compare_code = EQUAL;
00313 }
00314 else {
00315
00316 if ( (UINT64) WN_const_val(case1) < (UINT64) WN_const_val(case2) )
00317 compare_code = LESS;
00318
00319 else
00320 if ( (UINT64) WN_const_val(case1) > (UINT64) WN_const_val(case2) )
00321 compare_code = GREATER;
00322
00323 else
00324 compare_code = EQUAL;
00325 }
00326
00327 return ( compare_code );
00328 }
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342 INT32
00343 VHO_Switch_Compare_Frequency ( const void *v_item1, const void *v_item2 )
00344 {
00345 INT32 compare_code;
00346 WN * case1;
00347 WN * case2;
00348 FB_FREQ freq1;
00349 FB_FREQ freq2;
00350
00351 case1 = (( VHO_SWITCH_ITEM * ) v_item1)->wn;
00352 case2 = (( VHO_SWITCH_ITEM * ) v_item2)->wn;
00353 freq1 = (( VHO_SWITCH_ITEM * ) v_item1)->freq;
00354 freq2 = (( VHO_SWITCH_ITEM * ) v_item2)->freq;
00355
00356 if ( freq1 != freq2 ) {
00357
00358
00359
00360 if ( freq1 > freq2 )
00361 compare_code = LESS;
00362
00363 else
00364 compare_code = GREATER;
00365
00366 } else
00367 if ( VHO_Switch_Signed ) {
00368
00369 if ( WN_const_val(case1) < WN_const_val(case2) )
00370 compare_code = LESS;
00371
00372 else
00373 if ( WN_const_val(case1) > WN_const_val(case2) )
00374 compare_code = GREATER;
00375
00376 else
00377 compare_code = EQUAL;
00378 }
00379
00380 else {
00381
00382 if ( (UINT64) WN_const_val(case1) < (UINT64) WN_const_val(case2) )
00383 compare_code = LESS;
00384
00385 else
00386 if ( (UINT64) WN_const_val(case1) > (UINT64) WN_const_val(case2) )
00387 compare_code = GREATER;
00388
00389 else
00390 compare_code = EQUAL;
00391 }
00392
00393 return ( compare_code );
00394 }
00395
00396 #ifdef KEY
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407 static WN *
00408 VHO_Switch_Generate_If_Else_Reduce_Branch (SRCPOS srcpos)
00409 {
00410 WN *block, *case_goto, *wn;
00411 INT32 i, j;
00412 INT32 switch_first_label;
00413 INT32 highest_label_num, lowest_label_num;
00414 WN **labels_map;
00415
00416 block = WN_CreateBlock();
00417 WN_Set_Linenum(block, srcpos);
00418
00419
00420 highest_label_num = 0;
00421 lowest_label_num = INT32_MAX;
00422 for (i = 0; i < VHO_Switch_Ncases; i++) {
00423 case_goto = VHO_SWITCH_wn(i);
00424 INT64 value = WN_label_number(case_goto);
00425 if (value > highest_label_num)
00426 highest_label_num = value;
00427 if (value < lowest_label_num)
00428 lowest_label_num = value;
00429 }
00430
00431
00432 INT32 size = (highest_label_num - lowest_label_num + 1) * sizeof(WN *);
00433 labels_map = (WN **) alloca(size);
00434 memset(labels_map, 0, size);
00435
00436
00437
00438 WN *first_label_in_group = (WN *) NULL;
00439 for (wn = WN_next(VHO_Switch_Stmt); ; wn = WN_next(wn)) {
00440 if (WN_operator(wn) == OPR_LABEL) {
00441 if (first_label_in_group == NULL)
00442 first_label_in_group = wn;
00443
00444 if (WN_label_number(wn) >= lowest_label_num &&
00445 WN_label_number(wn) <= highest_label_num) {
00446 labels_map[WN_label_number(wn)] = first_label_in_group;
00447 }
00448 if (WN_label_number(wn) == VHO_Switch_Last_Label)
00449 break;
00450 } else {
00451
00452 first_label_in_group = NULL;
00453 }
00454 }
00455
00456
00457 qsort(VHO_Switch_Case_Table, VHO_Switch_Ncases,
00458 sizeof(VHO_SWITCH_ITEM), VHO_Switch_Compare_Value);
00459
00460 for (i = 0; i < VHO_Switch_Ncases; i++) {
00461 WN *test, *sub, *tas;
00462 case_goto = VHO_SWITCH_wn(i);
00463 INT64 first_value = WN_const_val(case_goto);
00464 INT64 last_value = first_value;
00465
00466
00467 for (j = i + 1; j < VHO_Switch_Ncases; j++) {
00468 WN *next_case_goto = VHO_SWITCH_wn(j);
00469 INT64 next_value = WN_const_val(next_case_goto);
00470 if (next_value != last_value + 1 ||
00471 (labels_map[WN_label_number(next_case_goto)] !=
00472 labels_map[WN_label_number(case_goto)]))
00473 break;
00474 last_value = next_value;
00475 }
00476
00477 if (first_value == last_value) {
00478
00479 test = WN_CreateExp2(VHO_Switch_EQ_Opcode,
00480 WN_COPY_Tree(VHO_Switch_Index),
00481 WN_CreateIntconst(VHO_Switch_Int_Opcode,
00482 first_value));
00483 wn = WN_CreateTruebr(WN_label_number(case_goto), test);
00484 WN_Set_Linenum(wn, srcpos);
00485 } else {
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501 WN *upper =
00502 WN_CreateIntconst(VHO_Switch_Int_Opcode, last_value - first_value);
00503 TYPE_ID mtype = WN_rtype(VHO_Switch_Index);
00504 sub = WN_CreateExp2(VHO_Switch_Sub_Opcode,
00505 WN_COPY_Tree(VHO_Switch_Index),
00506 WN_CreateIntconst(VHO_Switch_Int_Opcode,
00507 first_value));
00508 tas = WN_Tas(MTYPE_U4, MTYPE_To_TY(MTYPE_U4), sub);
00509 test = WN_CreateExp2(OPCODE_make_op(OPR_LE, MTYPE_U4, MTYPE_U4),
00510 tas, upper);
00511 wn = WN_CreateTruebr(WN_label_number(case_goto), test);
00512 WN_Set_Linenum(wn, srcpos);
00513 i = j - 1;
00514 }
00515 WN_INSERT_BlockAfter(block, WN_last(block), wn);
00516 }
00517
00518 WN_INSERT_BlockAfter(block, WN_last(block),
00519 WN_COPY_Tree(VHO_Switch_Default_Goto));
00520 return block;
00521 }
00522 #endif
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534 static WN *
00535 VHO_Switch_Generate_If_Else ( SRCPOS srcpos )
00536 {
00537 WN * block;
00538 WN * value;
00539 WN * test;
00540 WN * case_goto;
00541 WN * wn;
00542 INT32 i;
00543 FB_FREQ freq_rest;
00544
00545 block = WN_CreateBlock();
00546 WN_Set_Linenum ( block, srcpos );
00547
00548 if ( Cur_PU_Feedback ) {
00549
00550 qsort ( VHO_Switch_Case_Table, VHO_Switch_Ncases,
00551 sizeof(VHO_SWITCH_ITEM), VHO_Switch_Compare_Frequency );
00552
00553 freq_rest = VHO_Switch_Default_Freq;
00554 for ( i = 0; i < VHO_Switch_Ncases; i++ ) {
00555 freq_rest += VHO_SWITCH_freq(i);
00556 }
00557
00558 }
00559
00560 for ( i = 0; i < VHO_Switch_Ncases; i++ ) {
00561
00562 case_goto = VHO_SWITCH_wn(i);
00563 value = WN_CreateIntconst ( VHO_Switch_Int_Opcode,
00564 WN_const_val(case_goto) );
00565 test = WN_CreateExp2 ( VHO_Switch_EQ_Opcode,
00566 WN_COPY_Tree ( VHO_Switch_Index ), value );
00567 wn = WN_CreateTruebr ( WN_label_number(case_goto), test );
00568 WN_Set_Linenum ( wn, srcpos );
00569
00570 if ( Cur_PU_Feedback ) {
00571 freq_rest -= VHO_SWITCH_freq(i);
00572 Cur_PU_Feedback->Annot( wn, FB_EDGE_BRANCH_TAKEN, VHO_SWITCH_freq(i) );
00573 Cur_PU_Feedback->Annot( wn, FB_EDGE_BRANCH_NOT_TAKEN, freq_rest );
00574 }
00575
00576 WN_INSERT_BlockAfter ( block, WN_last(block), wn );
00577 }
00578 if ( Cur_PU_Feedback && (VHO_Switch_Ncases > 0))
00579 Cur_PU_Feedback->Annot( wn, FB_EDGE_BRANCH_NOT_TAKEN,
00580 VHO_Switch_Default_Freq );
00581
00582 WN_INSERT_BlockAfter ( block, WN_last(block),
00583 WN_COPY_Tree ( VHO_Switch_Default_Goto ) );
00584
00585 return ( block );
00586 }
00587
00588
00589
00590
00591
00592
00593
00594
00595 static WN *
00596 VHO_Switch_Opt_Case_Hoist( SRCPOS srcpos )
00597 {
00598 WN * block;
00599 WN * value;
00600 WN * test;
00601 WN * case_goto;
00602 WN * wn;
00603 INT32 i;
00604 FB_FREQ freq_total, freq_rest, freq_top;
00605 FB_FREQ freq_tops;
00606 INT32 num_hoist=0;
00607
00608 if (!Cur_PU_Feedback ) return NULL;
00609
00610 #ifdef KEY
00611 freq_tops = freq_total = 0.0;
00612 #else
00613 freq_tops = freq_total = 0;
00614 #endif
00615
00616 block = WN_CreateBlock();
00617 WN_Set_Linenum ( block, srcpos );
00618
00619 if ( Cur_PU_Feedback ) {
00620 qsort ( VHO_Switch_Case_Table, VHO_Switch_Ncases,
00621 sizeof(VHO_SWITCH_ITEM), VHO_Switch_Compare_Frequency );
00622
00623 freq_total = VHO_Switch_Default_Freq;
00624 for ( i = 0; i < VHO_Switch_Ncases; i++ ) {
00625 freq_total += VHO_SWITCH_freq(i);
00626
00627 if (i < VHO_Switch_Ncases * 0.3)
00628 freq_tops += VHO_SWITCH_freq(i);
00629 }
00630 }
00631
00632 if (freq_total.Value()<=0 || freq_tops.Value()/freq_total.Value() < 0.70)
00633 return NULL;
00634
00635
00636 freq_rest = freq_total;
00637
00638 for ( i = 0; i < VHO_Switch_Ncases; i++ ) {
00639
00640 if ( Cur_PU_Feedback && VHO_SWITCH_freq(i).Value()/freq_total.Value()
00641 < (float) VHO_Switch_Opt_Threshold/100)
00642 break;
00643 #ifdef VHO_DEBUG
00644 if ( VHO_Switch_Debug )
00645 fprintf ( TFile, "SWITCH_OPT_CASE_HOIST: %d (case %d of freq %f)\n", (INT32) srcpos, i, VHO_SWITCH_freq(i).Value() );
00646 #endif
00647
00648
00649
00650 num_hoist++;
00651 case_goto = VHO_SWITCH_wn(i);
00652 value = WN_CreateIntconst ( VHO_Switch_Int_Opcode,
00653 WN_const_val(case_goto) );
00654 test = WN_CreateExp2 ( VHO_Switch_EQ_Opcode,
00655 WN_COPY_Tree ( VHO_Switch_Index ), value );
00656 wn = WN_CreateTruebr ( WN_label_number(case_goto), test );
00657
00658 WN_Set_Linenum ( wn, srcpos );
00659
00660
00661 if ( Cur_PU_Feedback ) {
00662 freq_rest -= VHO_SWITCH_freq(i);
00663 Cur_PU_Feedback->Annot_branch( wn, FB_Info_Branch( VHO_SWITCH_freq(i),
00664 freq_rest, WN_operator( wn ) ) );
00665 Cur_PU_Feedback->FB_hoist_case(VHO_Switch_Stmt, i);
00666 #ifdef KEY
00667 VHO_SWITCH_freq(i) = 0.0;
00668 #else
00669 VHO_SWITCH_freq(i) = 0;
00670 #endif
00671 }
00672
00673 WN_INSERT_BlockAfter ( block, WN_last(block), wn );
00674 }
00675
00676
00677 for ( i = 0; i < VHO_Switch_Ncases; i++ ) {
00678 VHO_SWITCH_wn(i) = VHO_SWITCH_wn(i + num_hoist);
00679 VHO_SWITCH_freq(i) = VHO_SWITCH_freq(i + num_hoist);
00680 VHO_SWITCH_count(i) = VHO_SWITCH_count(i+num_hoist);
00681
00682 }
00683 VHO_Switch_Ncases = VHO_Switch_Ncases - num_hoist;
00684 VHO_SWITCH_wn(VHO_Switch_Ncases) = VHO_SWITCH_wn(VHO_Switch_Ncases - 1);
00685
00686 return ( block );
00687
00688 }
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701 static WN *
00702 VHO_Switch_Generate_Compgoto ( SRCPOS srcpos )
00703 {
00704 WN * block;
00705 WN * test;
00706 WN * value;
00707 WN * wn;
00708 WN * case_goto;
00709 INT32 i;
00710 INT32 j;
00711 INT32 n;
00712 INT64 case_value;
00713 INT64 curr_value;
00714 FB_FREQ * freq_new = NULL;
00715
00716 block = WN_CreateBlock ();
00717 WN_Set_Linenum ( block, srcpos );
00718
00719 case_goto = VHO_SWITCH_wn(0);
00720 case_value = WN_const_val(case_goto);
00721 curr_value = 0;
00722 test = WN_COPY_Tree ( VHO_Switch_Index );
00723
00724
00725
00726 if ( case_value
00727 && (UINT64)case_value > VHO_Switch_Compgoto_Limit ) {
00728
00729 value = WN_CreateIntconst ( VHO_Switch_Int_Opcode,
00730 WN_const_val(case_goto) );
00731 test = WN_CreateExp2 ( VHO_Switch_Sub_Opcode, test, value );
00732 curr_value = case_value;
00733 }
00734
00735 i = 0;
00736 n = WN_const_val(VHO_SWITCH_wn(VHO_Switch_Ncases - 1))
00737 - curr_value + 1;
00738
00739 if ( Cur_PU_Feedback )
00740 freq_new = TYPE_MEM_POOL_ALLOC_N( FB_FREQ, MEM_local_pool_ptr, n );
00741
00742 for ( j = 0; j < n; j++ ) {
00743
00744 if ( curr_value != case_value ) {
00745 wn = WN_COPY_Tree ( VHO_Switch_Default_Goto );
00746 if ( Cur_PU_Feedback )
00747
00748 freq_new[j] = FB_FREQ(FB_FREQ_TYPE_GUESS);
00749
00750 } else {
00751
00752 wn = WN_CreateGoto ( (ST_IDX) NULL, WN_label_number(case_goto) );
00753 if ( Cur_PU_Feedback )
00754 freq_new[j] = VHO_SWITCH_freq(i);
00755 i++;
00756 case_goto = VHO_SWITCH_wn(i);
00757 case_value = WN_const_val(case_goto);
00758 }
00759
00760 WN_Set_Linenum ( wn, srcpos );
00761
00762 WN_INSERT_BlockAfter ( block, WN_last(block), wn );
00763 curr_value++;
00764 }
00765
00766 wn = WN_CreateCompgoto ( n, test, block, VHO_Switch_Default_Goto,
00767 VHO_Switch_Last_Label );
00768
00769 if ( Cur_PU_Feedback ) {
00770
00771 FB_Info_Switch info_switch( n );
00772 info_switch[ FB_EDGE_SWITCH_INDEX( FB_EDGE_SWITCH_DEFAULT ) ]
00773
00774 = FB_FREQ(VHO_Switch_Default_Freq.Value(), FALSE);
00775 for ( j = 0; j < n; j++ )
00776 info_switch[ FB_EDGE_SWITCH_INDEX( FB_EDGE_SWITCH( j ) ) ] = freq_new[j];
00777 Cur_PU_Feedback->Annot_switch( wn, info_switch );
00778
00779 MEM_POOL_FREE( MEM_local_pool_ptr, freq_new );
00780 }
00781
00782 return wn;
00783 }
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799 static void
00800 VHO_Switch_Generate_Binary_Search ( INT32 left, INT32 right, WN * block )
00801 {
00802 INT32 mid;
00803 INT64 value;
00804 WN * test;
00805 WN * wn;
00806 SRCPOS srcpos;
00807
00808 LABEL_IDX lt_label;
00809 LABEL_IDX gt_label;
00810
00811 srcpos = WN_Get_Linenum(block);
00812
00813 mid = ( left + right + 1 ) >> 1;
00814 value = WN_const_val(VHO_SWITCH_wn(mid));
00815
00816
00817 if (mid > left)
00818 LABEL_Init (New_LABEL (CURRENT_SYMTAB, lt_label), 0, LKIND_DEFAULT);
00819 else
00820 lt_label = VHO_Switch_Default_Label;
00821
00822 if (mid < right)
00823 LABEL_Init (New_LABEL (CURRENT_SYMTAB, gt_label), 0, LKIND_DEFAULT);
00824 else
00825 gt_label = VHO_Switch_Default_Label;
00826
00827 if ( lt_label == gt_label ) {
00828
00829 test = WN_CreateExp2 ( VHO_Switch_EQ_Opcode,
00830 WN_COPY_Tree ( VHO_Switch_Index ),
00831 WN_CreateIntconst ( VHO_Switch_Int_Opcode,
00832 value ) );
00833 wn = WN_CreateFalsebr ( lt_label, test );
00834 WN_Set_Linenum ( wn, srcpos );
00835 if ( Cur_PU_Feedback ) {
00836 Cur_PU_Feedback->Annot( wn, FB_EDGE_BRANCH_TAKEN, FB_FREQ_UNKNOWN );
00837 Cur_PU_Feedback->Annot( wn, FB_EDGE_BRANCH_NOT_TAKEN,
00838 VHO_SWITCH_freq( mid ) );
00839 }
00840
00841 WN_INSERT_BlockAfter ( block, WN_last(block), wn );
00842 }
00843
00844 else {
00845
00846 test = WN_CreateExp2 ( VHO_Switch_LT_Opcode,
00847 WN_COPY_Tree ( VHO_Switch_Index ),
00848 WN_CreateIntconst ( VHO_Switch_Int_Opcode,
00849 value ) );
00850 wn = WN_CreateTruebr ( lt_label, test );
00851 WN_Set_Linenum ( wn, srcpos );
00852 if ( Cur_PU_Feedback ) {
00853 Cur_PU_Feedback->Annot( wn, FB_EDGE_BRANCH_TAKEN, FB_FREQ_UNKNOWN );
00854 Cur_PU_Feedback->Annot( wn, FB_EDGE_BRANCH_NOT_TAKEN,
00855 FB_FREQ_UNKNOWN );
00856 }
00857
00858 WN_INSERT_BlockAfter ( block, WN_last(block), wn );
00859
00860 test = WN_CreateExp2 ( VHO_Switch_GT_Opcode,
00861 WN_COPY_Tree ( VHO_Switch_Index ),
00862 WN_CreateIntconst ( VHO_Switch_Int_Opcode,
00863 value ) );
00864 wn = WN_CreateTruebr ( gt_label, test );
00865 WN_Set_Linenum ( wn, srcpos );
00866 if ( Cur_PU_Feedback ) {
00867 Cur_PU_Feedback->Annot( wn, FB_EDGE_BRANCH_TAKEN, FB_FREQ_UNKNOWN );
00868 Cur_PU_Feedback->Annot( wn, FB_EDGE_BRANCH_NOT_TAKEN,
00869 VHO_SWITCH_freq( mid ) );
00870 }
00871
00872 WN_INSERT_BlockAfter ( block, WN_last(block), wn );
00873 }
00874
00875 wn = WN_CreateGoto ( (ST_IDX) NULL, WN_label_number(VHO_SWITCH_wn(mid)) );
00876 WN_Set_Linenum ( wn, srcpos );
00877 if ( Cur_PU_Feedback )
00878 Cur_PU_Feedback->Annot( wn, FB_EDGE_OUTGOING, VHO_SWITCH_freq( mid ) );
00879
00880 WN_INSERT_BlockAfter ( block, WN_last(block), wn );
00881
00882 if ( mid > left ) {
00883
00884 wn = WN_CreateLabel ( (ST_IDX) 0, lt_label, 0, NULL );
00885 WN_Set_Linenum ( wn, srcpos );
00886
00887 WN_INSERT_BlockAfter ( block, WN_last(block), wn );
00888 VHO_Switch_Generate_Binary_Search ( left, mid - 1, block );
00889 }
00890
00891 if ( mid < right ) {
00892
00893 wn = WN_CreateLabel ( (ST_IDX) 0, gt_label, 0, NULL );
00894 WN_Set_Linenum ( wn, srcpos );
00895
00896 WN_INSERT_BlockAfter ( block, WN_last(block), wn );
00897 VHO_Switch_Generate_Binary_Search ( mid + 1, right, block );
00898 }
00899 }
00900
00901
00902
00903
00904
00905
00906
00907
00908
00909
00910
00911
00912 static void
00913 VHO_Switch_Find_Clusters ( void )
00914 {
00915 INT32 i;
00916 INT32 j;
00917 INT32 k;
00918 INT32 n;
00919
00920 qsort ( VHO_Switch_Case_Table, VHO_Switch_Ncases,
00921 sizeof(VHO_SWITCH_ITEM), VHO_Switch_Compare_Value );
00922
00923 #ifdef VHO_DEBUG
00924 if ( VHO_Switch_Debug ) {
00925
00926 fprintf ( TFile, "SWITCH TABLE after sorting\n" );
00927
00928 for ( i = 0; i < VHO_Switch_Ncases; i++ ) {
00929
00930 case_goto = VHO_SWITCH_wn(i);
00931 fprintf ( TFile, VHO_Switch_Format, i,
00932 WN_const_val(case_goto), WN_label_number(case_goto) );
00933 }
00934 }
00935 #endif
00936
00937 j = 0;
00938 VHO_Switch_Cluster_Table [0] = 0;
00939
00940 for ( i = 1; i < VHO_Switch_Ncases; i++ ) {
00941
00942 if ( ( i - VHO_Switch_Cluster_Table [j] ) * VHO_Switch_Density
00943 >= SWITCH_key(i) - SWITCH_key(VHO_Switch_Cluster_Table[j]) ) {
00944
00945 if (j > 0) {
00946
00947 if ( ( i - VHO_Switch_Cluster_Table [j-1] ) * VHO_Switch_Density
00948 >= SWITCH_key(i) - SWITCH_key(VHO_Switch_Cluster_Table[j-1]) )
00949 j--;
00950 }
00951 }
00952
00953 else
00954 VHO_Switch_Cluster_Table [++j] = i;
00955 }
00956
00957 VHO_Switch_Cluster_Table [++j] = VHO_Switch_Ncases;
00958
00959 VHO_Switch_Nclusters = 0;
00960
00961 for ( i = 0; i < j; i++ ) {
00962
00963 if ( VHO_Switch_Cluster_Table [i+1] - VHO_Switch_Cluster_Table [i]
00964 > VHO_Switch_If_Else_Limit )
00965 VHO_Switch_Nclusters++;
00966
00967 else
00968 VHO_Switch_Nclusters +=
00969 VHO_Switch_Cluster_Table [i+1] - VHO_Switch_Cluster_Table [i];
00970 }
00971
00972 if ( VHO_Switch_Nclusters > j ) {
00973
00974 i = VHO_Switch_Nclusters;
00975
00976 while ( j > 0 ) {
00977
00978 n = VHO_Switch_Cluster_Table [j] - VHO_Switch_Cluster_Table [j-1];
00979
00980 if ( n > VHO_Switch_If_Else_Limit )
00981 VHO_Switch_Cluster_Table [i--] = VHO_Switch_Cluster_Table [j];
00982
00983 else {
00984
00985 for ( k = 0; k < n; k++ )
00986 VHO_Switch_Cluster_Table [i--] = VHO_Switch_Cluster_Table [j] - k;
00987
00988 if ( i < j )
00989 break;
00990 }
00991
00992 --j;
00993 }
00994 }
00995
00996 #ifdef VHO_DEBUG
00997 if ( VHO_Switch_Debug ) {
00998
00999 fprintf (TFile, " VHO_Switch_Nclusters = %d\n", VHO_Switch_Nclusters);
01000
01001 for ( i = 0; i <= VHO_Switch_Nclusters; i++ )
01002 fprintf (TFile, " VHO_Switch_Cluster_Table [%2d] = %2d\n",
01003 i, VHO_Switch_Cluster_Table [i]);
01004 }
01005 #endif
01006 }
01007
01008
01009
01010
01011
01012
01013
01014
01015
01016
01017
01018
01019
01020
01021
01022 static WN *
01023 VHO_Lower_Switch ( WN * wn )
01024 {
01025 WN * block;
01026 WN * case_goto;
01027 TYPE_ID mtype;
01028 INT32 i;
01029 INT32 j;
01030 SRCPOS srcpos;
01031 INT32 count;
01032 WN * conv_wn = NULL;
01033
01034 LABEL_IDX last_label;
01035
01036 srcpos = WN_Get_Linenum(wn);
01037 block = WN_kid1(wn);
01038
01039 VHO_Switch_Stmt = wn;
01040 VHO_Switch_Index = WN_kid0(wn);
01041 VHO_Switch_Default_Goto = ( WN_kid_count(wn) == 3 ) ? WN_kid2(wn) : NULL;
01042 VHO_Switch_Last_Label = WN_last_label(wn);
01043
01044 mtype = WN_rtype (VHO_Switch_Index);
01045
01046 VHO_Switch_Int_Opcode = OPCODE_make_op ( OPR_INTCONST,
01047 Promoted_Mtype [mtype],
01048 MTYPE_V );
01049 VHO_Switch_Sub_Opcode = OPCODE_make_op ( OPR_SUB,
01050 Promoted_Mtype [mtype],
01051 MTYPE_V );
01052 VHO_Switch_EQ_Opcode = OPCODE_make_op ( OPR_EQ,
01053 MTYPE_I4,
01054 Promoted_Mtype [mtype] );
01055 VHO_Switch_LT_Opcode = OPCODE_make_op ( OPR_LT,
01056 MTYPE_I4,
01057 Promoted_Mtype [mtype] );
01058 VHO_Switch_GT_Opcode = OPCODE_make_op ( OPR_GT,
01059 MTYPE_I4,
01060 Promoted_Mtype [mtype] );
01061
01062 #ifdef VHO_DEBUG
01063 if ( VHO_Switch_Debug )
01064 fprintf ( TFile, "SWITCH TABLE before sorting\n" );
01065 #endif
01066
01067 switch ( mtype ) {
01068
01069 case MTYPE_I1:
01070 case MTYPE_I2:
01071 case MTYPE_I4:
01072 case MTYPE_I8:
01073
01074 #ifdef VHO_DEBUG
01075 VHO_Switch_Format = " [%2d] value = %lld, label = %d\n";
01076 #endif
01077
01078 VHO_Switch_Signed = TRUE;
01079 break;
01080
01081 case MTYPE_U1:
01082 case MTYPE_U2:
01083 case MTYPE_U4:
01084 case MTYPE_U8:
01085
01086 #ifdef VHO_DEBUG
01087 VHO_Switch_Format = " [%2d] value = %llu, label = %d\n";
01088 #endif
01089
01090 VHO_Switch_Signed = FALSE;
01091 break;
01092 }
01093
01094 for ( VHO_Switch_Ncases = 0, case_goto = WN_first(block);
01095 case_goto;
01096 VHO_Switch_Ncases++, case_goto = WN_next(case_goto) ) {
01097
01098 #ifdef VHO_DEBUG
01099 if ( VHO_Switch_Debug )
01100 fprintf ( TFile, VHO_Switch_Format, VHO_Switch_Ncases,
01101 WN_const_val(case_goto), WN_label_number(case_goto) );
01102 #endif
01103
01104 }
01105
01106 if ( Cur_PU_Feedback ) {
01107 VHO_Switch_Default_Freq
01108 = ( VHO_Switch_Default_Goto
01109 ? Cur_PU_Feedback->Query( wn, FB_EDGE_SWITCH_DEFAULT )
01110 : FB_FREQ_ZERO );
01111 }
01112
01113 VHO_Switch_Case_Table =
01114 TYPE_MEM_POOL_ALLOC_N(VHO_SWITCH_ITEM,
01115 MEM_local_pool_ptr, (VHO_Switch_Ncases+1));
01116 VHO_Switch_Cluster_Table =
01117 TYPE_MEM_POOL_ALLOC_N(INT32, MEM_local_pool_ptr, (VHO_Switch_Ncases+1));
01118
01119 last_label = INT32_MIN;
01120
01121 for ( i = 0, case_goto = WN_first(block);
01122 i < VHO_Switch_Ncases;
01123 i++, case_goto = WN_next(case_goto) ) {
01124
01125 VHO_SWITCH_wn(i) = case_goto;
01126 if ( Cur_PU_Feedback )
01127 VHO_SWITCH_freq(i) = Cur_PU_Feedback->Query( wn, FB_EDGE_SWITCH( i ) );
01128
01129 if ( WN_label_number(case_goto) == last_label )
01130 count++;
01131
01132 else {
01133
01134 for ( j = i - 1; j >= 0; --j ) {
01135
01136 if ( last_label == WN_label_number(VHO_SWITCH_wn(j)) )
01137 VHO_SWITCH_count(j) = count;
01138
01139 else
01140 break;
01141 }
01142
01143 count = 1;
01144 last_label = WN_label_number(case_goto);
01145 }
01146 }
01147
01148 for ( j = i - 1; j >= 0; --j ) {
01149
01150 if ( last_label == WN_label_number(VHO_SWITCH_wn(j)) )
01151 VHO_SWITCH_count(j) = count;
01152
01153 else
01154 break;
01155 }
01156
01157 VHO_SWITCH_wn(VHO_Switch_Ncases) = VHO_SWITCH_wn(VHO_Switch_Ncases - 1);
01158
01159 for ( i = 0; i < VHO_Switch_Ncases; i++ ) {
01160
01161 case_goto = VHO_SWITCH_wn(i);
01162 }
01163
01164 if ( VHO_Switch_Ncases <= VHO_Switch_If_Else_Limit ) {
01165
01166 #ifdef VHO_DEBUG
01167 if ( VHO_Switch_Debug )
01168 fprintf ( TFile, "SWITCH_If_Else %d\n", (INT32) srcpos );
01169 #endif
01170
01171 #ifdef KEY
01172 if ( !Cur_PU_Feedback &&
01173 VHO_Switch_Reduce_Branch) {
01174 wn = VHO_Switch_Generate_If_Else_Reduce_Branch(srcpos);
01175 } else
01176 #endif
01177 wn = VHO_Switch_Generate_If_Else ( srcpos );
01178 }
01179
01180 else {
01181 if (VHO_Switch_Opt)
01182 conv_wn = VHO_Switch_Opt_Case_Hoist ( srcpos );
01183
01184 #ifdef VHO_DEBUG
01185 if ( VHO_Switch_Debug )
01186 fprintf ( TFile, "SWITCH_OPT %d\n", (INT32) srcpos );
01187 #endif
01188
01189 VHO_Switch_Find_Clusters ();
01190
01191 if ( VHO_Switch_Nclusters == 1 ) {
01192
01193 #ifdef VHO_DEBUG
01194 if ( VHO_Switch_Debug )
01195 fprintf ( TFile, "SWITCH_Compgoto %d\n", (INT32) srcpos );
01196 #endif
01197
01198 wn = VHO_Switch_Generate_Compgoto ( srcpos );
01199 }
01200
01201 else {
01202
01203 #ifdef VHO_DEBUG
01204 if ( VHO_Switch_Debug )
01205 fprintf ( TFile, "SWITCH_binary %d\n", (INT32) srcpos );
01206 #endif
01207
01208 wn = WN_CreateBlock ();
01209 WN_Set_Linenum ( wn, srcpos );
01210
01211 if (VHO_Switch_Default_Goto)
01212 VHO_Switch_Default_Label = WN_label_number(VHO_Switch_Default_Goto);
01213 else
01214 LABEL_Init (New_LABEL (CURRENT_SYMTAB, VHO_Switch_Default_Label),
01215 0, LKIND_DEFAULT);
01216
01217 VHO_Switch_Generate_Binary_Search ( 0, VHO_Switch_Ncases-1, wn );
01218 }
01219 }
01220
01221 MEM_POOL_FREE ( MEM_local_pool_ptr, VHO_Switch_Case_Table );
01222 MEM_POOL_FREE ( MEM_local_pool_ptr, VHO_Switch_Cluster_Table );
01223 if (conv_wn == NULL)
01224 return wn;
01225 else {
01226 WN_INSERT_BlockAfter (conv_wn, WN_last(conv_wn), wn);
01227 return conv_wn;
01228 }
01229
01230 return wn;
01231 }
01232
01233
01234
01235
01236
01237
01238
01239
01240
01241 static WN *
01242 VHO_Lower_Compgoto ( WN * wn )
01243 {
01244 return wn;
01245 }
01246
01247
01248
01249
01250
01251
01252
01253
01254
01255
01256
01257
01258
01259
01260
01261
01262
01263
01264
01265 static UINT
01266 VHO_Get_Field_List ( WN_OFFSET offset, TY_IDX sty_idx, UINT field_id )
01267 {
01268 TY_IDX fty_idx;
01269 WN_OFFSET field_offset;
01270
01271 if ( TY_fld(Ty_Table [sty_idx]).Is_Null () ) {
01272 VHO_Struct_Can_Be_Lowered = FALSE;
01273 return field_id;
01274 }
01275
01276 FLD_ITER fld_iter = Make_fld_iter (TY_fld (Ty_Table[sty_idx]));
01277
01278 while (VHO_Struct_Can_Be_Lowered) {
01279 FLD_HANDLE fld (fld_iter);
01280 if ( FLD_is_bit_field(fld) ) {
01281 VHO_Struct_Can_Be_Lowered = FALSE;
01282 break;
01283 }
01284 fty_idx = FLD_type(fld);
01285 switch ( TY_kind(Ty_Table [fty_idx]) ) {
01286
01287 case KIND_SCALAR:
01288 case KIND_POINTER:
01289 field_offset = offset + FLD_ofst(fld);
01290
01291 ++field_id;
01292 if ( VHO_Struct_Nfields ) {
01293 if ( field_offset >= VHO_Struct_Last_Field_Offset
01294 + VHO_Struct_Last_Field_Size ) {
01295
01296 VHO_Struct_Last_Field_Offset = field_offset;
01297 VHO_Struct_Last_Field_Size = TY_size (Ty_Table [fty_idx]);
01298 VHO_Struct_Field_Is_Array_Table [VHO_Struct_Nfields] = FALSE;
01299 VHO_Struct_Field_Id_Table [VHO_Struct_Nfields] = field_id;
01300 VHO_Struct_Offset_Table [VHO_Struct_Nfields] = field_offset;
01301 VHO_Struct_Fld_Table [VHO_Struct_Nfields++] = fty_idx;
01302 }
01303 else
01304 if ( field_offset == VHO_Struct_Last_Field_Offset ) {
01305
01306 if ( TY_size (Ty_Table [fty_idx]) > VHO_Struct_Last_Field_Size ) {
01307
01308 VHO_Struct_Last_Field_Offset = field_offset;
01309 VHO_Struct_Last_Field_Size = TY_size (Ty_Table [fty_idx]);
01310 VHO_Struct_Field_Is_Array_Table [VHO_Struct_Nfields] = FALSE;
01311 VHO_Struct_Field_Id_Table [VHO_Struct_Nfields] = field_id;
01312 VHO_Struct_Fld_Table [VHO_Struct_Nfields-1] = fty_idx;
01313 VHO_Struct_Offset_Table [VHO_Struct_Nfields-1] = field_offset;
01314 }
01315 }
01316 else
01317 if ( field_offset + TY_size (Ty_Table [fty_idx])
01318 > VHO_Struct_Last_Field_Offset + VHO_Struct_Last_Field_Size ) {
01319 VHO_Struct_Can_Be_Lowered = FALSE;
01320 }
01321 }
01322
01323 else {
01324
01325 VHO_Struct_Last_Field_Offset = field_offset;
01326 VHO_Struct_Last_Field_Size = TY_size (Ty_Table [fty_idx]);
01327 VHO_Struct_Field_Is_Array_Table [VHO_Struct_Nfields] = FALSE;
01328 VHO_Struct_Field_Id_Table [VHO_Struct_Nfields] = field_id;
01329 VHO_Struct_Offset_Table [VHO_Struct_Nfields] = field_offset;
01330 VHO_Struct_Fld_Table [VHO_Struct_Nfields++] = fty_idx;
01331 }
01332 break;
01333
01334 case KIND_STRUCT:
01335
01336 if ( TY_is_packed(Ty_Table[fty_idx] ))
01337 VHO_Struct_Can_Be_Lowered = FALSE;
01338 else {
01339
01340
01341
01342
01343 ++field_id;
01344
01345
01346
01347 field_id = VHO_Get_Field_List (offset + FLD_ofst (fld), fty_idx, field_id);
01348 }
01349 break;
01350
01351 case KIND_ARRAY:
01352 INT32 array_elem_num;
01353 TY_IDX ety_idx;
01354
01355 ety_idx = Ty_Table [fty_idx].Etype();
01356 #ifdef KEY // bug 5273: array element size can be zero
01357 if (TY_size(Ty_Table[ety_idx]) == 0)
01358 array_elem_num = 0;
01359 else {
01360 #endif
01361 Is_True (TY_size(Ty_Table [fty_idx])%TY_size(Ty_Table [ety_idx]) == 0,
01362 ("unexpected array type"));
01363 array_elem_num = TY_size(Ty_Table [fty_idx])/TY_size(Ty_Table [ety_idx]);
01364 #ifdef KEY // bug 5273
01365 }
01366 #endif
01367
01368
01369 if (VHO_Struct_Nfields + array_elem_num >= 255) {
01370 VHO_Struct_Can_Be_Lowered = FALSE;
01371 break;
01372 }
01373 ++field_id;
01374 field_offset = offset + FLD_ofst(fld);
01375
01376 if(VHO_Struct_Nfields) {
01377 if ( field_offset >= VHO_Struct_Last_Field_Offset
01378 + VHO_Struct_Last_Field_Size ) {
01379 for(int i=0; i<array_elem_num; i++) {
01380 if (TY_kind(ety_idx) == KIND_STRUCT) {
01381 INT last_nfield = VHO_Struct_Nfields;
01382
01383 VHO_Get_Field_List (field_offset + i*TY_size(ety_idx),
01384 ety_idx, field_id);
01385 for (INT j=last_nfield; j < VHO_Struct_Nfields; ++j) {
01386 VHO_Struct_Field_Is_Array_Table [j] = TRUE;
01387 VHO_Struct_Field_Id_Table [j] = field_id;
01388 }
01389 }
01390 else {
01391 VHO_Struct_Field_Is_Array_Table [VHO_Struct_Nfields] = TRUE;
01392 VHO_Struct_Field_Id_Table [VHO_Struct_Nfields] = field_id;
01393 VHO_Struct_Offset_Table [VHO_Struct_Nfields] = field_offset + i*TY_size(Ty_Table [ety_idx]);
01394 VHO_Struct_Fld_Table [VHO_Struct_Nfields++] = ety_idx;
01395 }
01396 }
01397 VHO_Struct_Last_Field_Offset = field_offset;
01398 VHO_Struct_Last_Field_Size = TY_size(Ty_Table [fty_idx]);
01399 } else if ( field_offset == VHO_Struct_Last_Field_Offset ) {
01400 if ( TY_size (Ty_Table [fty_idx]) > VHO_Struct_Last_Field_Size ) {
01401 VHO_Struct_Nfields--;
01402 for(int i=0; i<array_elem_num; i++) {
01403 if (TY_kind(ety_idx) == KIND_STRUCT) {
01404 INT last_nfield = VHO_Struct_Nfields;
01405
01406 VHO_Get_Field_List (field_offset + i*TY_size(ety_idx),
01407 ety_idx, field_id);
01408 for (INT j=last_nfield; j < VHO_Struct_Nfields; ++j) {
01409 VHO_Struct_Field_Is_Array_Table [j] = TRUE;
01410 VHO_Struct_Field_Id_Table [j] = field_id;
01411 }
01412 }
01413 else {
01414 VHO_Struct_Field_Is_Array_Table [VHO_Struct_Nfields] = TRUE;
01415 VHO_Struct_Field_Id_Table [VHO_Struct_Nfields] = field_id;
01416 VHO_Struct_Offset_Table [VHO_Struct_Nfields] = field_offset + i*TY_size(Ty_Table [ety_idx]);
01417 VHO_Struct_Fld_Table [VHO_Struct_Nfields++] = ety_idx;
01418 }
01419 }
01420 VHO_Struct_Last_Field_Offset = field_offset;
01421 VHO_Struct_Last_Field_Size = TY_size(Ty_Table [fty_idx]);
01422 }
01423 } else if ( field_offset + TY_size (Ty_Table [fty_idx])
01424 > VHO_Struct_Last_Field_Offset + VHO_Struct_Last_Field_Size ) {
01425 VHO_Struct_Can_Be_Lowered = FALSE;
01426 }
01427 }
01428 else {
01429 for(int i=0; i<array_elem_num; i++) {
01430 if (TY_kind(ety_idx) == KIND_STRUCT) {
01431 INT last_nfield = VHO_Struct_Nfields;
01432
01433 VHO_Get_Field_List (field_offset + i*TY_size(ety_idx),
01434 ety_idx, field_id);
01435 for (INT j=last_nfield; j < VHO_Struct_Nfields; ++j) {
01436 VHO_Struct_Field_Is_Array_Table [j] = TRUE;
01437 VHO_Struct_Field_Id_Table [j] = field_id;
01438 }
01439 }
01440 else {
01441 VHO_Struct_Field_Is_Array_Table [VHO_Struct_Nfields] = TRUE;
01442 VHO_Struct_Field_Id_Table [VHO_Struct_Nfields] = field_id;
01443 VHO_Struct_Offset_Table [VHO_Struct_Nfields] = field_offset + i*TY_size(Ty_Table [ety_idx]);
01444 VHO_Struct_Fld_Table [VHO_Struct_Nfields++] = ety_idx;
01445 }
01446 }
01447 VHO_Struct_Last_Field_Offset = field_offset;
01448 VHO_Struct_Last_Field_Size = TY_size(Ty_Table [fty_idx]);
01449 }
01450 break;
01451
01452 default:
01453
01454 VHO_Struct_Can_Be_Lowered = FALSE;
01455 break;
01456 }
01457
01458 if (FLD_last_field (fld))
01459 break;
01460 else
01461 ++fld_iter;
01462 }
01463 return field_id;
01464
01465 }
01466
01467 #ifdef KEY
01468
01469
01470
01471 static INT
01472 single_field_in_struct (TY_IDX struct_type)
01473 {
01474 Is_True (TY_kind(struct_type) == KIND_STRUCT,
01475 ("single_field_in_struct: expected struct type"));
01476
01477 Is_True (TY_size(struct_type) == 4 || TY_size(struct_type) == 8,
01478 ("single_field_in_struct: sizes 4/8 only supported"));
01479 FLD_ITER fld_iter = Make_fld_iter (TY_fld (struct_type));
01480 INT fld_count = 0;
01481
01482 do {
01483 FLD_HANDLE fld(fld_iter);
01484 fld_count++;
01485 if (! FLD_is_bit_field(fld) &&
01486 TY_size (FLD_type (fld)) == TY_size (struct_type))
01487 return fld_count;
01488
01489
01490 else if (TY_size (FLD_type (fld)))
01491 return 0;
01492 } while (!FLD_last_field(fld_iter++));
01493
01494 return 0;
01495 }
01496 #endif
01497
01498 static TY_IDX
01499 get_field_type (TY_IDX struct_type, UINT field_id)
01500 {
01501 Is_True (TY_kind (struct_type) == KIND_STRUCT, ("expecting KIND_STRUCT"));
01502 UINT cur_field_id = 0;
01503 FLD_HANDLE fld = FLD_get_to_field (struct_type, field_id, cur_field_id);
01504 Is_True (! fld.Is_Null(), ("Invalid field id %d for type 0x%x",
01505 field_id, struct_type));
01506 return FLD_type (fld);
01507 }
01508
01509
01510
01511
01512
01513
01514
01515
01516
01517
01518
01519
01520
01521
01522
01523
01524
01525
01526
01527
01528 WN *
01529 VHO_Lower_Mstore ( WN * wn )
01530 {
01531 WN_OFFSET dst_offset;
01532 WN * dst_address;
01533 TY_IDX ptr_dst_ty_idx;
01534 TY_IDX dst_ty_idx;
01535 ST * dst_st = NULL;
01536 WN * src_value;
01537 WN_OFFSET src_offset;
01538 WN * src_address;
01539 TY_IDX ptr_src_ty_idx;
01540 TY_IDX src_ty_idx;
01541 ST * src_st;
01542 WN * size;
01543 INT64 bytes;
01544 WN * block;
01545
01546 INT32 i;
01547 SRCPOS srcpos;
01548 WN * temp;
01549 PREG_NUM preg;
01550 ST * preg_st;
01551 TY_IDX preg_ty_idx;
01552 OPCODE opc;
01553
01554 src_value = WN_kid0(wn);
01555 dst_address = WN_kid1(wn);
01556 size = WN_kid(wn,2);
01557 dst_offset = WN_store_offset(wn);
01558 ptr_dst_ty_idx = WN_ty(wn);
01559 srcpos = WN_Get_Linenum(wn);
01560
01561 if ( VHO_Struct_Opt
01562 && WN_operator(size) == OPR_INTCONST
01563 && WN_opcode(src_value) == OPC_MLOAD ) {
01564
01565
01566
01567 bytes = WN_const_val(size);
01568 src_address = WN_kid0(src_value);
01569 ptr_src_ty_idx = WN_ty(src_value);
01570 src_ty_idx = TY_pointed(Ty_Table[ptr_src_ty_idx]);
01571 if (WN_field_id(src_value) != 0) {
01572 src_ty_idx = get_field_type(src_ty_idx, WN_field_id(src_value));
01573 }
01574
01575 dst_ty_idx = TY_pointed(Ty_Table[ptr_dst_ty_idx]);
01576 if (WN_field_id(wn) != 0) {
01577 dst_ty_idx = get_field_type(dst_ty_idx, WN_field_id(wn));
01578 }
01579
01580
01581
01582
01583
01584 if (TY_kind(src_ty_idx) == KIND_STRUCT
01585 && TY_is_packed(Ty_Table[src_ty_idx]) == FALSE
01586 && TY_is_packed(Ty_Table[dst_ty_idx]) == FALSE
01587 && bytes / TY_align(src_ty_idx) <= VHO_Struct_Limit ) {
01588
01589 VHO_Struct_Nfields = 0;
01590 VHO_Struct_Can_Be_Lowered = TRUE;
01591
01592
01593
01594 VHO_Get_Field_List ( 0, src_ty_idx, WN_field_id(src_value) );
01595
01596 #ifdef VHO_DEBUG
01597 if ( VHO_Struct_Debug )
01598 fprintf ( TFile, "VHO_Lower_Mstore : %s %d\n",
01599 VHO_Struct_Can_Be_Lowered ? "TRUE" : "FALSE",
01600 (INT32) srcpos );
01601 #endif
01602
01603 if ( VHO_Struct_Can_Be_Lowered && VHO_Struct_Nfields ) {
01604
01605 block = WN_CreateBlock ();
01606 WN_Set_Linenum ( block, srcpos );
01607
01608 src_offset = WN_offset(src_value);
01609
01610 if ( WN_operator(src_address) == OPR_LDA &&
01611 WN_field_id(src_value) != 0 ) {
01612
01613 src_st = WN_st(src_address);
01614 src_offset += WN_offset(src_address);
01615 } else src_st = NULL;
01616
01617
01618
01619
01620
01621
01622
01623
01624
01625
01626
01627
01628
01629
01630
01631
01632
01633
01634
01635
01636
01637
01638
01639
01640
01641
01642
01643
01644
01645
01646
01647
01648
01649
01650
01651
01652
01653 dst_offset = WN_store_offset(wn);
01654
01655 if ( WN_operator(dst_address) == OPR_LDA && WN_field_id(wn) == 0) {
01656
01657 dst_st = WN_st(dst_address);
01658 dst_offset += WN_offset(dst_address);
01659 }
01660 else dst_st = NULL;
01661
01662
01663
01664
01665
01666
01667
01668
01669
01670
01671
01672
01673
01674
01675
01676
01677
01678
01679
01680
01681
01682
01683
01684
01685
01686
01687
01688
01689
01690
01691
01692
01693
01694
01695
01696
01697
01698
01699
01700
01701
01702 for ( i = 0; i < VHO_Struct_Nfields; i++ ) {
01703
01704 TY_IDX fty_idx;
01705 WN * src;
01706 WN * dst;
01707
01708 fty_idx = VHO_Struct_Fld_Table [i];
01709 if ( src_st ) {
01710 opc = OPCODE_make_op ( OPR_LDID,
01711 Promoted_Mtype [TY_mtype(fty_idx)],
01712 TY_mtype(fty_idx) );
01713 src = WN_CreateLdid ( opc, src_offset + VHO_Struct_Offset_Table[i],
01714 src_st, fty_idx );
01715 }
01716 else {
01717 opc = OPCODE_make_op ( OPR_ILOAD,
01718 Promoted_Mtype [TY_mtype(fty_idx)],
01719 TY_mtype(fty_idx) );
01720 src = WN_CreateIload ( opc, src_offset + VHO_Struct_Offset_Table[i], fty_idx,
01721 Make_Pointer_Type ( fty_idx, FALSE ),
01722 WN_COPY_Tree ( src_address ) );
01723 }
01724 if ( dst_st ) {
01725 opc = OPCODE_make_op ( OPR_STID, MTYPE_V, TY_mtype(fty_idx) );
01726 dst = WN_CreateStid ( opc, dst_offset + VHO_Struct_Offset_Table[i],
01727 dst_st, fty_idx, src );
01728 }
01729 else {
01730 opc = OPCODE_make_op ( OPR_ISTORE, MTYPE_V, TY_mtype(fty_idx) );
01731 dst = WN_CreateIstore ( opc, dst_offset + VHO_Struct_Offset_Table[i],
01732 Make_Pointer_Type ( fty_idx, FALSE ),
01733 src,
01734 WN_COPY_Tree ( dst_address ) );
01735 }
01736 WN_Set_Linenum(dst, srcpos);
01737 WN_INSERT_BlockAfter ( block, WN_last(block), dst );
01738
01739 }
01740 wn = block;
01741 }
01742 }
01743
01744 else {
01745 #ifdef VHO_DEBUG
01746 if ( VHO_Struct_Debug )
01747 fprintf ( TFile, "VHO_Lower_Mstore : FALSE %d\n", (INT32) srcpos );
01748 #endif
01749 }
01750 }
01751 return wn;
01752 }
01753
01754 inline BOOL Is_Ldid_Or_Lda (WN *tree)
01755 {
01756 return (WN_operator(tree) == OPR_LDID || WN_operator(tree) == OPR_LDA);
01757 }
01758
01759 inline BOOL Is_Multiply_Or_Cvt_Multiply (WN *tree)
01760 {
01761 return ((WN_operator(tree) == OPR_MPY)
01762 || (WN_operator(tree) == OPR_CVT && WN_operator(WN_kid0(tree)) == OPR_MPY));
01763 }
01764
01765
01766 static WN*
01767 Find_Ldid_Under_Iload (WN *iload_kid)
01768 {
01769 if (Is_Ldid_Or_Lda(iload_kid)) {
01770 return iload_kid;
01771 }
01772 else if (WN_operator(iload_kid) == OPR_ADD) {
01773 if (Is_Ldid_Or_Lda(WN_kid0(iload_kid))
01774 && Is_Multiply_Or_Cvt_Multiply(WN_kid1(iload_kid)) )
01775 {
01776
01777 return WN_kid0(iload_kid);
01778 }
01779
01780 else if (Is_Ldid_Or_Lda(WN_kid1(iload_kid))
01781 && Is_Multiply_Or_Cvt_Multiply(WN_kid0(iload_kid)) )
01782 {
01783
01784 return WN_kid1(iload_kid);
01785 }
01786 }
01787 else if (WN_operator(iload_kid) == OPR_ARRAY) {
01788
01789 return Find_Ldid_Under_Iload (WN_kid0(iload_kid));
01790 }
01791 return NULL;
01792 }
01793
01794 static TY_IDX
01795 Is_MM_load(WN *src, WN *dst)
01796 {
01797 if (WN_opcode(src) == OPC_MMLDID) {
01798 if (ST_class(WN_st(dst)) != CLASS_PREG &&
01799 ST_class(WN_st(src)) != CLASS_PREG)
01800 return WN_ty(src);
01801 else
01802 return (TY_IDX)0;
01803 }
01804 if (WN_opcode(src) == OPC_MMILOAD) {
01805 if (OPCODE_is_load(WN_opcode(WN_kid0(src))))
01806 return WN_ty(WN_kid0(src));
01807 }
01808 return (TY_IDX)0;
01809 }
01810
01811
01812
01813
01814
01815
01816
01817
01818
01819
01820
01821
01822
01823
01824
01825
01826
01827
01828
01829
01830 WN *
01831 VHO_Lower_Mstid (WN * wn)
01832 {
01833 WN_OFFSET dst_offset;
01834 TY_IDX dst_ty_idx;
01835 ST * dst_st;
01836 WN * src_value;
01837 WN * src_iload_kid;
01838 WN * src_ldid;
01839 WN_OFFSET src_offset;
01840 TY_IDX src_ty_idx;
01841 TY_IDX orig_src_ty_idx;
01842 TY_IDX src_ptr_ty_idx;
01843 ST * src_st;
01844 WN * size;
01845 INT64 bytes;
01846 WN * block;
01847
01848 INT32 i;
01849 SRCPOS srcpos;
01850 OPCODE opc;
01851 BOOL src_is_pointer = FALSE;
01852 INT src_field_id = 0;
01853 INT dst_field_id = 0;
01854
01855 src_value = WN_kid0(wn);
01856 dst_ty_idx = WN_ty(wn);
01857 srcpos = WN_Get_Linenum(wn);
01858
01859
01860
01861
01862
01863
01864 if (WN_field_id(wn) != 0) {
01865 dst_field_id = WN_field_id(wn);
01866 dst_ty_idx = get_field_type(dst_ty_idx, WN_field_id(wn));
01867 }
01868 if (WN_opcode(src_value) == OPC_MMLDID) {
01869 src_ldid = src_value;
01870 src_ty_idx = WN_ty(src_ldid);
01871 }
01872 else if (WN_opcode(src_value) == OPC_MMILOAD)
01873 {
01874
01875 src_iload_kid = WN_kid0(src_value);
01876
01877 src_is_pointer = TRUE;
01878 src_ptr_ty_idx = WN_load_addr_ty(src_value);
01879
01880 if (TY_kind(src_ptr_ty_idx) != KIND_POINTER) {
01881 return wn;
01882 }
01883 src_ty_idx = TY_pointed(src_ptr_ty_idx);
01884 src_ldid = Find_Ldid_Under_Iload (src_iload_kid);
01885
01886 if (src_ldid == NULL)
01887 return wn;
01888 }
01889 else
01890 {
01891 return wn;
01892 }
01893
01894
01895 orig_src_ty_idx = src_ty_idx;
01896
01897 if (WN_field_id(src_value) != 0) {
01898 src_field_id = WN_field_id(src_value);
01899 src_ty_idx = get_field_type(src_ty_idx, src_field_id);
01900 }
01901
01902 if ( ST_class(WN_st(wn)) == CLASS_PREG ||
01903 (ST_class(WN_st(src_ldid)) == CLASS_PREG && !src_is_pointer)) {
01904
01905 return wn;
01906 }
01907
01908 bytes = TY_size(dst_ty_idx);
01909
01910 #if defined(TARG_NVISA)
01911 if ((VHO_Struct_Opt && (bytes > 0))) {
01912 #else
01913 if ((VHO_Struct_Opt && (bytes > 0)) && (Is_MM_load(src_value, wn) != (TY_IDX)0)) {
01914
01915 #endif
01916
01917 #ifdef KEY
01918 VHO_Struct_Nfields = 0;
01919 VHO_Struct_Can_Be_Lowered = TRUE;
01920 #endif
01921
01922
01923
01924
01925
01926 if (TY_kind(src_ty_idx) == KIND_STRUCT
01927 && TY_is_packed(Ty_Table[src_ty_idx]) == FALSE
01928 && TY_is_packed(Ty_Table[dst_ty_idx]) == FALSE
01929 && bytes / TY_align(src_ty_idx) <= VHO_Struct_Limit) {
01930
01931 #ifndef KEY
01932 VHO_Struct_Nfields = 0;
01933 VHO_Struct_Can_Be_Lowered = TRUE;
01934 #endif
01935
01936
01937
01938
01939
01940
01941 VHO_Get_Field_List (0, src_ty_idx, src_field_id);
01942
01943 #ifdef VHO_DEBUG
01944 if ( VHO_Struct_Debug)
01945 fprintf ( TFile, "VHO_Lower_Mstid : %s %d \n",
01946 VHO_Struct_Can_Be_Lowered ? "TRUE" : "FALSE",
01947 (INT32) srcpos);
01948 #endif
01949
01950 if ( VHO_Struct_Can_Be_Lowered && VHO_Struct_Nfields) {
01951
01952 block = WN_CreateBlock();
01953 WN_Set_Linenum (block, srcpos);
01954 src_st = WN_st(src_ldid);
01955
01956 src_offset = WN_offset(src_value);
01957 dst_st = WN_st(wn);
01958 dst_offset = WN_store_offset(wn);
01959
01960
01961
01962 for (i = 0; i < VHO_Struct_Nfields; i++) {
01963
01964 TY_IDX fty_idx;
01965 WN * src;
01966 WN * dst;
01967
01968 fty_idx = VHO_Struct_Fld_Table[i];
01969 if (src_is_pointer) {
01970 opc = OPCODE_make_op ( OPR_ILOAD,
01971 Promoted_Mtype [TY_mtype(fty_idx)],
01972 TY_mtype(fty_idx) );
01973 if (VHO_Struct_Field_Is_Array_Table[i]) {
01974 src = WN_CreateIload ( opc,
01975 src_offset + VHO_Struct_Offset_Table[i],
01976 fty_idx,
01977 Make_Pointer_Type ( fty_idx),
01978 WN_COPY_Tree (src_iload_kid) );
01979 } else {
01980 src = WN_CreateIload ( opc,
01981 src_offset + VHO_Struct_Offset_Table[i],
01982 orig_src_ty_idx, src_ptr_ty_idx,
01983 WN_COPY_Tree (src_iload_kid),
01984 VHO_Struct_Field_Id_Table[i]);
01985 }
01986 } else {
01987 opc = OPCODE_make_op ( OPR_LDID,
01988 Promoted_Mtype [TY_mtype(fty_idx)],
01989 TY_mtype(fty_idx) );
01990 if (VHO_Struct_Field_Is_Array_Table[i]) {
01991
01992
01993 src = WN_CreateLdid ( opc,
01994 src_offset + VHO_Struct_Offset_Table[i],
01995 src_st, fty_idx);
01996 } else {
01997 src = WN_CreateLdid ( opc,
01998 src_offset + VHO_Struct_Offset_Table[i],
01999 src_st, WN_ty(src_ldid),
02000 VHO_Struct_Field_Id_Table[i]);
02001 }
02002 }
02003 opc = OPCODE_make_op ( OPR_STID, MTYPE_V, TY_mtype(fty_idx) );
02004 if (VHO_Struct_Field_Is_Array_Table[i]) {
02005
02006
02007 dst = WN_CreateStid ( opc,
02008 dst_offset + VHO_Struct_Offset_Table[i],
02009 dst_st, fty_idx, src);
02010 } else {
02011 dst = WN_CreateStid ( opc,
02012 dst_offset + VHO_Struct_Offset_Table[i],
02013 dst_st, WN_ty(wn), src,
02014 dst_field_id - src_field_id + VHO_Struct_Field_Id_Table[i]);
02015 }
02016 WN_Set_Linenum(dst, srcpos);
02017 WN_INSERT_BlockAfter (block, WN_last(block), dst);
02018
02019 }
02020 wn = block;
02021 }
02022 }
02023 #ifdef KEY
02024 if (VHO_Struct_Can_Be_Lowered && VHO_Struct_Nfields)
02025 ;
02026 #ifdef TARG_SL
02027 else if ((bytes == 4) && TY_size(src_ty_idx) == bytes) {
02028 #else
02029 else if ((bytes == 4 || bytes == 8) && TY_size(src_ty_idx) == bytes) {
02030 #endif
02031
02032 TYPE_ID mtype = (bytes == 4) ? MTYPE_U4 : MTYPE_U8;
02033 WN_set_desc(wn, mtype);
02034 WN_set_rtype(src_value, mtype);
02035 WN_set_desc(src_value, mtype);
02036
02037
02038 INT field_id;
02039
02040
02041 if ((TY_kind(src_ty_idx) == KIND_STRUCT) &&
02042 (field_id = single_field_in_struct (src_ty_idx)))
02043 WN_set_field_id (src_value, field_id);
02044
02045
02046
02047 if ((TY_kind(dst_ty_idx) == KIND_STRUCT) &&
02048 (field_id = single_field_in_struct (dst_ty_idx)))
02049 WN_set_field_id (wn, field_id);
02050 }
02051 else {
02052 #endif
02053
02054 #ifdef VHO_DEBUG
02055 if ( VHO_Struct_Debug)
02056 fprintf (TFile, "VHO_Lower_Mstid: FALSE %d\n", (INT32) scrpos);
02057 #endif
02058 }
02059 }
02060 return wn;
02061 }
02062
02063
02064
02065
02066
02067
02068
02069
02070
02071
02072
02073
02074
02075
02076
02077
02078
02079
02080
02081
02082 WN *
02083 VHO_Lower_Mistore ( WN * wn )
02084 {
02085 WN_OFFSET dst_offset;
02086 TY_IDX dst_ty_idx;
02087 ST * dst_st;
02088 WN * src_value;
02089 WN_OFFSET src_offset;
02090 TY_IDX src_ty_idx;
02091 ST * src_st;
02092 WN * size;
02093 INT64 bytes;
02094 WN * block;
02095
02096 INT32 i;
02097 SRCPOS srcpos;
02098 OPCODE opc;
02099 INT src_field_id = 0;
02100 INT dst_field_id = 0;
02101 BOOL src_is_pointer = FALSE;
02102 TY_IDX src_ptr_ty_idx;
02103 WN *src_iload_kid;
02104 WN *src_ldid;
02105
02106 src_value = WN_kid0(wn);
02107 WN *dst_address= WN_kid1(wn);
02108 dst_offset = WN_store_offset(wn);
02109 TY_IDX ptr_dst_ty_idx = WN_ty(wn);
02110 dst_ty_idx = TY_pointed(Ty_Table[ptr_dst_ty_idx]);
02111 if (WN_field_id(wn) != 0) {
02112 dst_ty_idx = get_field_type(dst_ty_idx, WN_field_id(wn));
02113 }
02114 srcpos = WN_Get_Linenum(wn);
02115 bytes = TY_size(dst_ty_idx);
02116
02117 if (WN_field_id(src_value) != 0) {
02118
02119 return wn;
02120 }
02121 if ( VHO_Struct_Opt
02122 && bytes > 0) {
02123 if (WN_opcode(src_value) == OPC_MMLDID
02124 && ST_class(WN_st(src_value)) != CLASS_PREG ) {
02125
02126 src_ty_idx = WN_ty(src_value);
02127 src_ldid = src_value;
02128 }
02129 else if (WN_opcode(src_value) == OPC_MMILOAD) {
02130
02131 src_is_pointer = TRUE;
02132 src_ptr_ty_idx = WN_load_addr_ty(src_value);
02133 if (TY_kind(src_ptr_ty_idx) != KIND_POINTER) {
02134 return wn;
02135 }
02136 src_ty_idx = TY_pointed(src_ptr_ty_idx);
02137 src_iload_kid = WN_kid0(src_value);
02138 src_ldid = Find_Ldid_Under_Iload (src_iload_kid);
02139 if (src_ldid == NULL)
02140 return wn;
02141 }
02142 else {
02143 return wn;
02144 }
02145
02146
02147
02148
02149
02150 if (TY_kind(src_ty_idx) == KIND_STRUCT
02151 && TY_is_packed(Ty_Table[src_ty_idx]) == FALSE
02152 && TY_is_packed(Ty_Table[dst_ty_idx]) == FALSE
02153 && bytes / TY_align(src_ty_idx) <= VHO_Struct_Limit ) {
02154
02155 VHO_Struct_Nfields = 0;
02156 VHO_Struct_Can_Be_Lowered = TRUE;
02157
02158
02159 VHO_Get_Field_List ( 0, src_ty_idx, WN_field_id(src_value) );
02160
02161 #ifdef VHO_DEBUG
02162 if ( VHO_Struct_Debug )
02163 fprintf ( TFile, "VHO_Lower_Mistore : %s %d\n",
02164 VHO_Struct_Can_Be_Lowered ? "TRUE" : "FALSE",
02165 (INT32) srcpos );
02166 #endif
02167
02168 if ( VHO_Struct_Can_Be_Lowered && VHO_Struct_Nfields ) {
02169
02170 block = WN_CreateBlock ();
02171 WN_Set_Linenum ( block, srcpos );
02172 src_st = WN_st(src_ldid);
02173
02174
02175 src_offset = WN_offset(src_value);
02176
02177 for ( i = 0; i < VHO_Struct_Nfields; i++ ) {
02178
02179 TY_IDX fty_idx;
02180 WN * src;
02181 WN * dst;
02182
02183 fty_idx = VHO_Struct_Fld_Table [i];
02184
02185 if (src_is_pointer) {
02186 opc = OPCODE_make_op ( OPR_ILOAD,
02187 Promoted_Mtype [TY_mtype(fty_idx)],
02188 TY_mtype(fty_idx) );
02189 if (VHO_Struct_Field_Is_Array_Table[i]) {
02190 src = WN_CreateIload ( opc,
02191 src_offset + VHO_Struct_Offset_Table[i],
02192 fty_idx,
02193 Make_Pointer_Type ( fty_idx),
02194 WN_COPY_Tree (src_iload_kid) );
02195 } else {
02196 src = WN_CreateIload ( opc,
02197 src_offset + VHO_Struct_Offset_Table[i],
02198 src_ty_idx, src_ptr_ty_idx,
02199 WN_COPY_Tree (src_iload_kid),
02200 VHO_Struct_Field_Id_Table[i]);
02201 }
02202 }
02203 else {
02204 opc = OPCODE_make_op ( OPR_LDID,
02205 Promoted_Mtype [TY_mtype(fty_idx)],
02206 TY_mtype(fty_idx) );
02207 if (VHO_Struct_Field_Is_Array_Table[i]) {
02208
02209
02210 src = WN_CreateLdid ( opc,
02211 src_offset + VHO_Struct_Offset_Table[i],
02212 src_st, fty_idx );
02213 } else {
02214 src = WN_CreateLdid ( opc,
02215 src_offset + VHO_Struct_Offset_Table[i],
02216 src_st, src_ty_idx, VHO_Struct_Field_Id_Table[i]);
02217 }
02218 }
02219 opc = OPCODE_make_op ( OPR_ISTORE, MTYPE_V, TY_mtype(fty_idx));
02220 if (VHO_Struct_Field_Is_Array_Table[i]) {
02221 dst = WN_CreateIstore ( opc,
02222 dst_offset + VHO_Struct_Offset_Table[i],
02223 Make_Pointer_Type( fty_idx),
02224 src, WN_COPY_Tree( dst_address ));
02225 } else {
02226 dst = WN_CreateIstore ( opc,
02227 dst_offset + VHO_Struct_Offset_Table[i],
02228 ptr_dst_ty_idx,
02229 src, WN_COPY_Tree( dst_address ),
02230 dst_field_id - src_field_id + VHO_Struct_Field_Id_Table[i]);
02231 }
02232 WN_Set_Linenum(dst, srcpos);
02233
02234 WN_INSERT_BlockAfter ( block, WN_last(block), dst );
02235
02236 }
02237 wn = block;
02238 }
02239 }
02240 else {
02241 #ifdef VHO_DEBUG
02242 if ( VHO_Struct_Debug )
02243 fprintf ( TFile, "VHO_Lower_Mstid : FALSE %d\n", (INT32) srcpos );
02244 #endif
02245 }
02246 }
02247
02248 return wn;
02249 }
02250
02251 static void
02252 vho_lower_set_st_addr_info ( WN * wn, ADDRESS_INFO_TYPE code )
02253 {
02254 OPCODE opc;
02255 OPERATOR wn_operator;
02256 ST * st;
02257
02258 opc = WN_opcode(wn);
02259 wn_operator = OPCODE_operator(opc);
02260
02261 switch ( wn_operator ) {
02262
02263 case OPR_LDA:
02264
02265 st = WN_st(wn);
02266 if ( ST_class(st) == CLASS_VAR || ST_class(st) == CLASS_FUNC ) {
02267
02268 if ( code == ADDRESS_PASSED ) {
02269
02270 if ( WHIRL_Addr_Passed_On ) {
02271 Set_ST_addr_taken_passed(st);
02272
02273 if ( WHIRL_Addr_Saved_For_Passed_On )
02274 Set_ST_addr_taken_saved(st);
02275 }
02276 }
02277
02278 else
02279 Set_ST_addr_taken_saved(st);
02280 }
02281 break;
02282
02283 case OPR_ARRAY:
02284
02285 vho_lower_set_st_addr_info ( WN_kid0(wn), code );
02286 break;
02287
02288 case OPR_LDID:
02289
02290
02291
02292
02293
02294
02295
02296
02297
02298
02299 case OPR_CONST:
02300 case OPR_ILOAD:
02301 case OPR_MLOAD:
02302 case OPR_INTCONST:
02303 case OPR_INTRINSIC_OP:
02304 case OPR_CALL:
02305 case OPR_EQ:
02306 case OPR_NE:
02307 case OPR_GT:
02308 case OPR_GE:
02309 case OPR_LT:
02310 case OPR_LE:
02311 break;
02312
02313 case OPR_EVAL:
02314 case OPR_TAS:
02315 case OPR_CVT:
02316 case OPR_CVTL:
02317 case OPR_NEG:
02318 case OPR_ABS:
02319 case OPR_SQRT:
02320 case OPR_REALPART:
02321 case OPR_IMAGPART:
02322 case OPR_PAREN:
02323 case OPR_RND:
02324 case OPR_TRUNC:
02325 case OPR_CEIL:
02326 case OPR_FLOOR:
02327 case OPR_BNOT:
02328 case OPR_LNOT:
02329 case OPR_DIVPART:
02330 case OPR_REMPART:
02331 case OPR_MINPART:
02332 case OPR_MAXPART:
02333 case OPR_RECIP:
02334 case OPR_RSQRT:
02335 case OPR_PARM:
02336
02337 vho_lower_set_st_addr_info ( WN_kid0(wn), code );
02338 break;
02339
02340 case OPR_SELECT:
02341 case OPR_CSELECT:
02342 case OPR_ADD:
02343 case OPR_SUB:
02344 case OPR_MPY:
02345 case OPR_DIV:
02346 case OPR_MOD:
02347 case OPR_REM:
02348 case OPR_DIVREM:
02349 case OPR_MAX:
02350 case OPR_MIN:
02351 case OPR_MINMAX:
02352 case OPR_BAND:
02353 case OPR_BIOR:
02354 case OPR_BXOR:
02355 case OPR_BNOR:
02356 case OPR_LAND:
02357 case OPR_LIOR:
02358 case OPR_SHL:
02359 case OPR_ASHR:
02360 case OPR_LSHR:
02361 case OPR_COMPLEX:
02362 case OPR_HIGHMPY:
02363 #ifdef KEY
02364 case OPR_COMPOSE_BITS:
02365 #endif
02366
02367 vho_lower_set_st_addr_info ( WN_kid0(wn), code );
02368 vho_lower_set_st_addr_info ( WN_kid1(wn), code );
02369 break;
02370
02371 case OPR_CAND:
02372 case OPR_CIOR:
02373
02374 break;
02375
02376 case OPR_COMMA:
02377
02378 vho_lower_set_st_addr_info ( WN_kid1(wn), code );
02379 break;
02380
02381 case OPR_RCOMMA:
02382
02383 vho_lower_set_st_addr_info ( WN_kid0(wn), code );
02384 break;
02385
02386 default:
02387
02388 FmtAssert ( TRUE,
02389 ("vho_lower_set_st_addr_info not implemented") );
02390 }
02391 }
02392
02393
02394 static void
02395 vho_initialize_bool_info ( BOOL_INFO * bool_info )
02396 {
02397 bool_info->opcode = OPCODE_UNKNOWN;
02398 bool_info->used_true_label = FALSE;
02399 bool_info->used_false_label = FALSE;
02400 bool_info->true_label = 0;
02401 bool_info->false_label = 0;
02402 }
02403
02404
02405 static WN *
02406 vho_lower_comma ( WN * wn, WN *block, BOOL_INFO * bool_info, BOOL is_return=FALSE)
02407 {
02408 WN * comma_block;
02409 WN * result_block;
02410 WN * result;
02411 WN * first;
02412 WN * value;
02413 WN * stmt;
02414 WN * prev_call;
02415 PREG_NUM preg;
02416 BOOL call;
02417
02418 result = WN_kid1 (wn);
02419 if( PU_cxx_lang (Get_Current_PU()) && WN_operator(WN_last(WN_kid0(wn))) == OPR_STID)
02420 prev_call = WN_kid0(WN_last(WN_kid0(wn)));
02421 else
02422 prev_call = NULL;
02423 call = WHIRL_Return_Val_On
02424 && WN_operator(result) == OPR_LDID
02425 && WN_st(result) == Return_Val_Preg;
02426
02427 if ( PU_cxx_lang (Get_Current_PU())&&
02428 prev_call &&
02429 WN_operator(prev_call) == OPR_LDID &&
02430 (WN_st(prev_call) == Return_Val_Preg || is_return)&&
02431 WN_rtype(prev_call) == MTYPE_M &&
02432 WN_rtype(wn) == MTYPE_M){
02433 WN_Set_Linenum ( block, VHO_Srcpos );
02434 WN * next_wn;
02435
02436 for ( wn = WN_first( WN_kid0(wn)); wn; wn = next_wn ) {
02437 next_wn = WN_next(wn);
02438 if (!next_wn) {
02439 result = vho_lower_expr (WN_kid0(wn), block, bool_info);
02440 break;
02441 }
02442 wn = vho_lower ( wn, block );
02443 if ( wn )
02444 WN_INSERT_BlockLast ( block, wn );
02445 }
02446 return result;
02447 }
02448
02449 comma_block = vho_lower_block (WN_kid0(wn));
02450 WN_Set_Linenum ( comma_block, VHO_Srcpos );
02451 first = WN_first(comma_block);
02452
02453 result_block = WN_CreateBlock ();
02454 result = vho_lower_expr (WN_kid1(wn), result_block, bool_info);
02455
02456 if ( VHO_Call_Opt
02457 && first
02458 && WN_first(result_block) == NULL
02459 && WN_operator(first) == OPR_PRAGMA
02460 && WN_pragma(first) == WN_PRAGMA_INLINE_BODY_START ) {
02461
02462
02463
02464
02465 value = NULL;
02466 preg = 0;
02467
02468 stmt = WN_next(first);
02469
02470 for (;;) {
02471
02472
02473
02474
02475 if ( WN_operator(stmt) == OPR_STID
02476 && ST_class(WN_st(stmt)) == CLASS_PREG ) {
02477
02478 if ( value == NULL )
02479 value = WN_kid0(stmt);
02480
02481 else
02482 if ( WN_operator(WN_kid0(stmt)) == OPR_LDID
02483 && ST_class(WN_st(WN_kid0(stmt))) == CLASS_PREG
02484 && WN_load_offset(WN_kid0(stmt)) == preg ) {
02485 }
02486
02487 else
02488 break;
02489
02490 preg = WN_store_offset(stmt);
02491
02492
02493
02494 }
02495
02496 else
02497 if ( WN_operator(stmt) == OPR_PRAGMA
02498 && WN_pragma(stmt) == WN_PRAGMA_INLINE_BODY_END ) {
02499
02500 stmt = WN_next(stmt);
02501
02502
02503
02504
02505
02506
02507
02508 if ( stmt
02509 && WN_next(stmt) == NULL
02510 && WN_operator(stmt) == OPR_STID
02511 && ST_class(WN_st(stmt)) == CLASS_PREG ) {
02512
02513 if ( value == NULL )
02514 value = WN_kid0(stmt);
02515
02516 else
02517 if ( WN_operator(WN_kid0(stmt)) == OPR_LDID
02518 && ST_class(WN_st(WN_kid0(stmt))) == CLASS_PREG
02519 && WN_load_offset(WN_kid0(stmt)) == preg ) {
02520 }
02521
02522 else
02523 break;
02524 }
02525
02526 else
02527 break;
02528
02529 preg = WN_store_offset(stmt);
02530
02531
02532
02533
02534
02535
02536 if ( value
02537 && WN_operator(result) == OPR_LDID
02538 && ST_class(WN_st(result)) == CLASS_PREG
02539 && WN_load_offset(result) == preg ) {
02540
02541 comma_block = NULL;
02542 result = WN_Simplify_Tree ( value );
02543
02544
02545
02546
02547
02548
02549 }
02550
02551 break;
02552 }
02553
02554 else
02555 break;
02556
02557 stmt = WN_next(stmt);
02558 }
02559 }
02560
02561 if ( comma_block ) {
02562
02563 if (call) {
02564
02565 TYPE_ID rtype = WN_rtype (result);
02566 TYPE_ID desc = WN_desc (result);
02567 TY_IDX ty_idx = WN_ty (result);
02568
02569 if (desc == MTYPE_M) {
02570
02571 ST* st = Gen_Temp_Symbol (ty_idx, ".call");
02572 wn = WN_CreateStid (OPC_MSTID, 0, st, ty_idx, result);
02573 WN_Set_Linenum ( wn, VHO_Srcpos );
02574 WN_INSERT_BlockLast (comma_block, wn);
02575 result = WN_CreateLdid (OPC_MMLDID, 0, st, ty_idx);
02576 }
02577 #ifdef TARG_X8664
02578 else if (MTYPE_is_complex(desc) ||
02579 MTYPE_is_mmx_vector(desc)) {
02580 ST* st = Gen_Temp_Symbol (ty_idx, ".call");
02581 wn = WN_CreateStid (OPR_STID, MTYPE_V, desc, 0, st, ty_idx, result);
02582 WN_Set_Linenum ( wn, VHO_Srcpos );
02583 WN_INSERT_BlockLast (comma_block, wn);
02584 result = WN_CreateLdid (OPR_LDID, desc, desc, 0, st, ty_idx);
02585 }
02586 #endif
02587
02588 else {
02589
02590 #ifdef KEY
02591 if (VHO_In_MP_Region_Pragma)
02592 {
02593 ST * comma_st = Gen_Temp_Symbol (MTYPE_TO_TY_array[rtype], "_comma");
02594 wn = WN_Stid (rtype, 0, comma_st, ty_idx, result);
02595 WN_Set_Linenum ( wn, VHO_Srcpos );
02596 WN_INSERT_BlockLast (comma_block, wn);
02597 result = WN_Ldid (rtype, 0, comma_st, ty_idx);
02598 }
02599 else
02600 #endif // KEY
02601 {
02602 PREG_NUM preg = Create_Preg (rtype, vho_lower_comma_name);
02603 ST* preg_st = MTYPE_To_PREG (rtype);
02604 OPCODE opcode = OPCODE_make_op (OPR_STID, MTYPE_V, rtype);
02605 wn = WN_CreateStid (opcode, preg, preg_st, ty_idx, result);
02606 WN_Set_Linenum ( wn, VHO_Srcpos );
02607 WN_INSERT_BlockLast (comma_block, wn);
02608 opcode = OPCODE_make_op (OPR_LDID, rtype, rtype);
02609 result = WN_CreateLdid (opcode, preg, preg_st, ty_idx);
02610 }
02611 }
02612 }
02613
02614 #ifdef KEY
02615 if (VHO_In_MP_Region_Pragma && WN_operator (result) == OPR_LDID &&
02616 ST_class (WN_st (result)) == CLASS_PREG)
02617 {
02618
02619
02620 TYPE_ID rtype = WN_rtype (result);
02621 ST * comma_st = Gen_Temp_Symbol (MTYPE_TO_TY_array[rtype], "_comma");
02622 WN * stid = WN_Stid (rtype, 0, comma_st, WN_ty (result), result);
02623 WN_Set_Linenum (stid, VHO_Srcpos);
02624 WN_INSERT_BlockLast (comma_block, stid);
02625 result = WN_Ldid (rtype, 0, comma_st, WN_ty (result));
02626 }
02627
02628
02629
02630
02631 WN * last = WN_last (block);
02632 if (last && WN_operator (last) == OPR_PRAGMA &&
02633 WN_pragma (last) == WN_PRAGMA_ATOMIC)
02634 {
02635 WN_INSERT_BlockBefore ( block, WN_last (block), comma_block );
02636 }
02637 else
02638 #endif // KEY
02639 WN_INSERT_BlockLast ( block, comma_block );
02640 }
02641
02642 if ( WN_first(result_block) ) {
02643
02644 WN_INSERT_BlockLast ( block, result_block );
02645 }
02646
02647 wn = result;
02648
02649 return wn;
02650 }
02651
02652
02653 static WN *
02654 vho_lower_rcomma ( WN * wn, WN *block, BOOL_INFO * bool_info )
02655 {
02656 WN * rcomma_block;
02657 WN * test;
02658 TYPE_ID preg_mtype;
02659 PREG_NUM preg;
02660 ST * preg_st;
02661 TY_IDX preg_ty_idx;
02662 OPCODE opcode;
02663
02664 preg_mtype = WN_rtype(wn);
02665 rcomma_block = WN_CreateBlock ();
02666 WN_Set_Linenum ( rcomma_block, VHO_Srcpos );
02667
02668 test = vho_lower_expr (WN_kid0(wn), rcomma_block, bool_info);
02669 if ( WN_first(rcomma_block) )
02670 WN_INSERT_BlockLast ( block, rcomma_block );
02671 rcomma_block = vho_lower_block ( WN_kid1(wn));
02672
02673 preg = Create_Preg (preg_mtype, vho_lower_rcomma_name);
02674
02675 preg_st = MTYPE_To_PREG ( preg_mtype );
02676 preg_ty_idx = Be_Type_Tbl(preg_mtype);
02677 opcode = OPCODE_make_op ( OPR_STID, MTYPE_V, preg_mtype );
02678 wn = WN_CreateStid ( opcode, preg, preg_st, preg_ty_idx, test );
02679 WN_Set_Linenum ( wn, VHO_Srcpos );
02680
02681 WN_INSERT_BlockLast ( block, wn );
02682 WN_INSERT_BlockLast ( block, rcomma_block );
02683 opcode = OPCODE_make_op ( OPR_LDID, Promoted_Mtype [preg_mtype],
02684 preg_mtype );
02685 wn = WN_CreateLdid ( opcode, preg, preg_st, preg_ty_idx );
02686
02687 return wn;
02688 }
02689
02690
02691 static WN *
02692 vho_simplify_cand ( WN * wn, WN * l_wn, WN * r_wn )
02693 {
02694 BOOL simplified;
02695 OPCODE l_opc;
02696 OPCODE r_opc;
02697 OPERATOR l_oper;
02698 OPERATOR r_oper;
02699 OPERATOR ll_oper;
02700 OPERATOR lr_oper;
02701 OPERATOR rl_oper;
02702 OPERATOR rr_oper;
02703 OPERATOR llr_oper;
02704 OPERATOR rlr_oper;
02705
02706 WN * ll_wn;
02707 WN * lr_wn;
02708 WN * rl_wn;
02709 WN * rr_wn;
02710 WN * lll_wn;
02711 WN * llr_wn;
02712 WN * rll_wn;
02713 WN * rlr_wn;
02714
02715 simplified = FALSE;
02716
02717 l_opc = WN_opcode(l_wn);
02718 r_opc = WN_opcode(r_wn);
02719 l_oper = OPCODE_operator(l_opc);
02720 r_oper = OPCODE_operator(r_opc);
02721
02722
02723
02724
02725
02726
02727
02728 if ( WN_Simp_Compare_Trees ( l_wn, r_wn ) == 0 ) {
02729
02730 wn = l_wn;
02731 simplified = TRUE;
02732 }
02733
02734
02735
02736
02737
02738
02739
02740 else
02741 if ( r_oper == OPR_INTCONST
02742 && WN_const_val(r_wn) == 1 ) {
02743
02744 wn = l_wn;
02745 simplified = TRUE;
02746 }
02747
02748
02749
02750
02751
02752
02753
02754 else
02755 if ( r_oper == OPR_INTCONST
02756 && WN_const_val(r_wn) == 0 ) {
02757
02758 wn = r_wn;
02759 simplified = TRUE;
02760 }
02761
02762
02763
02764
02765
02766
02767
02768 else
02769 if ( l_oper == OPR_INTCONST
02770 && WN_const_val(l_wn) == 1 ) {
02771
02772 wn = r_wn;
02773 simplified = TRUE;
02774 }
02775
02776
02777
02778
02779
02780
02781
02782 else
02783 if ( l_oper == OPR_INTCONST
02784 && WN_const_val(l_wn) == 0 ) {
02785
02786 wn = l_wn;
02787 simplified = TRUE;
02788 }
02789
02790
02791
02792
02793
02794
02795
02796 else
02797 if ( l_oper == OPR_CIOR
02798 && r_oper == OPR_CIOR ) {
02799
02800 ll_wn = WN_kid0(l_wn);
02801 lr_wn = WN_kid1(l_wn);
02802 rl_wn = WN_kid0(r_wn);
02803 rr_wn = WN_kid1(r_wn);
02804
02805 if ( WN_Simp_Compare_Trees ( ll_wn, rl_wn ) == 0 ) {
02806
02807 WN *r_wn_new = WN_Create ( OPC_I4CAND, 2 );
02808 WN_kid0(r_wn_new) = lr_wn;
02809 WN_kid1(r_wn_new) = rr_wn;
02810 wn = WN_Create ( OPC_I4CIOR, 2 );
02811 WN_kid0(wn) = ll_wn;
02812 WN_kid1(wn) = r_wn_new;
02813 simplified = TRUE;
02814
02815 if ( Cur_PU_Feedback )
02816 Cur_PU_Feedback->FB_factor_circuit( l_wn, r_wn, wn, r_wn_new );
02817 }
02818 }
02819
02820
02821
02822
02823
02824
02825
02826 else
02827 if ( l_oper == OPR_NE
02828 && r_oper == OPR_NE
02829 && l_opc == r_opc ) {
02830
02831 ll_wn = WN_kid0(l_wn);
02832 lr_wn = WN_kid1(l_wn);
02833 rl_wn = WN_kid0(r_wn);
02834 rr_wn = WN_kid1(r_wn);
02835
02836 ll_oper = WN_operator(ll_wn);
02837 lr_oper = WN_operator(lr_wn);
02838 rl_oper = WN_operator(rl_wn);
02839 rr_oper = WN_operator(rr_wn);
02840
02841 if ( ll_oper == OPR_BAND
02842 && lr_oper == OPR_INTCONST
02843 && WN_const_val(lr_wn) == 0
02844 && rl_oper == OPR_BAND
02845 && rr_oper == OPR_INTCONST
02846 && WN_const_val(rr_wn) == 0 ) {
02847
02848 lll_wn = WN_kid0(ll_wn);
02849 llr_wn = WN_kid1(ll_wn);
02850 rll_wn = WN_kid0(rl_wn);
02851 rlr_wn = WN_kid1(rl_wn);
02852
02853 llr_oper = WN_operator(llr_wn);
02854 rlr_oper = WN_operator(rlr_wn);
02855
02856 if ( llr_oper == OPR_INTCONST
02857 && rlr_oper == OPR_INTCONST
02858 && WN_Simp_Compare_Trees ( lll_wn, rll_wn ) == 0
02859 && IS_POWER_OF_2(WN_const_val(llr_wn))
02860 && IS_POWER_OF_2(WN_const_val(rlr_wn)) ) {
02861
02862 r_wn = rlr_wn;
02863 WN_const_val(r_wn) |= WN_const_val(llr_wn);
02864 ll_wn = lll_wn;
02865 lr_wn = llr_wn;
02866 WN_const_val(lr_wn) = WN_const_val(r_wn);
02867 l_wn = WN_CreateExp2 ( WN_opcode(rl_wn), ll_wn, lr_wn );
02868 #ifdef KEY
02869 if( MTYPE_is_size_double(WN_rtype(l_wn)) )
02870 wn = WN_CreateExp2 ( OPC_I4I8EQ, l_wn, r_wn );
02871 else
02872 #endif
02873 wn = WN_CreateExp2 ( OPC_I4I4EQ, l_wn, r_wn );
02874 simplified = TRUE;
02875 }
02876 }
02877 }
02878
02879 if ( ! simplified ) {
02880
02881 if ( WN_kid0(wn) != l_wn
02882 || WN_kid1(wn) != r_wn ) {
02883
02884 wn = WN_Create ( OPC_I4CAND, 2 );
02885 WN_kid0(wn) = l_wn;
02886 WN_kid1(wn) = r_wn;
02887 }
02888 }
02889
02890 return wn;
02891 }
02892
02893 static WN *
02894 vho_simplify_cior ( WN * wn, WN * l_wn, WN * r_wn )
02895 {
02896 BOOL simplified;
02897 OPCODE l_opc;
02898 OPCODE r_opc;
02899 OPERATOR l_oper;
02900 OPERATOR r_oper;
02901 OPERATOR ll_oper;
02902 OPERATOR lr_oper;
02903 OPERATOR rl_oper;
02904 OPERATOR rr_oper;
02905 OPERATOR llr_oper;
02906 OPERATOR rlr_oper;
02907
02908 WN * ll_wn;
02909 WN * lr_wn;
02910 WN * rl_wn;
02911 WN * rr_wn;
02912 WN * lll_wn;
02913 WN * llr_wn;
02914 WN * rll_wn;
02915 WN * rlr_wn;
02916
02917 simplified = FALSE;
02918
02919 l_opc = WN_opcode(l_wn);
02920 r_opc = WN_opcode(r_wn);
02921 l_oper = OPCODE_operator(l_opc);
02922 r_oper = OPCODE_operator(r_opc);
02923
02924 if ( WN_Simp_Compare_Trees ( l_wn, r_wn ) == 0 ) {
02925
02926 wn = l_wn;
02927 simplified = TRUE;
02928 }
02929
02930
02931
02932
02933
02934
02935
02936 else
02937 if ( r_oper == OPR_INTCONST
02938 && WN_const_val(r_wn) == 1 ) {
02939
02940 wn = r_wn;
02941 simplified = TRUE;
02942 }
02943
02944
02945
02946
02947
02948
02949
02950 else
02951 if ( r_oper == OPR_INTCONST
02952 && WN_const_val(r_wn) == 0 ) {
02953
02954 wn = l_wn;
02955 simplified = TRUE;
02956 }
02957
02958
02959
02960
02961
02962
02963
02964 else
02965 if ( l_oper == OPR_INTCONST
02966 && WN_const_val(l_wn) == 1 ) {
02967
02968 wn = l_wn;
02969 simplified = TRUE;
02970 }
02971
02972
02973
02974
02975
02976
02977
02978 else
02979 if ( l_oper == OPR_INTCONST
02980 && WN_const_val(l_wn) == 0 ) {
02981
02982 wn = r_wn;
02983 simplified = TRUE;
02984 }
02985
02986
02987
02988
02989
02990
02991
02992 else
02993 if ( l_oper == OPR_CAND
02994 && r_oper == OPR_CAND ) {
02995
02996 ll_wn = WN_kid0(l_wn);
02997 lr_wn = WN_kid1(l_wn);
02998 rl_wn = WN_kid0(r_wn);
02999 rr_wn = WN_kid1(r_wn);
03000
03001 if ( WN_Simp_Compare_Trees ( ll_wn, rl_wn ) == 0 ) {
03002
03003 WN *r_wn_new = WN_Create ( OPC_I4CIOR, 2 );
03004 WN_kid0(r_wn_new) = lr_wn;
03005 WN_kid1(r_wn_new) = rr_wn;
03006 wn = WN_Create ( OPC_I4CAND, 2 );
03007 WN_kid0(wn) = ll_wn;
03008 WN_kid1(wn) = r_wn_new;
03009 simplified = TRUE;
03010
03011 if ( Cur_PU_Feedback )
03012 Cur_PU_Feedback->FB_factor_circuit( l_wn, r_wn, wn, r_wn_new );
03013 }
03014 }
03015
03016
03017
03018
03019
03020
03021
03022 else
03023 if ( l_oper == OPR_NE
03024 && r_oper == OPR_NE
03025 && l_opc == r_opc ) {
03026
03027 ll_wn = WN_kid0(l_wn);
03028 lr_wn = WN_kid1(l_wn);
03029 rl_wn = WN_kid0(r_wn);
03030 rr_wn = WN_kid1(r_wn);
03031
03032 ll_oper = WN_operator(ll_wn);
03033 lr_oper = WN_operator(lr_wn);
03034 rl_oper = WN_operator(rl_wn);
03035 rr_oper = WN_operator(rr_wn);
03036
03037 if ( ll_oper == OPR_BAND
03038 && lr_oper == OPR_INTCONST
03039 && WN_const_val(lr_wn) == 0
03040 && rl_oper == OPR_BAND
03041 && rr_oper == OPR_INTCONST
03042 && WN_const_val(rr_wn) == 0 ) {
03043
03044 lll_wn = WN_kid0(ll_wn);
03045 llr_wn = WN_kid1(ll_wn);
03046 rll_wn = WN_kid0(rl_wn);
03047 rlr_wn = WN_kid1(rl_wn);
03048
03049 llr_oper = WN_operator(llr_wn);
03050 rlr_oper = WN_operator(rlr_wn);
03051
03052 if ( llr_oper == OPR_INTCONST
03053 && rlr_oper == OPR_INTCONST
03054 && WN_Simp_Compare_Trees ( lll_wn, rll_wn ) == 0 ) {
03055
03056 ll_wn = lll_wn;
03057 lr_wn = llr_wn;
03058 WN_const_val(lr_wn) |= WN_const_val(rlr_wn);
03059 l_wn = WN_CreateExp2 ( WN_opcode(rl_wn), ll_wn, lr_wn );
03060 r_wn = rr_wn;
03061 wn = WN_CreateExp2 ( l_opc, l_wn, r_wn );
03062 simplified = TRUE;
03063 }
03064 }
03065 }
03066
03067 if ( ! simplified ) {
03068
03069 if ( WN_kid0(wn) != l_wn
03070 || WN_kid1(wn) != r_wn ) {
03071
03072 wn = WN_Create ( OPC_I4CIOR, 2 );
03073 WN_kid0(wn) = l_wn;
03074 WN_kid1(wn) = r_wn;
03075 }
03076 }
03077
03078 return wn;
03079 }
03080
03081
03082 static WN *
03083 vho_simplify_cand_cior ( WN * wn )
03084 {
03085 WN * lwn;
03086 WN * rwn;
03087
03088 switch ( WN_opcode(wn) ) {
03089
03090
03091
03092 case OPC_BCAND:
03093 case OPC_I4CAND:
03094
03095
03096 lwn = vho_simplify_cand_cior ( WN_kid0(wn) );
03097 rwn = vho_simplify_cand_cior ( WN_kid1(wn) );
03098 wn = vho_simplify_cand ( wn, lwn, rwn );
03099 break;
03100
03101
03102
03103 case OPC_BCIOR:
03104 case OPC_I4CIOR:
03105
03106
03107 lwn = vho_simplify_cand_cior ( WN_kid0(wn) );
03108 rwn = vho_simplify_cand_cior ( WN_kid1(wn) );
03109 wn = vho_simplify_cior ( wn, lwn, rwn );
03110 break;
03111 }
03112
03113 return wn;
03114 }
03115
03116
03117 static WN *
03118 vho_lower_cand_cior ( WN *wn, WN *block, BOOL_INFO *bool_info )
03119 {
03120 WN * one;
03121 WN * zero;
03122 WN * cflow_block1;
03123 WN * cflow_block2;
03124 BOOL_INFO cflow_bool_info;
03125 BOOL_INFO cflow_bool_info1;
03126 BOOL_INFO cflow_bool_info2;
03127 OPCODE opcode;
03128 LABEL_IDX join_label;
03129 WN * lwn;
03130 WN * rwn;
03131 PREG_NUM preg;
03132 ST * preg_st;
03133 TY_IDX preg_ty_idx;
03134
03135 opcode = WN_opcode(wn);
03136
03137 cflow_block1 = WN_CreateBlock ();
03138 cflow_block2 = WN_CreateBlock ();
03139
03140 WN_Set_Linenum ( cflow_block1, VHO_Srcpos );
03141 WN_Set_Linenum ( cflow_block2, VHO_Srcpos );
03142
03143 if ( ! bool_info ) {
03144
03145 vho_initialize_bool_info (&cflow_bool_info);
03146 LABEL_Init (New_LABEL (CURRENT_SYMTAB, cflow_bool_info.true_label),
03147 0, LKIND_DEFAULT);
03148 LABEL_Init (New_LABEL (CURRENT_SYMTAB, cflow_bool_info.false_label),
03149 0, LKIND_DEFAULT);
03150 bool_info = &cflow_bool_info;
03151 }
03152
03153 cflow_bool_info1 = *bool_info;
03154 cflow_bool_info1.opcode = opcode;
03155
03156 if ( cflow_bool_info1.opcode != OPCODE_UNKNOWN )
03157 cflow_bool_info1.opcode = opcode;
03158
03159 cflow_bool_info2 = cflow_bool_info1;
03160
03161
03162
03163
03164
03165
03166 {
03167
03168 if ( opcode == (OPC_I4CAND) ) {
03169
03170 LABEL_Init (New_LABEL (CURRENT_SYMTAB, cflow_bool_info1.true_label),
03171 0, LKIND_DEFAULT);
03172 cflow_bool_info1.used_true_label = FALSE;
03173 }
03174
03175 else {
03176
03177 LABEL_Init (New_LABEL (CURRENT_SYMTAB, cflow_bool_info1.false_label),
03178 0, LKIND_DEFAULT);
03179 cflow_bool_info1.used_false_label = FALSE;
03180 }
03181 }
03182
03183 lwn = vho_lower_expr (WN_kid0(wn), cflow_block1, &cflow_bool_info1);
03184 rwn = vho_lower_expr (WN_kid1(wn), cflow_block2, &cflow_bool_info2);
03185 WN_kid0(wn) = lwn;
03186 WN_kid1(wn) = rwn;
03187
03188 WN *wn_label, *wn_left_branch = NULL, *wn_right_branch = NULL;
03189
03190 if ( WN_first(cflow_block1) )
03191 WN_INSERT_BlockLast ( block, cflow_block1 );
03192
03193 if ( WN_first(cflow_block2)
03194 || cflow_bool_info1.used_true_label
03195 || cflow_bool_info1.used_false_label
03196 || cflow_bool_info2.used_true_label
03197 || cflow_bool_info2.used_false_label ) {
03198
03199 if ( opcode == (OPC_I4CAND) ) {
03200
03201 if ( lwn ) {
03202
03203 wn_left_branch
03204 = WN_CreateFalsebr ( cflow_bool_info1.false_label, lwn );
03205 WN_Set_Linenum ( wn_left_branch, VHO_Srcpos );
03206 WN_INSERT_BlockLast ( block, wn_left_branch );
03207 }
03208
03209
03210
03211
03212
03213
03214
03215
03216
03217
03218 if ( cflow_bool_info1.used_true_label ) {
03219
03220 wn_label = WN_CreateLabel ( (ST_IDX) 0, cflow_bool_info1.true_label,
03221 0, NULL );
03222 WN_Set_Linenum ( wn_label, VHO_Srcpos );
03223 WN_INSERT_BlockLast ( block, wn_label );
03224 }
03225
03226 if ( WN_first(cflow_block2) )
03227 WN_INSERT_BlockLast ( block, cflow_block2 );
03228
03229 if ( rwn ) {
03230
03231 wn_right_branch
03232 = WN_CreateFalsebr ( cflow_bool_info2.false_label, rwn );
03233 WN_Set_Linenum ( wn_right_branch, VHO_Srcpos );
03234 WN_INSERT_BlockLast ( block, wn_right_branch );
03235
03236 if ( bool_info->opcode ) {
03237
03238 if ( opcode != bool_info->opcode ) {
03239
03240 WN *wn_goto
03241 = WN_CreateGoto ( (ST_IDX) NULL, cflow_bool_info2.true_label );
03242 WN_Set_Linenum ( wn_goto, VHO_Srcpos );
03243 WN_INSERT_BlockLast ( block, wn_goto );
03244
03245 cflow_bool_info2.used_true_label = TRUE;
03246 }
03247 }
03248 }
03249
03250 bool_info->used_false_label = TRUE;
03251 bool_info->used_true_label |= cflow_bool_info2.used_true_label;
03252
03253 if (Cur_PU_Feedback) {
03254 Cur_PU_Feedback->FB_lower_circuit( wn,
03255 wn_left_branch, wn_right_branch );
03256 }
03257 }
03258
03259 else {
03260
03261 if ( lwn ) {
03262
03263 wn_left_branch = WN_CreateTruebr ( cflow_bool_info1.true_label, lwn );
03264 WN_Set_Linenum ( wn_left_branch, VHO_Srcpos );
03265 WN_INSERT_BlockLast ( block, wn_left_branch );
03266 }
03267
03268 else
03269 if ( cflow_bool_info1.used_false_label ) {
03270
03271 WN *wn_goto
03272 = WN_CreateGoto ( (ST_IDX) NULL, cflow_bool_info1.true_label );
03273 WN_Set_Linenum ( wn_goto, VHO_Srcpos );
03274 WN_INSERT_BlockLast ( block, wn_goto );
03275 }
03276
03277 if ( cflow_bool_info1.used_false_label ) {
03278
03279 wn_label
03280 = WN_CreateLabel ( (ST_IDX) 0, cflow_bool_info1.false_label, 0, NULL );
03281 WN_Set_Linenum ( wn_label, VHO_Srcpos );
03282 WN_INSERT_BlockLast ( block, wn_label );
03283 }
03284
03285 if ( WN_first(cflow_block2) )
03286 WN_INSERT_BlockLast ( block, cflow_block2 );
03287
03288 if ( rwn ) {
03289
03290 wn_right_branch
03291 = WN_CreateFalsebr ( cflow_bool_info2.false_label, rwn );
03292 WN_Set_Linenum ( wn_right_branch, VHO_Srcpos );
03293 WN_INSERT_BlockLast ( block, wn_right_branch );
03294 cflow_bool_info2.used_false_label = TRUE;
03295
03296 if ( bool_info->opcode != opcode
03297 && bool_info->opcode != OPCODE_UNKNOWN ) {
03298
03299 WN *wn_goto
03300 = WN_CreateGoto ( (ST_IDX) NULL, cflow_bool_info2.true_label );
03301 WN_Set_Linenum ( wn_goto, VHO_Srcpos );
03302 WN_INSERT_BlockLast ( block, wn_goto );
03303 }
03304 }
03305
03306
03307
03308
03309
03310
03311
03312
03313
03314
03315
03316
03317 bool_info->used_true_label = TRUE;
03318 bool_info->used_false_label |= cflow_bool_info2.used_false_label;
03319
03320 if (Cur_PU_Feedback)
03321 Cur_PU_Feedback->FB_lower_circuit( wn,
03322 wn_left_branch, wn_right_branch );
03323 }
03324
03325 if ( bool_info == &cflow_bool_info ) {
03326
03327
03328
03329 LABEL_Init (New_LABEL (CURRENT_SYMTAB, join_label),
03330 0, LKIND_DEFAULT);
03331
03332 preg = Create_Preg (MTYPE_I4, vho_lower_cand_cior_name);
03333
03334 preg_st = MTYPE_To_PREG ( MTYPE_I4 );
03335 preg_ty_idx = Be_Type_Tbl(MTYPE_I4);
03336
03337 if ( bool_info->used_true_label ) {
03338
03339 wn = WN_CreateLabel ( (ST_IDX) 0, bool_info->true_label, 0, NULL );
03340 WN_Set_Linenum ( wn, VHO_Srcpos );
03341 WN_INSERT_BlockLast ( block, wn );
03342 }
03343
03344 one = WN_CreateIntconst ( OPC_I4INTCONST, 1 );
03345 wn = WN_CreateStid ( OPC_I4STID, preg, preg_st, preg_ty_idx, one );
03346 WN_Set_Linenum ( wn, VHO_Srcpos );
03347 WN_INSERT_BlockLast ( block, wn );
03348
03349 wn = WN_CreateGoto ( (ST_IDX) NULL, join_label );
03350 WN_Set_Linenum ( wn, VHO_Srcpos );
03351 WN_INSERT_BlockLast ( block, wn );
03352
03353 wn = WN_CreateLabel ( (ST_IDX) 0, bool_info->false_label, 0, NULL );
03354 WN_Set_Linenum ( wn, VHO_Srcpos );
03355 WN_INSERT_BlockLast ( block, wn );
03356
03357 zero = WN_CreateIntconst ( OPC_I4INTCONST, 0 );
03358 wn = WN_CreateStid ( OPC_I4STID, preg, preg_st, preg_ty_idx, zero );
03359 WN_Set_Linenum ( wn, VHO_Srcpos );
03360 WN_INSERT_BlockLast ( block, wn );
03361
03362 wn = WN_CreateLabel ( (ST_IDX) 0, join_label, 0, NULL );
03363 WN_Set_Linenum ( wn, VHO_Srcpos );
03364 WN_INSERT_BlockLast ( block, wn );
03365
03366 wn = WN_CreateLdid ( OPC_I4I4LDID, preg, preg_st, preg_ty_idx );
03367 }
03368
03369 else
03370
03371 wn = NULL;
03372 }
03373
03374 else {
03375
03376 wn = vho_simplify_cand_cior ( wn );
03377 }
03378
03379 return wn;
03380 }
03381
03382
03383 static WN *
03384 vho_lower_cselect ( WN * wn_cselect, WN * block, BOOL_INFO * bool_info )
03385 {
03386 WN * wn = wn_cselect;
03387 WN * cflow_block;
03388 WN * cflow_block1;
03389 WN * cflow_block2;
03390 BOOL_INFO cflow_bool_info;
03391 WN * test;
03392 WN * lwn;
03393 WN * rwn;
03394 TYPE_ID preg_mtype;
03395 PREG_NUM preg;
03396 ST * preg_st;
03397 TY_IDX preg_ty_idx;
03398 OPCODE opcode;
03399 OPCODE addopc;
03400 OPCODE intopc;
03401 LABEL_IDX join_label;
03402 BOOL mcselect;
03403 BOOL vcselect;
03404 TY_IDX ty_idx;
03405 WN_OFFSET offset;
03406 WN_OFFSET lwn_offset;
03407 WN_OFFSET rwn_offset;
03408 WN * swn;
03409 BOOL has_side_effects;
03410
03411 vcselect = FALSE;
03412 mcselect = FALSE;
03413 cflow_block = WN_CreateBlock ();
03414 cflow_block1 = WN_CreateBlock ();
03415 cflow_block2 = WN_CreateBlock ();
03416
03417 WN_Set_Linenum ( cflow_block, VHO_Srcpos );
03418 WN_Set_Linenum ( cflow_block1, VHO_Srcpos );
03419 WN_Set_Linenum ( cflow_block2, VHO_Srcpos );
03420
03421 vho_initialize_bool_info (&cflow_bool_info);
03422
03423 LABEL_Init (New_LABEL (CURRENT_SYMTAB, cflow_bool_info.true_label),
03424 0, LKIND_DEFAULT);
03425 LABEL_Init (New_LABEL (CURRENT_SYMTAB, cflow_bool_info.false_label),
03426 0, LKIND_DEFAULT);
03427
03428 opcode = WN_opcode(wn_cselect);
03429 test = vho_lower_expr ( WN_kid0(wn_cselect), cflow_block,
03430 &cflow_bool_info );
03431 lwn = vho_lower_expr ( WN_kid1(wn_cselect), cflow_block1, NULL );
03432 rwn = vho_lower_expr ( WN_kid2(wn_cselect), cflow_block2, NULL );
03433
03434 if ( WHIRL_Mldid_Mstid_On && opcode == OPC_MCSELECT && test != NULL ) {
03435
03436
03437
03438
03439
03440
03441
03442
03443
03444
03445
03446 ty_idx = WN_ty(lwn);
03447 #ifdef KEY // bug 5179
03448 if (WN_field_id(lwn) != 0)
03449 ty_idx = get_field_type(ty_idx, WN_field_id(lwn));
03450 #endif
03451 ST* temp = Gen_Temp_Symbol (ty_idx, ".mcselect");
03452
03453 wn = WN_CreateStid (OPR_STID, MTYPE_V, MTYPE_M,
03454 0, ST_st_idx (temp), ty_idx, lwn);
03455 WN_Set_Linenum (wn, VHO_Srcpos);
03456 WN_INSERT_BlockLast (cflow_block1, wn);
03457
03458 wn = WN_CreateStid (OPR_STID, MTYPE_V, MTYPE_M,
03459 0, ST_st_idx (temp), ty_idx, rwn);
03460 WN_Set_Linenum (wn, VHO_Srcpos);
03461 WN_INSERT_BlockLast (cflow_block2, wn);
03462
03463 wn = WN_CreateIf (test, cflow_block1, cflow_block2);
03464 WN_Set_Linenum ( wn, VHO_Srcpos );
03465 if ( Cur_PU_Feedback ) {
03466 Cur_PU_Feedback->FB_lower_branch( wn_cselect, wn );
03467 }
03468
03469 if (WN_first (cflow_block))
03470 WN_INSERT_BlockLast (block, cflow_block);
03471
03472 WN_INSERT_BlockLast (block, wn);
03473
03474 wn = WN_CreateLdid (OPR_LDID, MTYPE_M, MTYPE_M,
03475 0, ST_st_idx (temp), ty_idx);
03476 return wn;
03477 }
03478
03479 if ( VHO_Cselect_Opt
03480 && WN_first(cflow_block) == NULL
03481 && WN_first(cflow_block1) == NULL
03482 && WN_first(cflow_block2) == NULL
03483 && cflow_bool_info.used_true_label == FALSE
03484 && cflow_bool_info.used_false_label == FALSE ) {
03485
03486 if ( opcode == OPC_VCSELECT ) {
03487
03488 }
03489
03490 else
03491 if ( opcode == OPC_MCSELECT ) {
03492
03493 }
03494
03495 else {
03496
03497 has_side_effects = VHO_WN_has_side_effects ( test )
03498 || VHO_WN_has_side_effects ( lwn )
03499 || VHO_WN_has_side_effects ( rwn );
03500
03501 if ( has_side_effects == FALSE ) {
03502
03503
03504 #ifdef KEY // bug 5363 and bug 5817
03505 if ( ( ! MTYPE_is_float(WN_desc(test)) || ! Force_IEEE_Comparisons) &&
03506 WN_operator(test) == OPR_NE &&
03507 VHO_WN_is_zero(WN_kid1(test)) &&
03508 WN_Simp_Compare_Trees ( WN_kid0(test), lwn ) == 0 &&
03509 VHO_WN_is_zero(rwn) )
03510 return lwn;
03511 #endif
03512
03513 #ifdef KEY
03514
03515 if( ( WN_operator(test) == OPR_GT ||
03516 WN_operator(test) == OPR_GE ) &&
03517 VHO_WN_is_zero(WN_kid1(test)) &&
03518 WN_Simp_Compare_Trees( WN_kid0(test), lwn ) == 0 ){
03519
03520 if( WN_operator(rwn) == OPR_SUB &&
03521 WN_operator(lwn) == WN_operator(rwn) &&
03522 WN_Simp_Compare_Trees( WN_kid0(rwn), WN_kid1(lwn) ) == 0 &&
03523 WN_Simp_Compare_Trees( WN_kid1(rwn), WN_kid0(lwn) ) == 0 ){
03524
03525 opcode = OPCODE_make_op ( OPR_ABS,
03526 WN_rtype(wn),
03527 MTYPE_V );
03528 wn = WN_CreateExp1 ( opcode, lwn );
03529 return wn;
03530 }
03531 }
03532
03533
03534
03535
03536
03537 #if defined(TARG_X8664)
03538 if ( WN_operator(test) == OPR_GT &&
03539 WN_rtype(test) == MTYPE_I4 &&
03540 WN_desc(test) == MTYPE_U4 &&
03541 WN_operator(WN_kid1(test)) == OPR_INTCONST &&
03542 WN_const_val(WN_kid1(test)) == 0x7fff &&
03543
03544 WN_operator(WN_kid2(wn_cselect)) == OPR_INTCONST &&
03545 WN_const_val(WN_kid2(wn_cselect)) == 0 &&
03546
03547 WN_operator(WN_kid1(wn_cselect)) == OPR_CVTL &&
03548 WN_cvtl_bits(WN_kid1(wn_cselect)) == 16 &&
03549 WN_operator(WN_kid0(WN_kid1(wn_cselect))) == OPR_SUB &&
03550 WN_operator(WN_kid1(WN_kid0(WN_kid1(wn_cselect)))) ==
03551 OPR_INTCONST &&
03552 WN_const_val(WN_kid1(WN_kid0(WN_kid1(wn_cselect)))) == 0x8000 &&
03553
03554 WN_has_sym(WN_kid0(test)) &&
03555 WN_has_sym(WN_kid0(WN_kid0(WN_kid1(wn_cselect)))) &&
03556 WN_st(WN_kid0(test)) ==
03557 WN_st(WN_kid0(WN_kid0(WN_kid1(wn_cselect)))) ) {
03558 WN* kids[2];
03559 kids[0] = WN_kid0(test);
03560 kids[1] = WN_kid1(WN_kid0(WN_kid1(wn_cselect)));
03561
03562 kids[0] = WN_CreateParm (MTYPE_U4, kids[0],
03563 Be_Type_Tbl(MTYPE_U4),
03564 WN_PARM_BY_VALUE);
03565 kids[1] = WN_CreateParm (MTYPE_U4, kids[1],
03566 Be_Type_Tbl(MTYPE_U4),
03567 WN_PARM_BY_VALUE);
03568 wn = WN_Create_Intrinsic(OPCODE_make_op(OPR_INTRINSIC_OP,
03569 MTYPE_U4, MTYPE_V),
03570 INTRN_SUBSU2, 2, kids);
03571 return wn;
03572
03573 }
03574 #endif // TARG_X7664
03575 #endif
03576
03577
03578
03579 if ( ( WN_operator(test) == OPR_GT
03580 || WN_operator(test) == OPR_GE )
03581 && VHO_WN_is_zero(WN_kid1(test))
03582 && WN_Simp_Compare_Trees ( WN_kid0(test), lwn ) == 0
03583 && WN_operator(rwn) == OPR_NEG
03584 && WN_Simp_Compare_Trees ( lwn, WN_kid0(rwn) ) == 0 ) {
03585
03586 DevWarn ( "%s: %s %s\n",
03587 OPCODE_name(WN_opcode(wn)),
03588 MTYPE_name(WN_rtype(wn)),
03589 MTYPE_name(WN_desc(wn)) );
03590
03591 if ( MTYPE_signed(WN_rtype(wn)) ) {
03592
03593 opcode = OPCODE_make_op ( OPR_ABS,
03594 WN_rtype(wn),
03595 MTYPE_V );
03596 wn = WN_CreateExp1 ( opcode, lwn );
03597
03598
03599
03600 return wn;
03601 }
03602 }
03603
03604
03605
03606 if ( ( WN_operator(test) == OPR_GT
03607 || WN_operator(test) == OPR_GE )
03608 && WN_Simp_Compare_Trees ( WN_kid0(test), lwn ) == 0
03609 && WN_Simp_Compare_Trees ( WN_kid1(test), rwn ) == 0
03610 #if defined(TARG_SL)
03611 && MTYPE_is_integral(WN_desc(test))
03612 #endif
03613 ) {
03614
03615 DevWarn ( "%s: %s %s\n",
03616 OPCODE_name(WN_opcode(wn)),
03617 MTYPE_name(WN_rtype(wn)),
03618 MTYPE_name(WN_desc(wn)) );
03619
03620 opcode = OPCODE_make_op ( OPR_MAX,
03621 WN_rtype(wn),
03622 MTYPE_V );
03623 wn = WN_CreateExp2 ( opcode, lwn, rwn );
03624
03625
03626
03627 return wn;
03628 }
03629
03630
03631
03632 if ( ( WN_operator(test) == OPR_LT
03633 || WN_operator(test) == OPR_LE )
03634 && WN_Simp_Compare_Trees ( WN_kid0(test), lwn ) == 0
03635 && WN_Simp_Compare_Trees ( WN_kid1(test), rwn ) == 0
03636 #if defined(TARG_SL)
03637 && MTYPE_is_integral(WN_desc(test))
03638 #endif
03639 ) {
03640
03641 DevWarn ( "%s: %s %s\n",
03642 OPCODE_name(WN_opcode(wn)),
03643 MTYPE_name(WN_rtype(wn)),
03644 MTYPE_name(WN_desc(wn)) );
03645
03646 opcode = OPCODE_make_op ( OPR_MIN,
03647 WN_rtype(wn),
03648 MTYPE_V );
03649 wn = WN_CreateExp2 ( opcode, lwn, rwn );
03650
03651
03652
03653 return wn;
03654 }
03655 #ifdef TARG_NVISA
03656
03657
03658
03659
03660
03661
03662 if (WN_operator(rwn) == OPR_LDID
03663 && WN_operator(lwn) == OPR_ADD
03664 && WN_Simp_Compare_Trees ( WN_kid0(lwn), rwn ) == 0
03665 && WN_operator(WN_kid1(lwn)) == OPR_INTCONST
03666 && (WN_const_val(WN_kid1(lwn)) == 1
03667
03668 || WN_const_val(WN_kid1(lwn)) == -1))
03669 {
03670 DevWarn("transform cselect back to straightline code");
03671 ST *st = Gen_Temp_Symbol (MTYPE_To_TY(WN_rtype(test)), "_cond");
03672 wn = WN_Stid (WN_rtype(test), 0, st, ST_type(st),
03673 test, 0);
03674 WN_Set_Linenum ( wn, VHO_Srcpos );
03675 WN_INSERT_BlockLast ( block, wn );
03676
03677 WN *ldid = WN_Ldid (WN_rtype(test), 0, st, ST_type(st));
03678 if (WN_rtype(test) != WN_rtype(rwn))
03679 ldid = WN_Cvt(WN_rtype(test), WN_rtype(rwn), ldid);
03680 if (WN_const_val(WN_kid1(lwn)) == 1)
03681 wn = WN_Binary(OPR_ADD, WN_rtype(rwn), rwn, ldid);
03682 else
03683 wn = WN_Binary(OPR_SUB, WN_rtype(rwn), rwn, ldid);
03684 return wn;
03685 }
03686
03687 else if (WN_operator(rwn) == OPR_LDID
03688 && WN_operator(lwn) == OPR_BIOR
03689 && WN_Simp_Compare_Trees ( WN_kid0(lwn), rwn ) == 0
03690 && WN_operator(WN_kid1(lwn)) == OPR_INTCONST
03691 && WN_const_val(WN_kid1(lwn)) == 1)
03692 {
03693 DevWarn("transform cselect back to straightline code");
03694 ST *st = Gen_Temp_Symbol (MTYPE_To_TY(WN_rtype(test)), "_cond");
03695 wn = WN_Stid (WN_rtype(test), 0, st, ST_type(st),
03696 test, 0);
03697 WN_Set_Linenum ( wn, VHO_Srcpos );
03698 WN_INSERT_BlockLast ( block, wn );
03699
03700 WN *ldid = WN_Ldid (WN_rtype(test), 0, st, ST_type(st));
03701 if (WN_rtype(test) != WN_rtype(rwn))
03702 ldid = WN_Cvt(WN_rtype(test), WN_rtype(rwn), ldid);
03703 wn = WN_Binary(OPR_BIOR, WN_rtype(rwn), rwn, ldid);
03704 return wn;
03705 }
03706
03707 #endif
03708 }
03709 }
03710 }
03711
03712 if ( WN_first(cflow_block) )
03713 WN_INSERT_BlockLast ( block, cflow_block );
03714
03715 if ( opcode == OPC_VCSELECT )
03716 vcselect = TRUE;
03717
03718 else {
03719
03720 if ( opcode == OPC_MCSELECT ) {
03721
03722 FmtAssert ( ( WN_opcode(lwn) == OPC_MLOAD
03723 && WN_opcode(rwn) == OPC_MLOAD ),
03724 ("unimplemented case encountered in OPC_MCSELECT") );
03725
03726 mcselect = TRUE;
03727 preg_mtype = Pointer_Mtype;
03728 lwn_offset = WN_offset(lwn);
03729 rwn_offset = WN_offset(rwn);
03730 swn = WN_kid1(lwn);
03731 ty_idx = WN_ty(lwn);
03732 lwn = WN_kid0(lwn);
03733 rwn = WN_kid0(rwn);
03734
03735 if ( lwn_offset == rwn_offset )
03736 offset = lwn_offset;
03737
03738 else {
03739
03740 offset = 0;
03741 addopc = OPCODE_make_op ( OPR_ADD, Pointer_Mtype, MTYPE_V );
03742 intopc = OPCODE_make_op ( OPR_INTCONST, Pointer_Mtype, MTYPE_V );
03743
03744 if ( lwn_offset )
03745 lwn = WN_CreateExp2 ( addopc,
03746 lwn,
03747 WN_CreateIntconst ( intopc, lwn_offset ) );
03748
03749 if ( rwn_offset )
03750 rwn = WN_CreateExp2 ( addopc,
03751 rwn,
03752 WN_CreateIntconst ( intopc, rwn_offset ) );
03753 }
03754 }
03755
03756 else {
03757
03758 preg_mtype = WN_rtype(wn);
03759 }
03760
03761 vho_lower_set_st_addr_info ( lwn, ADDRESS_SAVED );
03762 vho_lower_set_st_addr_info ( rwn, ADDRESS_SAVED );
03763
03764 preg = Create_Preg (preg_mtype, vho_lower_cselect_name);
03765
03766 preg_st = MTYPE_To_PREG ( preg_mtype );
03767 preg_ty_idx = Be_Type_Tbl(preg_mtype);
03768 opcode = OPCODE_make_op ( OPR_STID, MTYPE_V, preg_mtype );
03769 }
03770
03771 if ( cflow_bool_info.used_true_label
03772 || cflow_bool_info.used_false_label ) {
03773
03774 LABEL_Init (New_LABEL (CURRENT_SYMTAB, join_label),
03775 0, LKIND_DEFAULT);
03776
03777 if ( cflow_bool_info.used_true_label ) {
03778
03779 wn = WN_CreateLabel ( (ST_IDX) 0, cflow_bool_info.true_label, 0, NULL );
03780 WN_Set_Linenum ( wn, VHO_Srcpos );
03781
03782 WN_INSERT_BlockLast ( block, wn );
03783 }
03784
03785 if ( WN_first(cflow_block1 ) )
03786 WN_INSERT_BlockLast ( block, cflow_block1 );
03787
03788 if ( ! vcselect ) {
03789
03790 lwn = WN_CreateStid ( opcode, preg, preg_st, preg_ty_idx, lwn );
03791 WN_Set_Linenum ( lwn, VHO_Srcpos );
03792
03793 WN_INSERT_BlockLast ( block, lwn );
03794 }
03795
03796 wn = WN_CreateGoto ( (ST_IDX) NULL, join_label );
03797 WN_Set_Linenum ( wn, VHO_Srcpos );
03798 if (Cur_PU_Feedback)
03799 Cur_PU_Feedback->Annot( wn, FB_EDGE_OUTGOING, FB_FREQ_UNKNOWN );
03800
03801 WN_INSERT_BlockLast ( block, wn );
03802
03803 wn = WN_CreateLabel ( (ST_IDX) 0, cflow_bool_info.false_label, 0, NULL );
03804 WN_Set_Linenum ( wn, VHO_Srcpos );
03805
03806 WN_INSERT_BlockLast ( block, wn );
03807
03808 if ( WN_first(cflow_block2 ) )
03809 WN_INSERT_BlockLast ( block, cflow_block2 );
03810
03811 if ( ! vcselect ) {
03812
03813 rwn = WN_CreateStid ( opcode, preg, preg_st, preg_ty_idx, rwn );
03814 WN_Set_Linenum ( rwn, VHO_Srcpos );
03815
03816 WN_INSERT_BlockLast ( block, rwn );
03817 }
03818
03819 wn = WN_CreateLabel ( (ST_IDX) 0, join_label, 0, NULL );
03820 WN_Set_Linenum ( wn, VHO_Srcpos );
03821
03822 WN_INSERT_BlockLast ( block, wn );
03823 }
03824
03825 else {
03826
03827 if ( ! vcselect ) {
03828
03829
03830
03831
03832
03833
03834
03835
03836
03837
03838
03839 lwn = WN_CreateStid ( opcode, preg, preg_st, preg_ty_idx, lwn );
03840 WN_Set_Linenum ( lwn, VHO_Srcpos );
03841
03842 WN_INSERT_BlockLast ( cflow_block1, lwn );
03843
03844 rwn = WN_CreateStid ( opcode, preg, preg_st, preg_ty_idx, rwn );
03845 WN_Set_Linenum ( rwn, VHO_Srcpos );
03846
03847 WN_INSERT_BlockLast ( cflow_block2, rwn );
03848 }
03849
03850 wn = WN_CreateIf ( test, cflow_block1, cflow_block2 );
03851 WN_Set_Linenum ( wn, VHO_Srcpos );
03852 if ( Cur_PU_Feedback ) {
03853 Cur_PU_Feedback->FB_lower_branch( wn_cselect, wn );
03854 }
03855
03856 WN_INSERT_BlockLast ( block, wn );
03857 }
03858
03859 if ( !vcselect ) {
03860
03861 opcode = OPCODE_make_op ( OPR_LDID, Promoted_Mtype [preg_mtype],
03862 preg_mtype );
03863 wn = WN_CreateLdid ( opcode, preg, preg_st, preg_ty_idx );
03864
03865 if ( mcselect )
03866 wn = WN_CreateMload ( offset, ty_idx, wn, swn );
03867 }
03868
03869 else
03870 wn = NULL;
03871
03872 return wn;
03873 }
03874
03875
03876 #if VHO_DEBUG
03877 #define record_combine_loads_failure(arg1,arg2) \
03878 fprintf (stderr, "[%d] combine_load_failure at %d of vho_lower.c\n", \
03879 arg1, arg2);
03880 #else
03881 #define record_combine_loads_failure(x,y)
03882 #endif
03883
03884 WN *
03885 vho_lower_combine_loads ( WN * wn )
03886 {
03887 TYPE_ID mtype;
03888 OPCODE opcode;
03889 OPCODE add_opc;
03890 OPCODE or_opc;
03891 OPCODE shift_opc;
03892 OPCODE load_opcode;
03893 OPERATOR wn_operator;
03894 OPERATOR load_operator;
03895 INT32 bytes;
03896 INT32 size;
03897 INT32 item_size;
03898 INT32 last_item_size;
03899 INT32 shift_bits;
03900 INT32 shift_bytes;
03901 INT32 last_index;
03902 WN * source;
03903 WN * lwn;
03904 WN * swn;
03905 WN * twn;
03906 WN * awn1;
03907 WN * awn2;
03908 BOOL combine;
03909
03910 opcode = WN_opcode(wn);
03911
03912 if ( opcode == OPC_U4ADD || opcode == OPC_U4BIOR ) {
03913 add_opc = OPC_U4ADD;
03914 or_opc = OPC_U4BIOR;
03915 shift_opc = OPC_U4SHL;
03916 size = 4;
03917 }
03918 else if ( opcode == OPC_U8ADD || opcode == OPC_U8BIOR ) {
03919 add_opc = OPC_U8ADD;
03920 or_opc = OPC_U8BIOR;
03921 shift_opc = OPC_U8SHL;
03922 size = 8;
03923 }
03924 else {
03925 record_combine_loads_failure ((INT32) VHO_Srcpos, __LINE__);
03926 return wn;
03927 }
03928
03929 bytes = 0;
03930 source = NULL;
03931 combine = TRUE;
03932 lwn = WN_kid0(wn);
03933 swn = WN_kid1(wn);
03934
03935 if ( WN_opcode(swn) != shift_opc ) {
03936 if ( WN_opcode(lwn) == shift_opc ) {
03937 swn = lwn;
03938 lwn = WN_kid1(wn);
03939 }
03940 else {
03941 combine = FALSE;
03942 record_combine_loads_failure ((INT32) VHO_Srcpos, __LINE__);
03943 }
03944 }
03945
03946 mtype = WN_desc(lwn);
03947
03948 if ( !MTYPE_is_unsigned(mtype) ) {
03949 combine = FALSE;
03950 record_combine_loads_failure ((INT32) VHO_Srcpos, __LINE__);
03951 }
03952
03953 load_opcode = WN_opcode(lwn);
03954 load_operator = OPCODE_operator(load_opcode);
03955
03956 if ( combine
03957 && WN_operator(WN_kid1(swn)) == OPR_INTCONST
03958 && ( load_operator == OPR_LDID || load_operator == OPR_ILOAD ) ) {
03959 bytes = TY_size(WN_ty(lwn));
03960 source = lwn;
03961 last_item_size = bytes;
03962
03963 if ( load_operator == OPR_ILOAD
03964 && WN_operator(WN_kid0(lwn)) == OPR_ARRAY )
03965 last_index = WN_kid_count(WN_kid0(lwn)) - 1;
03966
03967 while ( swn ) {
03968 shift_bits = WN_const_val(WN_kid1(swn));
03969 if ( shift_bits == 0 || shift_bits % 8 ) {
03970 combine = FALSE;
03971 record_combine_loads_failure ((INT32) VHO_Srcpos, __LINE__);
03972 break;
03973 }
03974
03975 shift_bytes = shift_bits >> 3;
03976
03977 lwn = WN_kid0(swn);
03978 opcode = WN_opcode(lwn);
03979 wn_operator = OPCODE_operator(opcode);
03980
03981 if ( wn_operator == OPR_LDID || wn_operator == OPR_ILOAD )
03982 swn = NULL;
03983 else if ( opcode == add_opc || opcode == or_opc ) {
03984 swn = WN_kid1(lwn);
03985 lwn = WN_kid0(lwn);
03986 if ( WN_opcode(swn) != shift_opc ) {
03987 if ( WN_opcode(lwn) == shift_opc ) {
03988 twn = lwn;
03989 lwn = swn;
03990 swn = twn;
03991 }
03992 else {
03993 combine = FALSE;
03994 record_combine_loads_failure ((INT32) VHO_Srcpos, __LINE__);
03995 break;
03996 }
03997 }
03998
03999 if ( WN_operator(WN_kid1(swn)) != OPR_INTCONST ) {
04000 combine = FALSE;
04001 record_combine_loads_failure ((INT32) VHO_Srcpos, __LINE__);
04002 break;
04003 }
04004
04005 wn_operator = WN_operator(lwn);
04006
04007 if ( wn_operator != OPR_LDID && wn_operator != OPR_ILOAD ) {
04008 combine = FALSE;
04009 record_combine_loads_failure ((INT32) VHO_Srcpos, __LINE__);
04010 break;
04011 }
04012 }
04013 else {
04014 combine = FALSE;
04015 record_combine_loads_failure ((INT32) VHO_Srcpos, __LINE__);
04016 break;
04017 }
04018
04019 item_size = TY_size(WN_ty(lwn));
04020
04021 if ( item_size != shift_bytes ) {
04022 combine = FALSE;
04023 record_combine_loads_failure ((INT32) VHO_Srcpos, __LINE__);
04024 break;
04025 }
04026
04027 bytes += item_size;
04028
04029 if ( bytes > size ) {
04030 combine = FALSE;
04031 record_combine_loads_failure ((INT32) VHO_Srcpos, __LINE__);
04032 break;
04033 }
04034
04035 opcode = WN_opcode(lwn);
04036 wn_operator = OPCODE_operator(opcode);
04037
04038 if ( wn_operator != load_operator ) {
04039 combine = FALSE;
04040 record_combine_loads_failure ((INT32) VHO_Srcpos, __LINE__);
04041 break;
04042 }
04043
04044 mtype = OPCODE_desc(opcode);
04045
04046 if ( !MTYPE_is_unsigned(mtype) ) {
04047 combine = FALSE;
04048 record_combine_loads_failure ((INT32) VHO_Srcpos, __LINE__);
04049 break;
04050 }
04051
04052 if ( load_operator == OPR_LDID ) {
04053 if ( WN_st(source) != WN_st(lwn)
04054 && WN_offset(source) != WN_offset(lwn) + last_item_size ) {
04055 combine = FALSE;
04056 record_combine_loads_failure ((INT32) VHO_Srcpos, __LINE__);
04057 break;
04058 }
04059 }
04060 else if ( load_operator == OPR_ILOAD ) {
04061 awn1 = WN_kid0(source);
04062 awn2 = WN_kid0(lwn);
04063 if ( WN_load_offset(source) == WN_load_offset(lwn) + last_item_size ) {
04064 if ( WN_Simp_Compare_Trees ( awn1, awn2 ) ) {
04065 combine = FALSE;
04066 record_combine_loads_failure ((INT32) VHO_Srcpos, __LINE__);
04067 break;
04068 }
04069 }
04070 else if ( WN_load_offset(source) == WN_load_offset(lwn) ) {
04071 if ( WN_operator(awn1) == OPR_ARRAY
04072 && WN_operator(WN_kid(awn1,last_index)) == OPR_INTCONST ) {
04073 WN_const_val(WN_kid(awn1,last_index)) -= 1;
04074
04075 if ( WN_Simp_Compare_Trees ( awn1, awn2 ) ) {
04076 WN_const_val(WN_kid(awn1,last_index)) += 1;
04077 combine = FALSE;
04078 record_combine_loads_failure ((INT32) VHO_Srcpos, __LINE__);
04079 break;
04080 }
04081 else
04082 WN_const_val(WN_kid(awn1,last_index)) += 1;
04083 }
04084 else {
04085 combine = FALSE;
04086 record_combine_loads_failure ((INT32) VHO_Srcpos, __LINE__);
04087 break;
04088 }
04089 }
04090 else {
04091 combine = FALSE;
04092 record_combine_loads_failure ((INT32) VHO_Srcpos, __LINE__);
04093 break;
04094 }
04095 }
04096 else {
04097 combine = FALSE;
04098 record_combine_loads_failure ((INT32) VHO_Srcpos, __LINE__);
04099 break;
04100 }
04101
04102 source = lwn;
04103 last_item_size = item_size;
04104 }
04105 }
04106
04107 if ( combine && bytes == size ) {
04108 TY_IDX aty_idx;
04109 TY_IDX uty_idx;
04110 TY_IDX pty_idx;
04111
04112 if ( size == 4 ) {
04113 aty_idx = Be_Type_Tbl(MTYPE_U4);
04114 uty_idx = vho_u4a1_ty_idx;
04115
04116 if ( uty_idx == (TY_IDX) 0 ) {
04117 uty_idx = aty_idx;
04118 Set_TY_align (uty_idx, 1);
04119 pty_idx = Make_Pointer_Type ( uty_idx, TRUE );
04120
04121 vho_u4a1_ty_idx = uty_idx;
04122 }
04123 else
04124 pty_idx = TY_pointer(uty_idx);
04125 }
04126 else {
04127 aty_idx = Be_Type_Tbl(MTYPE_U8);
04128 uty_idx = vho_u8a1_ty_idx;
04129
04130 if ( uty_idx == (TY_IDX) 0 ) {
04131 uty_idx = aty_idx;
04132 Set_TY_align (uty_idx, 1);
04133 pty_idx = Make_Pointer_Type ( uty_idx, TRUE );
04134
04135 vho_u8a1_ty_idx = uty_idx;
04136 }
04137 else
04138 pty_idx = TY_pointer(uty_idx);
04139 }
04140
04141 if ( load_operator == OPR_LDID ) {
04142 lwn = WN_COPY_Tree(lwn);
04143 WN_DELETE_Tree(wn);
04144 wn = lwn;
04145 opcode = size == 4 ? OPC_U4U4LDID : OPC_U8U8LDID;
04146 WN_set_opcode(wn,opcode);
04147 WN_set_ty(wn,uty_idx);
04148 }
04149 else {
04150 lwn = WN_COPY_Tree(lwn);
04151 WN_DELETE_Tree(wn);
04152 wn = lwn;
04153 opcode = size == 4 ? OPC_U4U4ILOAD : OPC_U8U8ILOAD;
04154 WN_set_opcode(wn,opcode);
04155 WN_set_ty(wn,aty_idx);
04156 WN_set_load_addr_ty(wn,pty_idx);
04157 }
04158 }
04159
04160 return wn;
04161 }
04162
04163 #ifdef KEY
04164
04165
04166
04167
04168
04169 static inline BOOL
04170 traverse_struct (const TY_IDX ty)
04171 {
04172 Is_True (TY_size(ty) <= 8, ("Type size cannot exceed 8"));
04173 if (TY_kind (ty) == KIND_STRUCT)
04174 {
04175 FLD_ITER fld_iter = Make_fld_iter(TY_fld(ty));
04176 do
04177 {
04178 FLD_HANDLE fld(fld_iter);
04179 if (TY_size(FLD_type(fld)) == 0)
04180 continue;
04181 if (!traverse_struct (FLD_type(fld))) return 0;
04182 } while (!FLD_last_field(fld_iter++));
04183 }
04184 else if (TY_kind (ty) == KIND_ARRAY)
04185 return traverse_struct (TY_etype (ty));
04186 else
04187 switch (TY_mtype (ty))
04188 {
04189 case MTYPE_F4:
04190 case MTYPE_F8:
04191 case MTYPE_C4: return 0;
04192 default: return 1;
04193 }
04194
04195 return 1;
04196 }
04197
04198
04199
04200 static inline WN *
04201 vho_lower_mparm (WN * wn)
04202 {
04203 WN * kid = WN_kid0 (wn);
04204 if (WN_opcode (kid) != OPC_MMLDID) return wn;
04205
04206 TY_IDX ty = WN_ty (kid);
04207 INT64 bytes = TY_size (ty);
04208
04209 if (VHO_Struct_Opt &&
04210 (bytes == 4 || bytes == 8) &&
04211 TY_size (WN_ty (wn)) == bytes &&
04212 ST_class (WN_st (kid)) != CLASS_PREG
04213 #ifdef TARG_X8664
04214 && (Is_Target_32bit() ||
04215 traverse_struct (WN_ty (wn)))
04216 #elif defined(TARG_MIPS) || defined(TARG_IA64)
04217 && traverse_struct (WN_ty(wn))
04218 #endif
04219 #if defined(TARG_SL)
04220 && (bytes == 4)
04221 #endif
04222 )
04223 {
04224 TYPE_ID mtype = (bytes == 4) ? MTYPE_U4 : MTYPE_U8;
04225 WN_set_rtype (wn, mtype);
04226 WN_set_rtype (kid, mtype);
04227 WN_set_desc (kid, mtype);
04228
04229
04230
04231 INT field_id;
04232 Is_True (WN_field_id(kid) == 0,("vho_lower_mparm: Expected field-id zero"));
04233 if ((TY_kind(ty) == KIND_STRUCT) &&
04234 (field_id = single_field_in_struct (ty)))
04235 WN_set_field_id (kid, field_id);
04236 }
04237
04238 return wn;
04239 }
04240 #endif
04241
04242
04243
04244
04245
04246
04247
04248
04249
04250
04251
04252
04253
04254
04255
04256 static WN *
04257 vho_lower_expr ( WN * wn, WN * block, BOOL_INFO * bool_info, BOOL is_return )
04258 {
04259 OPCODE opcode;
04260 OPERATOR wn_operator;
04261 mINT16 nkids;
04262 mINT16 i;
04263
04264 opcode = WN_opcode(wn);
04265 wn_operator = OPCODE_operator(opcode);
04266 nkids = WN_kid_count(wn);
04267
04268 switch ( wn_operator ) {
04269
04270 case OPR_ILOAD:
04271
04272 WN_kid0(wn) = vho_lower_expr (WN_kid0(wn), block, NULL);
04273
04274 if ( VHO_Iload_Opt
04275 && WN_operator(WN_kid0(wn)) == OPR_LDA ) {
04276
04277 INT64 offset;
04278
04279 offset = WN_load_offset(wn) + WN_lda_offset(WN_kid0(wn));
04280
04281 if ( offset >= INT32_MIN && offset <= INT32_MAX ) {
04282
04283 WN * wn1;
04284
04285 wn1 = WN_CreateLdid ( OPCODE_make_op ( OPR_LDID,
04286 OPCODE_rtype(opcode),
04287 OPCODE_desc(opcode) ),
04288 offset,
04289 WN_st_idx(WN_kid0(wn)),
04290 WN_ty(wn),
04291 WN_field_id(wn) );
04292
04293
04294
04295
04296
04297
04298 wn = wn1;
04299 }
04300 }
04301
04302 break;
04303
04304 case OPR_ILOADX:
04305
04306 FmtAssert ( TRUE, ("unexpected operator encountered in vho_lower") );
04307 break;
04308
04309 case OPR_MLOAD:
04310
04311 WN_kid0(wn) = vho_lower_expr (WN_kid0(wn), block, NULL);
04312 WN_kid1(wn) = vho_lower_expr (WN_kid1(wn), block, NULL);
04313 break;
04314
04315 case OPR_ARRAY:
04316
04317 WN_kid0(wn) = vho_lower_expr (WN_kid0(wn), block, NULL);
04318
04319 for ( i = (nkids + 1) >> 1; i < nkids; i++ )
04320 WN_kid(wn,i) = vho_lower_expr (WN_kid(wn,i), block, NULL);
04321 break;
04322
04323 case OPR_INTRINSIC_OP:
04324
04325 #ifndef TARG_X8664
04326 for ( i = 0; i < nkids; i++ )
04327 WN_kid(wn,i) = vho_lower_expr (WN_kid(wn,i), block, NULL);
04328 break;
04329 #else
04330 {
04331
04332
04333
04334 if ( WN_intrinsic(wn) == INTRN_F8I4EXPEXPR ||
04335 WN_intrinsic(wn) == INTRN_F4I4EXPEXPR ) {
04336 WN* parm1 = WN_kid1(wn);
04337 WN* exp = WN_kid0(parm1);
04338 if (WN_operator(exp) == OPR_INTCONST &&
04339 WN_const_val(exp) > 0 &&
04340 WN_const_val(exp) <= 5) {
04341 INT n = WN_const_val(exp);
04342 WN_kid0(WN_kid0(wn)) = vho_lower_expr(WN_kid0(WN_kid0(wn)),
04343 block, NULL);
04344 WN* opnd = WN_COPY_Tree ( WN_kid0(WN_kid0(wn)) );
04345 if ( n == 1 ) {
04346 wn = opnd; break;
04347 }
04348 wn = WN_Mpy(WN_rtype(wn), opnd, WN_COPY_Tree ( opnd )); n-= 2;
04349 for (;n > 0; n--)
04350 wn = WN_Mpy(WN_rtype(wn), wn, WN_COPY_Tree ( opnd ));
04351 break;
04352 }
04353 }
04354
04355 for ( i = 0; i < nkids; i++ )
04356 WN_kid(wn,i) = vho_lower_expr (WN_kid(wn,i), block, NULL);
04357 break;
04358 }
04359 #endif
04360
04361 case OPR_TAS:
04362
04363 WN_kid0(wn) = vho_lower_expr (WN_kid0(wn), block, NULL);
04364 break;
04365
04366 case OPR_SELECT:
04367
04368 WN_kid0(wn) = vho_lower_expr (WN_kid0(wn), block, NULL);
04369 WN_kid1(wn) = vho_lower_expr (WN_kid1(wn), block, NULL);
04370 WN_kid2(wn) = vho_lower_expr (WN_kid2(wn), block, NULL);
04371 break;
04372
04373 case OPR_CSELECT:
04374
04375 wn = vho_lower_cselect ( wn, block, bool_info);
04376 break;
04377
04378 case OPR_CVT:
04379 case OPR_CVTL:
04380
04381 WN_kid0(wn) = vho_lower_expr (WN_kid0(wn), block, NULL);
04382 break;
04383
04384 case OPR_NEG:
04385 case OPR_ABS:
04386 case OPR_SQRT:
04387 case OPR_REALPART:
04388 case OPR_IMAGPART:
04389 case OPR_PAREN:
04390 case OPR_RND:
04391 case OPR_TRUNC:
04392 case OPR_CEIL:
04393 case OPR_FLOOR:
04394 case OPR_BNOT:
04395 case OPR_LNOT:
04396 case OPR_ALLOCA:
04397 case OPR_EXTRACT_BITS:
04398
04399 WN_kid0(wn) = vho_lower_expr (WN_kid0(wn), block, NULL);
04400 break;
04401
04402 case OPR_ASM_INPUT:
04403
04404 WN_kid0(wn) = vho_lower_expr (WN_kid0(wn), block, NULL);
04405 break;
04406
04407 case OPR_ADD:
04408 case OPR_SUB:
04409 case OPR_MPY:
04410 case OPR_DIV:
04411 case OPR_MOD:
04412 case OPR_REM:
04413 case OPR_DIVREM:
04414 #ifdef KEY
04415 case OPR_COMPOSE_BITS:
04416 #endif
04417
04418 WN_kid0(wn) = vho_lower_expr (WN_kid0(wn), block, NULL);
04419 WN_kid1(wn) = vho_lower_expr (WN_kid1(wn), block, NULL);
04420
04421 if ( VHO_Combine_Loads && wn_operator == OPR_ADD )
04422 wn = vho_lower_combine_loads ( wn );
04423 break;
04424
04425 case OPR_LOWPART:
04426 case OPR_HIGHPART:
04427
04428 WN_kid0(wn) = vho_lower_expr (WN_kid0(wn), block, NULL);
04429 break;
04430
04431 case OPR_MAX:
04432 case OPR_MIN:
04433 case OPR_MINMAX:
04434
04435 WN_kid0(wn) = vho_lower_expr (WN_kid0(wn), block, NULL);
04436 WN_kid1(wn) = vho_lower_expr (WN_kid1(wn), block, NULL);
04437 break;
04438
04439 case OPR_MINPART:
04440 case OPR_MAXPART:
04441
04442 WN_kid0(wn) = vho_lower_expr (WN_kid0(wn), block, NULL);
04443 break;
04444
04445 case OPR_BAND:
04446 case OPR_BIOR:
04447 case OPR_BNOR:
04448 case OPR_BXOR:
04449 case OPR_LAND:
04450 case OPR_LIOR:
04451
04452 WN_kid0(wn) = vho_lower_expr (WN_kid0(wn), block, NULL);
04453 WN_kid1(wn) = vho_lower_expr (WN_kid1(wn), block, NULL);
04454
04455 if ( VHO_Combine_Loads && wn_operator == OPR_BIOR )
04456 wn = vho_lower_combine_loads ( wn );
04457 break;
04458
04459 case OPR_CAND:
04460 case OPR_CIOR:
04461
04462 wn = vho_lower_cand_cior ( wn, block, bool_info );
04463 break;
04464
04465 case OPR_SHL:
04466 case OPR_ASHR:
04467 case OPR_LSHR:
04468 case OPR_COMPLEX:
04469
04470 WN_kid0(wn) = vho_lower_expr (WN_kid0(wn), block, NULL);
04471 WN_kid1(wn) = vho_lower_expr (WN_kid1(wn), block, NULL);
04472 break;
04473
04474 case OPR_RECIP:
04475 case OPR_RSQRT:
04476
04477 WN_kid0(wn) = vho_lower_expr (WN_kid0(wn), block, NULL);
04478 break;
04479
04480 case OPR_MADD:
04481 case OPR_MSUB:
04482 case OPR_NMADD:
04483 case OPR_NMSUB:
04484
04485 WN_kid0(wn) = vho_lower_expr (WN_kid0(wn), block, NULL);
04486 WN_kid1(wn) = vho_lower_expr (WN_kid1(wn), block, NULL);
04487 WN_kid2(wn) = vho_lower_expr (WN_kid2(wn), block, NULL);
04488 break;
04489
04490 case OPR_IO_ITEM:
04491
04492 for ( i = 0; i < nkids; i++ )
04493 WN_kid(wn,i) = vho_lower_expr (WN_kid(wn,i), block, NULL);
04494 break;
04495
04496 case OPR_EQ:
04497 case OPR_NE:
04498 case OPR_GT:
04499 case OPR_GE:
04500 case OPR_LT:
04501 case OPR_LE:
04502
04503 WN_kid0(wn) = vho_lower_expr (WN_kid0(wn), block, NULL);
04504 WN_kid1(wn) = vho_lower_expr (WN_kid1(wn), block, NULL);
04505 break;
04506
04507 case OPR_LDID:
04508 #ifdef TARG_NVISA
04509
04510 if (ST_class(WN_st(wn)) == CLASS_VAR) {
04511 TY_IDX ty = ST_type(WN_st(wn));
04512 if (TY_kind(ty) == KIND_STRUCT && WN_offset(wn) >= TY_size(ty))
04513 {
04514 ErrMsgSrcpos(EC_Load_Past_Struct, VHO_Srcpos);
04515 }
04516 }
04517 #endif
04518 break;
04519
04520 case OPR_LDA:
04521 case OPR_CONST:
04522 case OPR_INTCONST:
04523 case OPR_IDNAME:
04524
04525
04526 break;
04527
04528 case OPR_LOOP_INFO:
04529
04530 FmtAssert ( TRUE, ("unexpected operator encountered in vho_lower") );
04531 break;
04532
04533 case OPR_PARM:
04534
04535 #ifdef KEY // bug 7741
04536 wn = vho_lower_mparm (wn);
04537 #endif
04538 WN_kid0(wn) = vho_lower_expr (WN_kid0(wn), block, NULL);
04539 break;
04540
04541 case OPR_TRIPLET:
04542 case OPR_ARRAYEXP:
04543 case OPR_ARRSECTION:
04544 case OPR_WHERE:
04545 case OPR_OPT_RESERVE2:
04546
04547 FmtAssert ( TRUE, ("unexpected operator encountered in vho_lower") );
04548 break;
04549
04550 case OPR_COMMA:
04551
04552 wn = vho_lower_comma ( wn, block, bool_info, is_return );
04553
04554
04555
04556
04557
04558 break;
04559
04560 case OPR_RCOMMA:
04561
04562 wn = vho_lower_rcomma ( wn, block, bool_info );
04563 break;
04564
04565 case OPR_HIGHMPY:
04566 case OPR_XMPY:
04567
04568 break;
04569
04570 case OPR_RROTATE:
04571 {
04572 #ifdef TARG_X8664
04573
04574
04575 if (!VHO_Generate_Rrotate_Set && PU_cxx_lang (Get_Current_PU()) &&
04576 (Is_Target_64bit() || MTYPE_byte_size(WN_desc(wn)) <= 4))
04577 VHO_Generate_Rrotate = TRUE;
04578
04579 if (!VHO_Generate_Rrotate)
04580 #endif
04581 {
04582 TYPE_ID desc = WN_desc(wn);
04583 TYPE_ID rtype = WN_rtype(wn);
04584 INT32 size = 8 * TY_size (Be_Type_Tbl (desc));
04585 WN *wn0 = vho_lower_expr (WN_kid0(wn), block, NULL);
04586 WN *wn1 = vho_lower_expr (WN_kid1(wn), block, NULL);
04587 TYPE_ID shift_rtype = WN_rtype(wn1);
04588 WN *rshift = WN_Lshr (rtype, WN_COPY_Tree (wn0), WN_COPY_Tree (wn1));
04589 WN *lshift = WN_Shl (rtype, wn0,
04590 WN_Binary (OPR_SUB, shift_rtype,
04591 WN_Intconst (shift_rtype, size),
04592 wn1));
04593 #ifdef TARG_X8664 // bug 4552
04594
04595 if (size < MTYPE_size_min(rtype))
04596 lshift = WN_CreateCvtl(OPR_CVTL, Mtype_TransferSign(MTYPE_U4, rtype),
04597 MTYPE_V, size, lshift);
04598 #endif
04599 wn = WN_Bior (rtype, lshift, rshift);
04600 }
04601 #ifdef TARG_X8664
04602 else
04603 {
04604 WN_kid0 (wn) = vho_lower_expr (WN_kid0(wn), block, NULL);
04605 WN_kid1 (wn) = vho_lower_expr (WN_kid1(wn), block, NULL);
04606 }
04607 #endif // TARG_X8664
04608 break;
04609 }
04610
04611 default:
04612
04613 FmtAssert ( TRUE, ("unknown operator encountered in vho_lower_expr") );
04614 break;
04615 }
04616
04617 return wn;
04618 }
04619
04620
04621 static WN *
04622 vho_lower_compgoto ( WN * wn, WN * block )
04623 {
04624 WN_kid0(wn) = vho_lower_expr ( WN_kid0(wn), block, NULL );
04625 WN_kid1(wn) = vho_lower_block ( WN_kid1(wn) );
04626 return wn;
04627 }
04628
04629
04630 static WN *
04631 vho_lower_switch ( WN * wn, WN * block )
04632 {
04633 WN_kid0(wn) = vho_lower_expr ( WN_kid0(wn), block, NULL );
04634 wn = VHO_Lower_Switch ( wn );
04635 return wn;
04636 }
04637
04638
04639 static WN *
04640 vho_lower_casegoto ( WN * wn, WN * block )
04641 {
04642 return wn;
04643 }
04644
04645
04646 static WN *
04647 vho_lower_truebr ( WN * wn, WN * block )
04648 {
04649 WN * test;
04650 WN * test_block;
04651 BOOL_INFO bool_info;
04652
04653 test_block = WN_CreateBlock ();
04654 WN_Set_Linenum ( test_block, VHO_Srcpos );
04655
04656 vho_initialize_bool_info (&bool_info);
04657 bool_info.true_label = WN_label_number(wn);
04658
04659 LABEL_Init (New_LABEL (CURRENT_SYMTAB, bool_info.false_label),
04660 0, LKIND_DEFAULT);
04661
04662 test = vho_lower_expr ( WN_kid0(wn), test_block, &bool_info );
04663
04664 if ( WN_first(test_block) ) {
04665 WN_INSERT_BlockLast ( block, test_block );
04666 }
04667
04668 if ( test ) {
04669 WN_kid0(wn) = test;
04670 }
04671
04672 else {
04673
04674
04675
04676
04677 WN *wn_goto = WN_CreateGoto ( (ST_IDX) NULL, bool_info.true_label );
04678 WN_Set_Linenum ( wn_goto, VHO_Srcpos );
04679 WN_INSERT_BlockLast ( block, wn_goto );
04680
04681 WN *wn_label
04682 = WN_CreateLabel ( (ST_IDX) 0, bool_info.false_label, 0, NULL );
04683 WN_Set_Linenum ( wn_label, VHO_Srcpos );
04684 WN_INSERT_BlockLast ( block, wn_label );
04685
04686
04687
04688 wn = NULL;
04689 }
04690
04691 return wn;
04692 }
04693
04694
04695 static WN *
04696 vho_lower_return ( WN * wn, WN * block )
04697 {
04698 return wn;
04699 }
04700
04701 static BOOL
04702 vho_singleton_field (TY_IDX ty_idx)
04703 {
04704 return FALSE;
04705 }
04706
04707 static WN *
04708 vho_lower_return_val (WN* wn, WN* block)
04709 {
04710 WN_kid0(wn) = vho_lower_expr ( WN_kid0(wn), block, NULL, WN_rtype(wn)==MTYPE_M );
04711 return wn;
04712 }
04713
04714 static WN *
04715 vho_lower_istore ( WN * wn, WN * block )
04716 {
04717 WN_kid0(wn) = vho_lower_expr ( WN_kid0(wn), block, NULL );
04718 WN_kid1(wn) = vho_lower_expr ( WN_kid1(wn), block, NULL );
04719 return wn;
04720 }
04721
04722
04723 static WN *
04724 vho_lower_mstore ( WN * wn, WN * block )
04725 {
04726 WN_kid0(wn) = vho_lower_expr ( WN_kid0(wn), block, NULL );
04727 WN_kid1(wn) = vho_lower_expr ( WN_kid1(wn), block, NULL );
04728 WN_kid(wn,2) = vho_lower_expr ( WN_kid(wn,2), block, NULL );
04729 wn = VHO_Lower_Mstore ( wn );
04730
04731 return wn;
04732 }
04733
04734
04735 static WN *
04736 vho_lower_stid ( WN * wn, WN * block )
04737 {
04738 WN_kid0(wn) = vho_lower_expr ( WN_kid0(wn), block, NULL );
04739 if (WN_desc(wn) == MTYPE_M) {
04740
04741 wn = VHO_Lower_Mstid (wn);
04742 }
04743
04744 return wn;
04745 }
04746
04747
04748 static WN *
04749 vho_lower_call ( WN * wn, WN * block )
04750 {
04751 INT32 i;
04752 #ifdef TARG_NVISA
04753 if ((!ST_is_export_local(WN_st(wn)) || ST_sclass(WN_st(wn)) == SCLASS_EXTERN)
04754 && !CLIST_enabled)
04755 {
04756
04757 ErrMsgSrcpos(EC_No_Calls, WN_Get_Linenum(wn), ST_name(WN_st(wn)));
04758 }
04759 #endif
04760
04761 for ( i = 0; i < WN_kid_count(wn); i++ )
04762 WN_actual(wn,i) = vho_lower_expr ( WN_actual(wn,i), block, NULL );
04763
04764 return wn;
04765 }
04766
04767 static char * extract_pu_name(char * src_pu_name )
04768 {
04769 if (src_pu_name == NULL)
04770 return NULL;
04771 char * pu_name = strchr(src_pu_name,'/');
04772 if (pu_name == NULL)
04773 return NULL;
04774 else
04775 {
04776 pu_name ++;
04777 return pu_name;
04778 }
04779 }
04780
04781 BOOL
04782 Is_Return_Store_Stmt( WN *wn )
04783 {
04784 if ( wn && WN_operator( wn ) == OPR_STID ) {
04785 WN *val = WN_kid( wn, 0 );
04786 if ( WN_operator( val ) == OPR_LDID ) {
04787 ST *st = WN_st( val );
04788 if ( ST_sym_class( st ) == CLASS_PREG
04789 && ( Is_Return_Preg( WN_offset( val ) )
04790 || st == Return_Val_Preg ) )
04791 return TRUE;
04792 }
04793 }
04794
04795 return FALSE;
04796 }
04797
04798 int
04799 GetPUSizeFromEnv(char * puname)
04800 {
04801 if (puname == NULL)
04802 return -1;
04803
04804 char *p = getenv (puname);
04805 int num;
04806 if (p)
04807 num = atoi(p);
04808 else num = 1;
04809 return num;
04810 }
04811
04812 static WN *
04813 vho_lower_if ( WN * wn, WN *block );
04814
04815
04816 int Get_len_and_goaheadlen(char ** str)
04817 {
04818 int len = atoi(*str);
04819 if (len>0 && len < strlen(*str) )
04820 {
04821 int ll = 0;
04822 if (len < 10)
04823 ll = 1;
04824 else if (len<100)
04825 ll = 2;
04826 else if (len<1000)
04827 ll = 3;
04828 else
04829 {
04830
04831 return 0;
04832 }
04833 *str += ll;
04834 if (len < strlen(*str))
04835 *str += len;
04836
04837 }
04838 return len;
04839 }
04840
04845 int Is_similar_cppname(char * name1, char * name2)
04846 {
04847 char * class_name_start1, * class_name_start2;
04848 class_name_start1 = strstr(name1,"__C");
04849 class_name_start2 = strstr(name2,"__C");
04850 if (class_name_start1 == NULL || class_name_start2 == NULL)
04851 return 0;
04852 class_name_start1 += strlen("__C");
04853 class_name_start2 += strlen("__C");
04854 int pu_name_len1 = class_name_start1 - name1;
04855 int pu_name_len2 = class_name_start2 - name2;
04856
04857 if (pu_name_len1 != pu_name_len2 || strncmp(name1,name2,pu_name_len1) != 0 )
04858 return 0;
04859
04860 int class_name_len1, class_name_len2;
04861 class_name_len1 = 0;
04862 class_name_len2 = 0;
04863 class_name_len1 = Get_len_and_goaheadlen(&class_name_start1);
04864 class_name_len2 = Get_len_and_goaheadlen(&class_name_start2);
04865 if (class_name_len1 == 0 || class_name_len2 == 0)
04866 return 0;
04867 if (strcmp(class_name_start1,class_name_start2) != 0)
04868 return 0;
04869 return 1;
04870 }
04871
04872 static WN *
04873 vho_lower_icall ( WN * wn, WN * block )
04874 {
04875 if ( ! VHO_Icall_Devir )
04876 return vho_lower_call(wn, block);
04877
04878
04879
04880
04881
04882
04883
04884
04885
04886
04887
04888
04889
04890
04891
04892
04893
04894
04895
04896
04897
04898
04899
04900
04901
04902
04903
04904
04905
04906
04907
04908
04909
04910
04911
04912
04913
04914
04915
04916
04917
04918
04919
04920
04921
04922
04923
04924
04925
04926
04927
04928
04929 if (Cur_PU_Feedback == NULL)
04930 {
04931 return vho_lower_call(wn,block);
04932 }
04933
04934 const FB_Info_Icall & info_icall = Cur_PU_Feedback->Query_icall(wn);
04935 const FB_Info_Call & info_call = Cur_PU_Feedback->Query_call(wn);
04936 if ( info_icall.Is_uninit() )
04937 {
04938 return vho_lower_call(wn,block);
04939 }
04940
04941 if ( info_icall.tnv._exec_counter == 0 )
04942 {
04943 Is_True(info_icall.tnv._counters[0]==0,("_counters[0] must be 0 if _exec_counter is 0"));
04944 return vho_lower_call(wn,block);
04945 }
04946 else
04947 Is_True(info_icall.tnv._values[0] >0, ("function address must be positive!"));
04948
04949 char * nameoffootmp = PU_Addr_Name_Map[info_icall.tnv._values[0]];
04950 int sizeoffoo = PU_Addr_Pusize_Map[info_icall.tnv._values[0]];
04951 if ( nameoffootmp == NULL)
04952 {
04953 return vho_lower_call(wn,block);
04954 }
04955
04956 char * nameoffoo1 = extract_pu_name(nameoffootmp);
04957 Is_True(nameoffoo1!=NULL,("Devirtualize: did not extract right pu_name in PU_Addr_Name_Map for address <%llu>",info_icall.tnv._values[0]));
04958
04959
04960 ST * st_foo1 = NULL;
04961 TY_IDX ty_foo1;
04962
04963 ST_TAB * parray = Scope_tab[GLOBAL_SYMTAB].st_tab;
04964 UINT32 last = (*parray).Size();
04965 UINT32 first = 1;
04966
04967 INT num_pu_found = 0;
04968 while (first < last){
04969 ST * block = &(*parray)[first];
04970 UINT32 size = (*parray).Get_block_size(first);
04971 for (UINT32 i = 0; i < size; ++i, ++block){
04972 if (ST_sym_class(block) != CLASS_FUNC)
04973 continue;
04974 STR_IDX str_idx = ST_name_idx(block);
04975 if (strcmp(nameoffoo1,&Str_Table[str_idx]) == 0)
04976 {
04977 if (num_pu_found > 0)
04978 {
04979 }
04980 st_foo1 = block;
04981 ty_foo1 = ST_pu_type(block);
04982 num_pu_found ++;
04983
04984
04985 }
04986 }
04987 first += size;
04988 }
04989
04990 if (num_pu_found == 0)
04991 {
04992 parray = Scope_tab[GLOBAL_SYMTAB].st_tab;
04993 last = (*parray).Size();
04994 first = 1;
04995 while (first < last){
04996 ST * block = &(*parray)[first];
04997 UINT32 size = (*parray).Get_block_size(first);
04998 for (UINT32 i = 0; i < size; ++i, ++block){
04999 if (ST_sym_class(block) != CLASS_FUNC)
05000 continue;
05001 STR_IDX str_idx = ST_name_idx(block);
05002 if (strcmp(nameoffoo1,&Str_Table[str_idx]) == 0)
05003 {
05004 st_foo1 = block;
05005 ty_foo1 = ST_pu_type(block);
05006 num_pu_found ++;
05007 }
05008 else if(Is_similar_cppname(nameoffoo1,&Str_Table[str_idx]))
05009 {
05010 if (num_pu_found == 0)
05011 {
05012 ST * newst = Copy_ST(block);
05013 STR_IDX newidx = Save_Str(nameoffoo1);
05014 Set_ST_name(newst,newidx);
05015 Set_ST_sclass(newst,SCLASS_EXTERN);
05016 st_foo1 = newst;
05017 ty_foo1 = ST_pu_type(newst);
05018
05019 }
05020 else
05021 {
05022
05023 }
05024 num_pu_found ++;
05025 }
05026 }
05027 first += size;
05028 }
05029 }
05030
05031
05032 extern char * Src_File_Name;
05033
05034 char strii[20];
05035 char tmpfilename[50];
05036
05037 char *p = getenv ("VHO_IGNORE_FILE_NUM");
05038 int ii, num_files;
05039 if (p)
05040 num_files = atoi(p);
05041 else num_files = 0;
05042 for ( ii=1; ii<=num_files; ii++)
05043 {
05044 sprintf(strii,"%d",ii);
05045 strcpy(tmpfilename,"VHO_IGNORE_FILE_NAME");
05046 strcat(tmpfilename,strii);
05047 p = getenv (tmpfilename);
05048 if ( !p )
05049 continue;
05050 if ( strcmp(Src_File_Name, p) == 0)
05051 {
05052 return vho_lower_call(wn,block);
05053 }
05054 }
05055
05056 if ( (float)info_icall.tnv._exec_counter != info_call.freq_entry._value )
05057 {
05058 return vho_lower_call(wn,block);
05059 }
05060
05061 float ratio = info_icall.tnv._counters[0] * 1.0 / info_icall.tnv._exec_counter;
05062 if (ratio < 0.98 )
05063 {
05064 return vho_lower_call(wn,block);
05065 }
05066 else if ( info_icall.tnv._exec_counter < 50 )
05067 {
05068 return vho_lower_call(wn,block);
05069 }
05070 else if (sizeoffoo < 20 && info_icall.tnv._exec_counter / sizeoffoo < 80 )
05071 {
05072 return vho_lower_call(wn,block);
05073 }
05074 else if (sizeoffoo < 100 && info_icall.tnv._exec_counter / sizeoffoo < 160 )
05075 {
05076 return vho_lower_call(wn,block);
05077 }
05078 else if (sizeoffoo < 200 && info_icall.tnv._exec_counter / sizeoffoo < 320 )
05079 {
05080 return vho_lower_call(wn,block);
05081 }
05082 else if (sizeoffoo < 1000 && info_icall.tnv._exec_counter / sizeoffoo < 640 )
05083 {
05084 return vho_lower_call(wn,block);
05085 }
05086 else if (sizeoffoo > 1000 && info_icall.tnv._exec_counter / sizeoffoo < 1280 )
05087 {
05088 return vho_lower_call(wn,block);
05089 }
05090 else
05091 {
05092 if ( num_pu_found > 0 )
05093 {
05094 DevWarn("Devirtualize:<last decision : willuse>Found <%d> PUs in symbol tables match profiled names <%s>",num_pu_found,nameoffoo1);
05095 }
05096 }
05097
05098
05099 if (num_pu_found == 0)
05100 {
05101 return vho_lower_call(wn,block);
05102 }
05103
05104
05105 WN * wn_if, * test, * if_then, * if_else, *if_then_block, *if_else_block, *wn_ret_value;
05106 WN * tmpkid0, * tmpkid1;
05107 WN * stmt;
05108 #ifdef KEY
05109 const BOOL ptr_is_64bit = MTYPE_bit_size(Pointer_Mtype) == 64;
05110 tmpkid0 = WN_CreateLda( ptr_is_64bit ? OPC_U8LDA : OPC_U4LDA,
05111 0, Make_Pointer_Type (ty_foo1),st_foo1 );
05112 #else
05113 tmpkid0 = WN_CreateLda(OPC_U8LDA,0, Make_Pointer_Type (ty_foo1),st_foo1);
05114 #endif // KEY
05115 tmpkid1 = WN_COPY_Tree(WN_kid(wn,WN_kid_count(wn)-1));
05116
05117 #ifdef KEY
05118 test = WN_Create( ptr_is_64bit ? OPC_U8U8EQ : OPC_U4U4EQ, 2 );
05119 #else
05120 test = WN_Create(OPC_U8U8EQ,2);
05121 #endif // KEY
05122
05123 WN_kid0(test) = tmpkid0;
05124 WN_kid1(test) = tmpkid1;
05125
05126 if_then = WN_Create(WN_opcode(wn),WN_kid_count(wn)-1);
05127 WN_set_operator(if_then,OPR_CALL);
05128 for (int i=0;i<WN_kid_count(if_then);i++)
05129 {
05130 WN_kid(if_then,i) = WN_COPY_Tree(WN_kid(wn,i));
05131 }
05132 WN_st_idx(if_then) = ST_st_idx(st_foo1);
05133
05134 if_then_block = WN_CreateBlock();
05135 WN_INSERT_BlockLast(if_then_block,if_then);
05136 stmt = WN_next(wn);
05137 while ( stmt && Is_Return_Store_Stmt( stmt ) ) {
05138 wn_ret_value = WN_COPY_Tree(stmt);
05139 WN_INSERT_BlockLast(if_then_block,wn_ret_value);
05140 stmt = WN_next(stmt);
05141 }
05142
05143 if_else = WN_COPY_Tree(wn);
05144 if_else_block = WN_CreateBlock();
05145 WN_INSERT_BlockLast(if_else_block,if_else);
05146 stmt = WN_next(wn);
05147 while ( stmt && Is_Return_Store_Stmt( stmt ) ) {
05148 wn_ret_value = WN_COPY_Tree(stmt);
05149 WN_INSERT_BlockLast(if_else_block,wn_ret_value);
05150 stmt = WN_next(stmt);
05151 }
05152
05153
05154 stmt = WN_next(wn);
05155 while ( stmt && Is_Return_Store_Stmt( stmt ) ) {
05156 wn_ret_value = stmt;
05157 stmt = WN_next(stmt);
05158 WN_set_kid_count(wn_ret_value,0);
05159 WN_set_operator(wn_ret_value,OPR_COMMENT);
05160 WN_set_rtype(wn_ret_value,MTYPE_V);
05161 WN_set_desc(wn_ret_value,MTYPE_V);
05162 }
05163
05164 wn_if = WN_CreateIf(test, if_then_block, if_else_block);
05165
05166 if (Cur_PU_Feedback)
05167 Cur_PU_Feedback->FB_lower_icall( wn, if_else, if_then, wn_if );
05168
05169
05170 Cur_PU_Feedback->Delete(wn);
05171
05172
05173 wn_if = vho_lower_if(wn_if,block);
05174
05175 return wn_if;
05176 }
05177
05178
05179 static WN *
05180 vho_lower_intrinsic_call ( WN * wn, WN * block )
05181 {
05182 INT32 i;
05183
05184 for ( i = 0; i < WN_kid_count(wn); i++ )
05185 WN_actual(wn,i) = vho_lower_expr ( WN_actual(wn,i), block, NULL );
05186
05187 return wn;
05188 }
05189
05190
05191 static WN *
05192 vho_lower_eval ( WN * wn, WN * block )
05193 {
05194 WN_kid0(wn) = vho_lower_expr ( WN_kid0(wn), block, NULL );
05195
05196 if ( WN_kid0(wn) )
05197 return wn;
05198
05199 else
05200 return NULL;
05201 }
05202
05203
05204 static WN *
05205 vho_lower_pragma ( WN * wn, WN * block )
05206 {
05207 return wn;
05208 }
05209
05210
05211 static WN *
05212 vho_lower_xpragma ( WN * wn, WN * block )
05213 {
05214 INT32 i;
05215
05216 for ( i = 0; i < WN_kid_count(wn); i++ )
05217 WN_kid(wn, i) = vho_lower_expr ( WN_kid(wn, i), block, NULL );
05218
05219 #ifdef KEY // bug 14036
05220 if (VHO_In_MP_Region_Pragma && WN_kid_count(wn) == 1)
05221 {
05222 WN * kid = WN_kid0(wn);
05223 TY_IDX ty_idx = MTYPE_TO_TY_array[WN_rtype(kid)];
05224 ST * st = Gen_Temp_Symbol (ty_idx, "_mp_xpragma");
05225 WN * stid = WN_Stid(WN_rtype(kid), 0, st, ty_idx, kid);
05226 WN_kid0(wn) = WN_Ldid(WN_rtype(kid), 0, st, ty_idx);
05227 WN_INSERT_BlockLast (block, stid);
05228 }
05229 #endif
05230
05231 return wn;
05232 }
05233
05234
05235 static WN *
05236 vho_lower_prefetch ( WN * wn, WN * block )
05237 {
05238 #ifdef KEY // bug 9499
05239
05240 WN_kid0(wn) = vho_lower_expr ( WN_kid0(wn), block, NULL );
05241 #endif
05242 return wn;
05243 }
05244
05245
05246 static WN *
05247 vho_lower_prefetchx ( WN * wn, WN * block )
05248 {
05249 return wn;
05250 }
05251
05252
05253 static WN *
05254 vho_lower_io ( WN * wn, WN * block )
05255 {
05256 INT32 i;
05257
05258 for ( i = 0; i < WN_kid_count(wn); i++ )
05259 WN_kid(wn, i) = vho_lower_expr ( WN_kid(wn, i), block, NULL );
05260
05261 return wn;
05262 }
05263
05264
05265 static WN *
05266 vho_lower_falsebr ( WN * wn, WN * block )
05267 {
05268 WN * test;
05269 WN * test_block;
05270 BOOL_INFO bool_info;
05271
05272 test_block = WN_CreateBlock ();
05273 WN_Set_Linenum ( test_block, VHO_Srcpos );
05274
05275 vho_initialize_bool_info (&bool_info);
05276 LABEL_Init (New_LABEL (CURRENT_SYMTAB, bool_info.true_label),
05277 0, LKIND_DEFAULT);
05278 bool_info.false_label = WN_label_number(wn);
05279
05280 test = vho_lower_expr ( WN_kid0(wn), test_block, &bool_info );
05281
05282 if ( WN_first(test_block) )
05283 WN_INSERT_BlockLast ( block, test_block );
05284
05285 if ( test ) {
05286
05287 WN_kid0(wn) = test;
05288 }
05289
05290 else {
05291
05292 wn = WN_CreateLabel ( (ST_IDX) 0, bool_info.true_label, 0, NULL );
05293 WN_Set_Linenum ( wn, VHO_Srcpos );
05294 WN_INSERT_BlockLast ( block, wn );
05295
05296 wn = NULL;
05297 }
05298
05299 return wn;
05300 }
05301
05302
05303 static WN *
05304 vho_lower_trap ( WN * wn, WN * block )
05305 {
05306 return wn;
05307 }
05308
05309
05310 static WN *
05311 vho_lower_asm_stmt (WN* wn, WN* block)
05312 {
05313 INT32 i;
05314
05315 for ( i = 2; i < WN_kid_count(wn); i++ )
05316 WN_kid(wn, i) = vho_lower_expr ( WN_kid(wn, i), block, NULL );
05317
05318 return wn;
05319 }
05320
05321 static WN *
05322 vho_lower_stmt ( WN * wn, WN * block )
05323 {
05324 PREG_NUM last_preg;
05325
05326 last_preg = PREG_Table_Size (CURRENT_SYMTAB);
05327
05328 VHO_Srcpos = WN_Get_Linenum(wn);
05329
05330 switch ( WN_operator(wn) ) {
05331
05332 case OPR_DEALLOCA:
05333
05334 break;
05335
05336 case OPR_REGION_EXIT:
05337
05338 break;
05339
05340 case OPR_COMPGOTO:
05341
05342 wn = vho_lower_compgoto ( wn, block );
05343 break;
05344
05345 case OPR_SWITCH:
05346
05347 wn = vho_lower_switch ( wn, block );
05348 break;
05349
05350 case OPR_CASEGOTO:
05351
05352 wn = vho_lower_casegoto ( wn, block );
05353 break;
05354
05355 case OPR_XGOTO:
05356 case OPR_GOTO:
05357 case OPR_AGOTO:
05358 case OPR_ALTENTRY:
05359
05360 break;
05361
05362 case OPR_TRUEBR:
05363
05364 wn = vho_lower_truebr ( wn, block );
05365 break;
05366
05367 case OPR_RETURN:
05368 #ifdef KEY
05369 case OPR_GOTO_OUTER_BLOCK:
05370 #endif
05371
05372 wn = vho_lower_return ( wn, block );
05373 break;
05374
05375 case OPR_RETURN_VAL:
05376
05377 wn = vho_lower_return_val ( wn, block );
05378 break;
05379
05380 case OPR_LABEL:
05381
05382 break;
05383
05384 case OPR_EXC_SCOPE_BEGIN:
05385 case OPR_EXC_SCOPE_END:
05386
05387 break;
05388
05389 case OPR_FORWARD_BARRIER:
05390 case OPR_BACKWARD_BARRIER:
05391
05392 break;
05393
05394 case OPR_ISTORE:
05395
05396 wn = vho_lower_istore ( wn, block );
05397
05398 if ( VHO_Istore_Opt
05399 && WN_operator(WN_kid1(wn)) == OPR_LDA ) {
05400
05401 INT64 offset;
05402 OPCODE opcode;
05403
05404 opcode = WN_opcode(wn);
05405 offset = WN_store_offset(wn) + WN_lda_offset(WN_kid1(wn));
05406
05407 if ( offset >= INT32_MIN && offset <= INT32_MAX ) {
05408
05409 WN * wn1;
05410
05411 wn1 = WN_CreateStid ( OPCODE_make_op ( OPR_STID,
05412 OPCODE_rtype(opcode),
05413 OPCODE_desc(opcode) ),
05414 offset,
05415 WN_st_idx(WN_kid1(wn)),
05416 TY_pointed(WN_ty(wn)),
05417 WN_kid0(wn),
05418 WN_field_id(wn));
05419 WN_Set_Linenum(wn1, WN_Get_Linenum(wn));
05420
05421
05422
05423
05424
05425
05426 wn = wn1;
05427 }
05428 }
05429
05430 if (WN_desc(wn) == MTYPE_M) {
05431 if (WN_operator(wn) == OPR_STID) {
05432 wn = VHO_Lower_Mstid(wn);
05433 } else {
05434 wn = VHO_Lower_Mistore(wn);
05435 }
05436 }
05437
05438 break;
05439
05440 case OPR_ISTOREX:
05441
05442 break;
05443
05444 case OPR_MSTORE:
05445
05446 wn = vho_lower_mstore ( wn, block );
05447 break;
05448
05449 case OPR_STID:
05450
05451 wn = vho_lower_stid ( wn, block );
05452 break;
05453
05454 case OPR_CALL:
05455
05456 wn = vho_lower_call ( wn, block );
05457 break;
05458
05459 case OPR_INTRINSIC_CALL:
05460
05461 wn = vho_lower_intrinsic_call ( wn, block );
05462 break;
05463
05464 case OPR_ICALL:
05465
05466 wn = vho_lower_icall ( wn, block );
05467 break;
05468
05469 case OPR_PICCALL:
05470
05471 break;
05472
05473 case OPR_EVAL:
05474
05475 wn = vho_lower_eval ( wn, block );
05476 break;
05477
05478 case OPR_PRAGMA:
05479
05480 wn = vho_lower_pragma ( wn, block );
05481 break;
05482
05483 case OPR_XPRAGMA:
05484
05485 wn = vho_lower_xpragma ( wn, block );
05486 break;
05487
05488 case OPR_PREFETCH:
05489
05490 wn = vho_lower_prefetch ( wn, block );
05491 break;
05492
05493 case OPR_PREFETCHX:
05494
05495 wn = vho_lower_prefetchx ( wn, block );
05496 break;
05497
05498 case OPR_IO:
05499
05500 wn = vho_lower_io ( wn, block );
05501 break;
05502
05503 case OPR_COMMENT:
05504
05505 break;
05506
05507 case OPR_FALSEBR:
05508
05509 wn = vho_lower_falsebr ( wn, block );
05510 break;
05511
05512 case OPR_TRAP:
05513
05514 wn = vho_lower_trap ( wn, block );
05515 break;
05516
05517 case OPR_ASSERT:
05518
05519 wn = vho_lower_trap ( wn, block );
05520 break;
05521
05522 case OPR_ASM_STMT:
05523
05524 wn = vho_lower_asm_stmt ( wn, block );
05525 break;
05526
05527 default:
05528
05529 break;
05530 }
05531
05532 if ( VHO_Recycle_Pregs )
05533 Reset_PREG_Table_Size (CURRENT_SYMTAB, last_preg);
05534
05535 return wn;
05536 }
05537
05538
05539 #ifdef KEY
05540
05541
05542
05543 static WN *
05544 vho_last_stmt_in_region ( WN * wn, BOOL extract )
05545 {
05546 Is_True (WN_operator(wn) == OPR_REGION,
05547 ("vho_last_stmt_in_region: expects REGION node"));
05548
05549 WN * block = WN_region_body(wn);
05550 WN * last = WN_last(block);
05551
05552 while (last)
05553 {
05554 if (WN_operator(last) == OPR_REGION)
05555 {
05556 block = WN_region_body(last);
05557 last = WN_last(block);
05558 }
05559 else
05560 {
05561 if (extract && WN_operator(last) == OPR_XPRAGMA)
05562 last = WN_EXTRACT_FromBlock (block, last);
05563 break;
05564 }
05565 }
05566
05567 return last;
05568 }
05569
05570 static WN *
05571 vho_lower_region ( WN * wn, WN * block )
05572 {
05573 WN_region_body(wn) = vho_lower_block ( WN_region_body(wn) );
05574
05575 INT region_id = WN_region_id(wn);
05576 if ((WN_region_kind(wn) == REGION_KIND_MP) &&
05577 (current_pu_id < VHO_Disable_MP_PU_Before ||
05578 current_pu_id > VHO_Disable_MP_PU_After ||
05579 current_pu_id == VHO_Disable_MP_PU_Equal ||
05580 region_id < VHO_Disable_MP_Local_Before ||
05581 region_id > VHO_Disable_MP_Local_After ||
05582 region_id == VHO_Disable_MP_Local_Equal)) {
05583 WN* region_body = WN_region_body(wn);
05584 WN* stmt = WN_first(region_body);
05585 WN* next_stmt;
05586 while(stmt) {
05587 next_stmt = WN_next(stmt);
05588 WN_INSERT_BlockLast(block, stmt);
05589 stmt = next_stmt;
05590 }
05591 WN_next(wn) = WN_prev(wn) = NULL;
05592 return NULL;
05593 }
05594
05595
05596 if (WN_region_kind(wn) == REGION_KIND_MP)
05597 {
05598 #ifdef Is_True_On
05599 {
05600
05601
05602
05603 WN * pragmas = WN_first (WN_region_pragmas (wn));
05604 while (pragmas)
05605 {
05606 WN * stmt = NULL;
05607 if (WN_operator(pragmas) == OPR_REGION)
05608 stmt = vho_last_stmt_in_region (pragmas, FALSE);
05609
05610 FmtAssert (WN_operator(pragmas) == OPR_PRAGMA ||
05611 WN_operator(pragmas) == OPR_XPRAGMA ||
05612
05613 (stmt && WN_operator(stmt) == OPR_XPRAGMA),
05614 ("Unexpected node in region pragmas"));
05615 pragmas = WN_next (pragmas);
05616 }
05617 }
05618 #endif // Is_True_On
05619
05620 VHO_In_MP_Region_Pragma = TRUE;
05621 WN_region_pragmas(wn) = vho_lower_block ( WN_region_pragmas(wn) );
05622 VHO_In_MP_Region_Pragma = FALSE;
05623
05624 WN * iter = WN_first (WN_region_pragmas (wn));
05625
05626 while (iter)
05627 {
05628
05629
05630 if ((WN_operator (iter) != OPR_PRAGMA ||
05631 (WN_pragma (iter) == WN_PRAGMA_INLINE_BODY_START ||
05632 WN_pragma (iter) == WN_PRAGMA_INLINE_BODY_END)) &&
05633 WN_operator (iter) != OPR_XPRAGMA)
05634 {
05635 WN * move = iter;
05636
05637 iter = WN_next (iter);
05638
05639 Is_True (WN_next (move), ("Pragma node not found in region pragmas"));
05640
05641 if (WN_operator(move) == OPR_REGION)
05642 {
05643 WN * stmt = vho_last_stmt_in_region (move, TRUE );
05644 if (stmt && WN_operator(stmt) == OPR_XPRAGMA)
05645 WN_INSERT_BlockBefore (WN_region_pragmas (wn), move, stmt);
05646 }
05647 move = WN_EXTRACT_FromBlock (WN_region_pragmas (wn), move);
05648
05649 WN_INSERT_BlockLast (block, move);
05650 }
05651 else iter = WN_next (iter);
05652 }
05653 }
05654
05655
05656
05657
05658 WN * last = WN_last ( WN_region_body (wn) );
05659 if ( last && WN_operator(last) == OPR_COMPGOTO && WN_region_is_EH (wn) )
05660 {
05661 Is_True (WN_first (WN_region_body (wn)) != last, ("No call inside region"));
05662 if (WN_prev (last))
05663 WN_next (WN_prev (last)) = NULL;
05664 WN_last (WN_region_body (wn)) = WN_prev (last);
05665
05666 WN_next (last) = WN_prev (last) = NULL;
05667 WN_INSERT_BlockLast (block, wn);
05668
05669 WN_INSERT_BlockLast (block, last);
05670 wn = NULL;
05671 }
05672 return wn;
05673 }
05674 #else
05675 static WN *
05676 vho_lower_region ( WN * wn )
05677 {
05678 WN_region_body(wn) = vho_lower_block ( WN_region_body(wn) );
05679 return wn;
05680 }
05681 #endif
05682
05683
05684 static WN *
05685 vho_lower_do_loop ( WN * wn, WN *block )
05686 {
05687 WN * start;
05688 WN * end;
05689 WN * step;
05690 WN * lower_block;
05691 WN * do_body;
05692 BOOL_INFO bool_info;
05693 SRCPOS srcpos;
05694
05695 srcpos = VHO_Srcpos;
05696 do_body = vho_lower_block ( WN_do_body(wn) );
05697
05698 lower_block = WN_CreateBlock ();
05699 WN_Set_Linenum ( lower_block, srcpos );
05700
05701 vho_initialize_bool_info (&bool_info);
05702 LABEL_Init (New_LABEL (CURRENT_SYMTAB, bool_info.true_label),
05703 0, LKIND_DEFAULT);
05704 LABEL_Init (New_LABEL (CURRENT_SYMTAB, bool_info.false_label),
05705 0, LKIND_DEFAULT);
05706
05707 #ifdef KEY // bug 6299
05708 start = WN_start(wn);
05709 WN_kid0(start) = vho_lower_expr ( WN_kid0(start), lower_block, &bool_info );
05710 #else
05711 start = vho_lower_expr ( WN_start(wn), lower_block, &bool_info );
05712
05713 FmtAssert ( WN_first(lower_block) == NULL,
05714 ( "lowering of do loop start generated statements" ) );
05715 #endif
05716
05717 end = vho_lower_expr ( WN_end(wn), lower_block, &bool_info );
05718
05719 #ifndef KEY
05720 FmtAssert ( WN_first(lower_block) == NULL,
05721 ( "lowering of do loop test generated statements" ) );
05722 #else
05723 #ifdef Is_True_On
05724
05725 Is_True (WN_first (lower_block) == NULL ||
05726 PU_c_lang (Get_Current_PU()) ||
05727 PU_cxx_lang (Get_Current_PU()) ||
05728 Instrumentation_Enabled,
05729 ("lowering of do loop test generated statements in Fortran"));
05730 #endif
05731
05732
05733 if (WN_first (lower_block))
05734 WN_INSERT_BlockLast (block, lower_block);
05735 #endif // KEY
05736
05737 step = vho_lower_expr ( WN_step(wn), lower_block, &bool_info );
05738
05739 FmtAssert ( WN_first(lower_block) == NULL,
05740 ( "lowering of do loop step generated statements" ) );
05741
05742 Scope_tab [CURRENT_SYMTAB].label_tab->Delete_last (2);
05743
05744
05745 WN_start(wn) = start;
05746 WN_end(wn) = end;
05747 WN_step(wn) = step;
05748 WN_do_body(wn) = do_body;
05749
05750 return wn;
05751 }
05752
05753
05754 static WN *
05755 vho_lower_do_while ( WN * wn, WN *block )
05756 {
05757 WN * test;
05758 WN * test_block;
05759 WN * while_body;
05760 BOOL_INFO bool_info;
05761 LABEL_IDX loop_label;
05762
05763 #ifdef KEY
05764 Misc_Loop_Fusion(wn, block);
05765 #endif
05766 while_body = vho_lower_block (WN_while_body(wn));
05767
05768 test_block = WN_CreateBlock ();
05769 WN_Set_Linenum ( test_block, VHO_Srcpos );
05770
05771 vho_initialize_bool_info (&bool_info);
05772 LABEL_Init (New_LABEL (CURRENT_SYMTAB, bool_info.true_label),
05773 0, LKIND_DEFAULT);
05774 LABEL_Init (New_LABEL (CURRENT_SYMTAB, bool_info.false_label),
05775 0, LKIND_DEFAULT);
05776
05777 test = vho_lower_expr ( WN_while_test(wn), test_block, &bool_info );
05778
05779 if ( bool_info.used_true_label
05780 || bool_info.used_false_label ) {
05781
05782
05783
05784
05785
05786
05787
05788
05789 if ( bool_info.used_true_label )
05790 loop_label = bool_info.true_label;
05791
05792 else
05793 LABEL_Init (New_LABEL (CURRENT_SYMTAB, loop_label),
05794 0, LKIND_DEFAULT);
05795
05796 WN *wn_label = WN_CreateLabel ( (ST_IDX) 0, loop_label, 0, NULL );
05797 WN_Set_Linenum ( wn_label, VHO_Srcpos );
05798 WN_INSERT_BlockLast ( block, wn_label );
05799
05800 WN_INSERT_BlockLast ( block, while_body );
05801
05802 if ( WN_first(test_block) ) {
05803 WN_INSERT_BlockLast ( block, test_block );
05804 }
05805
05806 WN *wn_back_goto = WN_CreateGoto ( (ST_IDX) NULL, loop_label );
05807 WN_Set_Linenum ( wn_back_goto, VHO_Srcpos );
05808 WN_INSERT_BlockLast ( block, wn_back_goto );
05809
05810 if ( bool_info.used_false_label ) {
05811
05812 wn_label = WN_CreateLabel ( (ST_IDX) 0, bool_info.false_label, 0, NULL );
05813 WN_Set_Linenum ( wn_label, VHO_Srcpos );
05814 WN_INSERT_BlockLast ( block, wn_label );
05815 }
05816
05817
05818
05819 wn = NULL;
05820 }
05821
05822 else {
05823
05824 if ( WN_first(test_block) )
05825 WN_INSERT_BlockLast ( while_body, test_block );
05826
05827 WN_while_test(wn) = test;
05828 WN_while_body(wn) = while_body;
05829 }
05830
05831 return wn;
05832 }
05833
05834
05835
05836 static BOOL vho_lower_labels_defined = FALSE;
05837 static BOOL vho_lower_too_many_label_definitions = FALSE;
05838
05839 typedef struct label_map_t {
05840 LABEL_IDX old_label;
05841 LABEL_IDX new_label;
05842 INT32 label_flag;
05843 } LABEL_MAP;
05844
05845 static LABEL_MAP vho_lower_label_map [16];
05846 static INT32 vho_lower_label_map_max = 16;
05847 static INT32 vho_lower_label_map_index = -1;
05848
05849 static void
05850 vho_lower_check_labels ( WN * wn )
05851 {
05852 WN * wn1;
05853 INT32 i;
05854
05855 switch ( WN_operator(wn) ) {
05856
05857 case OPR_FUNC_ENTRY:
05858
05859 vho_lower_check_labels ( WN_func_body(wn) );
05860 break;
05861
05862 case OPR_BLOCK:
05863
05864 for ( wn1 = WN_first(wn); wn1; wn1 = WN_next(wn1) )
05865 vho_lower_check_labels ( wn1 );
05866 break;
05867
05868 case OPR_REGION:
05869
05870 vho_lower_check_labels ( WN_region_body(wn) );
05871 break;
05872
05873 case OPR_REGION_EXIT:
05874
05875 break;
05876
05877 case OPR_DO_LOOP:
05878
05879 vho_lower_check_labels ( WN_index(wn) );
05880 vho_lower_check_labels ( WN_start(wn) );
05881 vho_lower_check_labels ( WN_end(wn) );
05882 vho_lower_check_labels ( WN_step(wn) );
05883 vho_lower_check_labels ( WN_do_body(wn) );
05884 break;
05885
05886 case OPR_DO_WHILE:
05887 case OPR_WHILE_DO:
05888
05889 vho_lower_check_labels ( WN_while_test(wn) );
05890 vho_lower_check_labels ( WN_while_body(wn) );
05891 break;
05892
05893 case OPR_IF:
05894
05895 vho_lower_check_labels ( WN_if_test(wn) );
05896 vho_lower_check_labels ( WN_then(wn) );
05897 vho_lower_check_labels ( WN_else(wn) );
05898 break;
05899
05900 case OPR_COMPGOTO:
05901 case OPR_SWITCH:
05902
05903 for ( i = 0; i < WN_kid_count(wn); i++ )
05904 vho_lower_check_labels ( WN_kid(wn,i) );
05905 break;
05906
05907 case OPR_CASEGOTO:
05908
05909 break;
05910
05911 case OPR_XGOTO:
05912
05913 FmtAssert ( TRUE,
05914 ("unexpected operator encountered in vho_lower_check_labels")
05915 );
05916 break;
05917
05918 case OPR_GOTO:
05919
05920 break;
05921
05922 case OPR_AGOTO:
05923
05924 FmtAssert ( TRUE,
05925 ("unexpected operator encountered in vho_lower_check_labels")
05926 );
05927 break;
05928
05929 case OPR_ALTENTRY:
05930
05931 break;
05932
05933 case OPR_TRUEBR:
05934
05935 vho_lower_check_labels ( WN_kid0(wn) );
05936 break;
05937
05938 case OPR_RETURN:
05939 #ifdef KEY
05940 case OPR_GOTO_OUTER_BLOCK:
05941 #endif
05942
05943 break;
05944
05945 case OPR_LABEL:
05946
05947 vho_lower_labels_defined = TRUE;
05948
05949 if ( ++vho_lower_label_map_index >= vho_lower_label_map_max )
05950 vho_lower_too_many_label_definitions = TRUE;
05951
05952 else {
05953
05954 vho_lower_label_map [vho_lower_label_map_index].old_label =
05955 WN_label_number(wn);
05956 LABEL_Init (New_LABEL (CURRENT_SYMTAB,
05957 vho_lower_label_map [vho_lower_label_map_index].new_label),
05958 0, LKIND_DEFAULT);
05959 vho_lower_label_map [vho_lower_label_map_index].label_flag =
05960 WN_label_flag(wn);
05961 }
05962 break;
05963
05964 case OPR_EXC_SCOPE_BEGIN:
05965 case OPR_EXC_SCOPE_END:
05966 case OPR_FORWARD_BARRIER:
05967 case OPR_BACKWARD_BARRIER:
05968
05969 break;
05970
05971 case OPR_ISTORE:
05972
05973 vho_lower_check_labels ( WN_kid0(wn) );
05974 vho_lower_check_labels ( WN_kid1(wn) );
05975 break;
05976
05977 case OPR_ISTOREX:
05978
05979 FmtAssert ( TRUE,
05980 ("unexpected operator encountered in vho_lower_check_labels")
05981 );
05982 break;
05983
05984 case OPR_MSTORE:
05985
05986 vho_lower_check_labels ( WN_kid0(wn) );
05987 vho_lower_check_labels ( WN_kid1(wn) );
05988 vho_lower_check_labels ( WN_kid2(wn) );
05989 break;
05990
05991 case OPR_STID:
05992
05993 vho_lower_check_labels ( WN_kid0(wn) );
05994 break;
05995
05996 case OPR_CALL:
05997 case OPR_INTRINSIC_CALL:
05998 case OPR_ICALL:
05999
06000 for ( i = 0; i < WN_kid_count(wn); i++ )
06001 vho_lower_check_labels ( WN_actual(wn,i) );
06002 break;
06003
06004
06005 case OPR_PICCALL:
06006
06007 FmtAssert ( TRUE,
06008 ("unexpected operator encountered in vho_lower_check_labels")
06009 );
06010 break;
06011
06012 case OPR_EVAL:
06013
06014 vho_lower_check_labels ( WN_kid0(wn) );
06015 break;
06016
06017 case OPR_PRAGMA:
06018 case OPR_XPRAGMA:
06019 case OPR_PREFETCH:
06020 case OPR_PREFETCHX:
06021
06022 break;
06023
06024 case OPR_IO:
06025
06026 FmtAssert ( TRUE,
06027 ("unexpected operator encountered in vho_lower_check_labels")
06028 );
06029 break;
06030
06031 case OPR_COMMENT:
06032
06033 break;
06034
06035 case OPR_ILOAD:
06036
06037 vho_lower_check_labels ( WN_kid0(wn) );
06038 break;
06039
06040 case OPR_ILOADX:
06041
06042 FmtAssert ( TRUE,
06043 ("unexpected operator encountered in vho_lower_check_labels")
06044 );
06045 break;
06046
06047 case OPR_MLOAD:
06048
06049 vho_lower_check_labels ( WN_kid0(wn) );
06050 vho_lower_check_labels ( WN_kid1(wn) );
06051 break;
06052
06053 case OPR_ARRAY:
06054
06055 vho_lower_check_labels ( WN_kid0(wn) );
06056
06057 for ( i = (WN_kid_count(wn) + 1) >> 1; i < WN_kid_count(wn); i++ )
06058 vho_lower_check_labels ( WN_kid(wn,i) );
06059 break;
06060
06061 case OPR_INTRINSIC_OP:
06062
06063 for ( i = 0; i < WN_kid_count(wn); i++ )
06064 vho_lower_check_labels ( WN_kid(wn,i) );
06065 break;
06066
06067 case OPR_TAS:
06068
06069 vho_lower_check_labels ( WN_kid0(wn) );
06070 break;
06071
06072 case OPR_SELECT:
06073
06074 vho_lower_check_labels ( WN_kid0(wn) );
06075 vho_lower_check_labels ( WN_kid1(wn) );
06076 vho_lower_check_labels ( WN_kid2(wn) );
06077 break;
06078
06079 case OPR_CVT:
06080 case OPR_CVTL:
06081 case OPR_NEG:
06082 case OPR_ABS:
06083 case OPR_SQRT:
06084 case OPR_REALPART:
06085 case OPR_IMAGPART:
06086 case OPR_PAREN:
06087 case OPR_RND:
06088 case OPR_TRUNC:
06089 case OPR_CEIL:
06090 case OPR_FLOOR:
06091 case OPR_BNOT:
06092 case OPR_LNOT:
06093
06094 vho_lower_check_labels ( WN_kid0(wn) );
06095 break;
06096
06097 case OPR_ADD:
06098 case OPR_SUB:
06099 case OPR_MPY:
06100 case OPR_DIV:
06101 case OPR_MOD:
06102 case OPR_REM:
06103 case OPR_DIVREM:
06104 #ifdef KEY
06105 case OPR_COMPOSE_BITS:
06106 #endif
06107
06108 vho_lower_check_labels ( WN_kid0(wn) );
06109 break;
06110
06111 case OPR_LOWPART:
06112 case OPR_HIGHPART:
06113
06114 vho_lower_check_labels ( WN_kid0(wn) );
06115 break;
06116
06117 case OPR_MAX:
06118 case OPR_MIN:
06119 case OPR_MINMAX:
06120
06121 vho_lower_check_labels ( WN_kid0(wn) );
06122 break;
06123
06124 case OPR_MINPART:
06125 case OPR_MAXPART:
06126
06127 vho_lower_check_labels ( WN_kid0(wn) );
06128 break;
06129
06130 case OPR_BAND:
06131 case OPR_BIOR:
06132 case OPR_BNOR:
06133 case OPR_BXOR:
06134 case OPR_LAND:
06135 case OPR_LIOR:
06136 case OPR_CAND:
06137 case OPR_CIOR:
06138 case OPR_SHL:
06139 case OPR_ASHR:
06140 case OPR_LSHR:
06141 case OPR_COMPLEX:
06142
06143 vho_lower_check_labels ( WN_kid0(wn) );
06144 break;
06145
06146 case OPR_RECIP:
06147 case OPR_RSQRT:
06148
06149 vho_lower_check_labels ( WN_kid0(wn) );
06150 break;
06151
06152 case OPR_MADD:
06153 case OPR_MSUB:
06154 case OPR_NMADD:
06155 case OPR_NMSUB:
06156
06157 vho_lower_check_labels ( WN_kid0(wn) );
06158 vho_lower_check_labels ( WN_kid1(wn) );
06159 vho_lower_check_labels ( WN_kid2(wn) );
06160 break;
06161
06162 case OPR_IO_ITEM:
06163
06164 FmtAssert ( TRUE,
06165 ("unexpected operator encountered in vho_lower_check_labels")
06166 );
06167 break;
06168
06169 case OPR_EQ:
06170 case OPR_NE:
06171 case OPR_GT:
06172 case OPR_GE:
06173 case OPR_LT:
06174 case OPR_LE:
06175
06176 vho_lower_check_labels ( WN_kid0(wn) );
06177 vho_lower_check_labels ( WN_kid1(wn) );
06178 break;
06179
06180 case OPR_LDID:
06181 case OPR_LDA:
06182 case OPR_CONST:
06183 case OPR_INTCONST:
06184 case OPR_IDNAME:
06185
06186 break;
06187
06188 case OPR_FALSEBR:
06189
06190 vho_lower_check_labels ( WN_kid0(wn) );
06191 break;
06192
06193 case OPR_LOOP_INFO:
06194
06195 FmtAssert ( TRUE,
06196 ("unexpected operator encountered in vho_lower_check_labels")
06197 );
06198 break;
06199
06200 case OPR_TRAP:
06201 case OPR_ASSERT:
06202
06203 FmtAssert ( TRUE,
06204 ("unexpected operator encountered in vho_lower_check_labels")
06205 );
06206 break;
06207
06208 case OPR_PARM:
06209
06210 vho_lower_check_labels ( WN_kid0(wn) );
06211 break;
06212
06213 case OPR_OPT_CHI:
06214 case OPR_TRIPLET:
06215 case OPR_ARRAYEXP:
06216 case OPR_ARRSECTION:
06217 case OPR_WHERE:
06218 case OPR_OPT_RESERVE2:
06219
06220 FmtAssert ( TRUE,
06221 ("unexpected operator encountered in vho_lower_check_labels")
06222 );
06223 break;
06224
06225 case OPR_COMMA:
06226 case OPR_RCOMMA:
06227
06228 vho_lower_check_labels ( WN_kid0(wn) );
06229 vho_lower_check_labels ( WN_kid1(wn) );
06230 break;
06231
06232 case OPR_HIGHMPY:
06233 case OPR_XMPY:
06234
06235 FmtAssert ( TRUE,
06236 ("unexpected operator encountered in vho_lower_check_labels")
06237 );
06238 break;
06239
06240 case OPR_CSELECT:
06241
06242 vho_lower_check_labels ( WN_kid0(wn) );
06243 vho_lower_check_labels ( WN_kid1(wn) );
06244 vho_lower_check_labels ( WN_kid2(wn) );
06245 break;
06246 }
06247 }
06248
06249
06250 static void
06251 vho_lower_rename_labels_defined ( WN * wn )
06252 {
06253 WN * wn1;
06254 INT32 i;
06255
06256 switch ( WN_operator(wn) ) {
06257
06258 case OPR_FUNC_ENTRY:
06259
06260 vho_lower_rename_labels_defined ( WN_func_body(wn) );
06261 break;
06262
06263 case OPR_BLOCK:
06264
06265 for ( wn1 = WN_first(wn); wn1; wn1 = WN_next(wn1) )
06266 vho_lower_rename_labels_defined ( wn1 );
06267 break;
06268
06269 case OPR_REGION:
06270
06271 vho_lower_rename_labels_defined ( WN_region_body(wn) );
06272 break;
06273
06274 case OPR_REGION_EXIT:
06275
06276 break;
06277
06278 case OPR_DO_LOOP:
06279
06280 vho_lower_rename_labels_defined ( WN_index(wn) );
06281 vho_lower_rename_labels_defined ( WN_start(wn) );
06282 vho_lower_rename_labels_defined ( WN_end(wn) );
06283 vho_lower_rename_labels_defined ( WN_step(wn) );
06284 vho_lower_rename_labels_defined ( WN_do_body(wn) );
06285 break;
06286
06287 case OPR_DO_WHILE:
06288 case OPR_WHILE_DO:
06289
06290 vho_lower_rename_labels_defined ( WN_while_test(wn) );
06291 vho_lower_rename_labels_defined ( WN_while_body(wn) );
06292 break;
06293
06294 case OPR_IF:
06295
06296 vho_lower_rename_labels_defined ( WN_if_test(wn) );
06297 vho_lower_rename_labels_defined ( WN_then(wn) );
06298 vho_lower_rename_labels_defined ( WN_else(wn) );
06299 break;
06300
06301 case OPR_COMPGOTO:
06302 case OPR_SWITCH:
06303
06304 for ( i = 0; i < WN_kid_count(wn); i++ )
06305 vho_lower_rename_labels_defined ( WN_kid(wn,i) );
06306 break;
06307
06308 case OPR_CASEGOTO:
06309
06310
06311 break;
06312
06313 case OPR_XGOTO:
06314
06315 FmtAssert ( TRUE, ("unexpected operator encountered in"
06316 " vho_lower_rename_labels_defined"));
06317 break;
06318
06319 case OPR_GOTO:
06320
06321
06322 break;
06323
06324 case OPR_AGOTO:
06325
06326 FmtAssert ( TRUE, ("unexpected operator encountered in"
06327 " vho_lower_rename_labels_defined"));
06328 break;
06329
06330 case OPR_ALTENTRY:
06331
06332 break;
06333
06334 case OPR_TRUEBR:
06335
06336 vho_lower_rename_labels_defined ( WN_kid0(wn) );
06337
06338 break;
06339
06340 case OPR_RETURN:
06341 #ifdef KEY
06342 case OPR_GOTO_OUTER_BLOCK:
06343 #endif
06344 break;
06345
06346 case OPR_LABEL:
06347
06348 vho_lower_labels_defined = TRUE;
06349 break;
06350
06351 case OPR_EXC_SCOPE_BEGIN:
06352 case OPR_EXC_SCOPE_END:
06353 case OPR_FORWARD_BARRIER:
06354 case OPR_BACKWARD_BARRIER:
06355
06356 break;
06357
06358 case OPR_ISTORE:
06359
06360 vho_lower_rename_labels_defined ( WN_kid0(wn) );
06361 vho_lower_rename_labels_defined ( WN_kid1(wn) );
06362 break;
06363
06364 case OPR_ISTOREX:
06365
06366 FmtAssert ( TRUE, ("unexpected operator encountered in"
06367 " vho_lower_rename_labels_defined"));
06368 break;
06369
06370 case OPR_MSTORE:
06371
06372 vho_lower_rename_labels_defined ( WN_kid0(wn) );
06373 vho_lower_rename_labels_defined ( WN_kid1(wn) );
06374 vho_lower_rename_labels_defined ( WN_kid2(wn) );
06375 break;
06376
06377 case OPR_STID:
06378
06379 vho_lower_rename_labels_defined ( WN_kid0(wn) );
06380 break;
06381
06382 case OPR_CALL:
06383 case OPR_INTRINSIC_CALL:
06384 case OPR_ICALL:
06385
06386 for ( i = 0; i < WN_kid_count(wn); i++ )
06387 vho_lower_rename_labels_defined ( WN_actual(wn,i) );
06388 break;
06389
06390
06391 case OPR_PICCALL:
06392
06393 FmtAssert ( TRUE, ("unexpected operator encountered in"
06394 " vho_lower_rename_labels_defined"));
06395 break;
06396
06397 case OPR_EVAL:
06398
06399 vho_lower_rename_labels_defined ( WN_kid0(wn) );
06400 break;
06401
06402 case OPR_PRAGMA:
06403 case OPR_XPRAGMA:
06404 case OPR_PREFETCH:
06405 case OPR_PREFETCHX:
06406
06407 break;
06408
06409 case OPR_IO:
06410
06411 FmtAssert ( TRUE, ("unexpected operator encountered in"
06412 " vho_lower_rename_labels_defined"));
06413 break;
06414
06415 case OPR_COMMENT:
06416
06417 break;
06418
06419 case OPR_ILOAD:
06420
06421 vho_lower_rename_labels_defined ( WN_kid0(wn) );
06422 break;
06423
06424 case OPR_ILOADX:
06425
06426 FmtAssert ( TRUE, ("unexpected operator encountered in"
06427 " vho_lower_rename_labels_defined"));
06428 break;
06429
06430 case OPR_MLOAD:
06431
06432 vho_lower_rename_labels_defined ( WN_kid0(wn) );
06433 vho_lower_rename_labels_defined ( WN_kid1(wn) );
06434 break;
06435
06436 case OPR_ARRAY:
06437
06438 vho_lower_rename_labels_defined ( WN_kid0(wn) );
06439
06440 for ( i = (WN_kid_count(wn) + 1) >> 1; i < WN_kid_count(wn); i++ )
06441 vho_lower_rename_labels_defined ( WN_kid(wn,i) );
06442 break;
06443
06444 case OPR_INTRINSIC_OP:
06445
06446 for ( i = 0; i < WN_kid_count(wn); i++ )
06447 vho_lower_rename_labels_defined ( WN_kid(wn,i) );
06448 break;
06449
06450 case OPR_TAS:
06451
06452 vho_lower_rename_labels_defined ( WN_kid0(wn) );
06453 break;
06454
06455 case OPR_SELECT:
06456
06457 vho_lower_rename_labels_defined ( WN_kid0(wn) );
06458 vho_lower_rename_labels_defined ( WN_kid1(wn) );
06459 vho_lower_rename_labels_defined ( WN_kid2(wn) );
06460 break;
06461
06462 case OPR_CVT:
06463 case OPR_CVTL:
06464 case OPR_NEG:
06465 case OPR_ABS:
06466 case OPR_SQRT:
06467 case OPR_REALPART:
06468 case OPR_IMAGPART:
06469 case OPR_PAREN:
06470 case OPR_RND:
06471 case OPR_TRUNC:
06472 case OPR_CEIL:
06473 case OPR_FLOOR:
06474 case OPR_BNOT:
06475 case OPR_LNOT:
06476
06477 vho_lower_rename_labels_defined ( WN_kid0(wn) );
06478 break;
06479
06480 case OPR_ADD:
06481 case OPR_SUB:
06482 case OPR_MPY:
06483 case OPR_DIV:
06484 case OPR_MOD:
06485 case OPR_REM:
06486 case OPR_DIVREM:
06487 #ifdef KEY
06488 case OPR_COMPOSE_BITS:
06489 #endif
06490
06491 vho_lower_rename_labels_defined ( WN_kid0(wn) );
06492 break;
06493
06494 case OPR_LOWPART:
06495 case OPR_HIGHPART:
06496
06497 vho_lower_rename_labels_defined ( WN_kid0(wn) );
06498 break;
06499
06500 case OPR_MAX:
06501 case OPR_MIN:
06502 case OPR_MINMAX:
06503
06504 vho_lower_rename_labels_defined ( WN_kid0(wn) );
06505 break;
06506
06507 case OPR_MINPART:
06508 case OPR_MAXPART:
06509
06510 vho_lower_rename_labels_defined ( WN_kid0(wn) );
06511 break;
06512
06513 case OPR_BAND:
06514 case OPR_BIOR:
06515 case OPR_BNOR:
06516 case OPR_BXOR:
06517 case OPR_LAND:
06518 case OPR_LIOR:
06519 case OPR_CAND:
06520 case OPR_CIOR:
06521 case OPR_SHL:
06522 case OPR_ASHR:
06523 case OPR_LSHR:
06524 case OPR_COMPLEX:
06525
06526 vho_lower_rename_labels_defined ( WN_kid0(wn) );
06527 break;
06528
06529 case OPR_RECIP:
06530 case OPR_RSQRT:
06531
06532 vho_lower_rename_labels_defined ( WN_kid0(wn) );
06533 break;
06534
06535 case OPR_MADD:
06536 case OPR_MSUB:
06537 case OPR_NMADD:
06538 case OPR_NMSUB:
06539
06540 vho_lower_rename_labels_defined ( WN_kid0(wn) );
06541 vho_lower_rename_labels_defined ( WN_kid1(wn) );
06542 vho_lower_rename_labels_defined ( WN_kid2(wn) );
06543 break;
06544
06545 case OPR_IO_ITEM:
06546
06547 FmtAssert ( TRUE, ("unexpected operator encountered in"
06548 " vho_lower_rename_labels_defined"));
06549 break;
06550
06551 case OPR_EQ:
06552 case OPR_NE:
06553 case OPR_GT:
06554 case OPR_GE:
06555 case OPR_LT:
06556 case OPR_LE:
06557
06558 vho_lower_rename_labels_defined ( WN_kid0(wn) );
06559 vho_lower_rename_labels_defined ( WN_kid1(wn) );
06560 break;
06561
06562 case OPR_LDID:
06563 case OPR_LDA:
06564 case OPR_CONST:
06565 case OPR_INTCONST:
06566 case OPR_IDNAME:
06567
06568 break;
06569
06570 case OPR_FALSEBR:
06571
06572 vho_lower_rename_labels_defined ( WN_kid0(wn) );
06573
06574 break;
06575
06576 case OPR_LOOP_INFO:
06577
06578 FmtAssert ( TRUE, ("unexpected operator encountered in"
06579 " vho_lower_rename_labels_defined"));
06580 break;
06581
06582 case OPR_TRAP:
06583 case OPR_ASSERT:
06584
06585 FmtAssert ( TRUE, ("unexpected operator encountered in"
06586 " vho_lower_rename_labels_defined"));
06587 break;
06588
06589 case OPR_PARM:
06590
06591 vho_lower_rename_labels_defined ( WN_kid0(wn) );
06592 break;
06593
06594 case OPR_OPT_CHI:
06595 case OPR_TRIPLET:
06596 case OPR_ARRAYEXP:
06597 case OPR_ARRSECTION:
06598 case OPR_WHERE:
06599 case OPR_OPT_RESERVE2:
06600
06601 FmtAssert ( TRUE, ("unexpected operator encountered in"
06602 " vho_lower_rename_labels_defined"));
06603 break;
06604
06605 case OPR_COMMA:
06606 case OPR_RCOMMA:
06607
06608 vho_lower_rename_labels_defined ( WN_kid0(wn) );
06609 vho_lower_rename_labels_defined ( WN_kid1(wn) );
06610 break;
06611
06612 case OPR_HIGHMPY:
06613 case OPR_XMPY:
06614
06615 FmtAssert ( TRUE, ("unexpected operator encountered in"
06616 " vho_lower_rename_labels_defined"));
06617 break;
06618
06619 case OPR_CSELECT:
06620
06621 vho_lower_rename_labels_defined ( WN_kid0(wn) );
06622 vho_lower_rename_labels_defined ( WN_kid1(wn) );
06623 vho_lower_rename_labels_defined ( WN_kid2(wn) );
06624 break;
06625 }
06626 }
06627
06628
06629
06630
06631
06632
06633
06634
06635 static WN *
06636 Substitute_LDID(WN *wn, WN *stid, WN *org, BOOL &replaced)
06637 {
06638 if (WN_operator(wn) == OPR_LDID &&
06639 WN_st(wn) == WN_st(stid) && WN_offset(wn) == WN_offset(stid)) {
06640 replaced = TRUE;
06641 return WN_COPY_Tree(org);
06642 }
06643 else if(OPCODE_is_leaf(WN_opcode(wn)))
06644 return wn;
06645 else {
06646 for (int i=0; i< WN_kid_count(wn); i++)
06647 WN_kid(wn,i) = Substitute_LDID(WN_kid(wn,i), stid, org, replaced);
06648 return wn;
06649 }
06650 }
06651
06652
06653
06654
06655
06656
06657
06658
06659
06660
06661
06662
06663
06664
06665
06666
06667
06668
06669
06670 static void
06671 Eliminate_Temp_In_While(WN *test_wn)
06672 {
06673 WN *stmt, *inc_const;
06674 WN *preg_ldid;
06675 BOOL replaced = FALSE;
06676
06677 if (WN_operator(test_wn)== OPR_COMMA && WN_operator(WN_kid0(test_wn)) == OPR_BLOCK) {
06678 WN *cmp_wn = WN_kid1(test_wn);
06679 WN *block_wn = WN_kid0(test_wn);
06680 WN *st_tmp = WN_first(block_wn);
06681 WN *org_var = WN_kid0(st_tmp);
06682
06683 if (WN_operator_is(st_tmp, OPR_STID) && ST_class(WN_st(st_tmp)) == CLASS_PREG &&
06684 OPERATOR_is_compare(WN_operator(cmp_wn)) && WN_operator_is(WN_kid0(cmp_wn), OPR_LDID) &&
06685 WN_operator_is(WN_kid1(cmp_wn), OPR_INTCONST) ) {
06686
06687 INT count = 0;
06688 for (stmt = WN_next(st_tmp); stmt; stmt = WN_next(stmt))
06689 count++;
06690
06691 stmt = WN_next(st_tmp);
06692 preg_ldid = WN_kid0(WN_kid0(stmt));
06693
06694
06695
06696 if (count == 1 && WN_operator(stmt) == OPR_STID &&
06697 WN_operator_is(org_var, OPR_LDID) &&
06698 WN_st(stmt)== WN_st(org_var) && WN_offset(stmt)== WN_offset(org_var) &&
06699 WN_operator_is(WN_kid0(stmt),OPR_ADD) &&
06700 WN_operator_is(WN_kid1(WN_kid0(stmt)), OPR_INTCONST) &&
06701 WN_st(preg_ldid) == WN_st(st_tmp) && WN_offset(preg_ldid) == WN_offset(st_tmp)) {
06702
06703 replaced=FALSE;
06704 stmt = Substitute_LDID(stmt, st_tmp, org_var, replaced);
06705
06706 if (replaced) {
06707 inc_const = WN_kid1(WN_kid0(stmt));
06708
06709
06710 OPCODE mpyopcode = OPCODE_make_op(OPR_SUB, WN_rtype(org_var),MTYPE_V);
06711 WN *sub_wn = WN_CreateExp2(mpyopcode, WN_COPY_Tree(org_var), WN_COPY_Tree(inc_const));
06712 replaced = FALSE;
06713 cmp_wn = Substitute_LDID(cmp_wn, st_tmp, sub_wn, replaced);
06714 Is_True(replaced, ("there should be one to be replaced"));
06715 }
06716 }
06717 }
06718 }
06719 }
06720
06721
06722 #ifdef KEY
06723 static BOOL Is_Loop_Suitable_For_Misc_Loop_Fusion (WN * wn, WN * block,
06724 WN **pre_l,
06725 WN **main_l,
06726 WN **post_l)
06727 {
06728
06729 WN *body = WN_while_body(wn);
06730 WN *stmt = WN_first(body);
06731 WN *preloop = NULL;
06732 WN *mainloop = NULL;
06733 WN *postloop = NULL;
06734
06735 while(stmt) {
06736 WN * curstmt = stmt;
06737 if (WN_operator(stmt) == OPR_DO_LOOP &&
06738 WN_next(stmt)) {
06739 if (WN_operator(WN_next(stmt)) == OPR_LABEL)
06740 stmt = WN_next(stmt);
06741 if (WN_next(stmt) && WN_operator(WN_next(stmt)) == OPR_STID &&
06742 WN_desc(WN_next(stmt)) == MTYPE_I4 &&
06743 WN_next(WN_next(stmt)) &&
06744 WN_operator(WN_next(WN_next(stmt))) == OPR_DO_LOOP &&
06745 WN_next(WN_next(WN_next(stmt)))) {
06746
06747 WN * p_mainloop = WN_next(WN_next(stmt));
06748 if (WN_operator(WN_next(WN_next(WN_next(stmt)))) == OPR_LABEL)
06749 stmt = WN_next(stmt);
06750 if (WN_next(WN_next(WN_next(stmt))) &&
06751 WN_operator(WN_next(WN_next(WN_next(stmt)))) == OPR_DO_LOOP) {
06752 if (preloop != NULL)
06753 return FALSE;
06754 postloop = WN_next(WN_next(WN_next(stmt)));
06755 mainloop = p_mainloop;
06756 stmt = curstmt;
06757 preloop = stmt;
06758
06759 if (!WN_do_body(preloop) || !WN_do_body(postloop) ||
06760 !WN_first(WN_do_body(preloop)) ||
06761 !WN_first(WN_do_body(postloop)) ||
06762 (WN_next(WN_first(WN_do_body(preloop))) &&
06763 (WN_operator(WN_next(WN_first(WN_do_body(preloop)))) !=
06764 OPR_LABEL ||
06765 WN_next(WN_next(WN_first(WN_do_body(preloop)))))) ||
06766 (WN_next(WN_first(WN_do_body(postloop))) &&
06767 (WN_operator(WN_next(WN_first(WN_do_body(postloop)))) !=
06768 OPR_LABEL ||
06769 WN_next(WN_next(WN_first(WN_do_body(postloop)))))) ||
06770 WN_operator(WN_first(WN_do_body(preloop))) != OPR_ISTORE ||
06771 WN_operator(WN_first(WN_do_body(postloop))) != OPR_ISTORE ||
06772 !WN_start(preloop) || !WN_kid0(WN_start(preloop)) ||
06773 !WN_start(mainloop) || !WN_kid0(WN_start(mainloop)) ||
06774 !WN_start(postloop) || !WN_kid0(WN_start(postloop)) ||
06775 WN_Simp_Compare_Trees(WN_kid0(WN_start(preloop)),
06776 WN_kid0(WN_start(mainloop))) != 0 ||
06777 WN_Simp_Compare_Trees(WN_kid0(WN_start(preloop)),
06778 WN_kid0(WN_start(postloop))) != 0 ||
06779 !WN_end(preloop) ||
06780 WN_operator(WN_end(preloop)) != OPR_GT ||
06781 !WN_end(postloop) ||
06782 WN_operator(WN_end(postloop)) != OPR_GT ||
06783 !WN_end(mainloop) ||
06784 WN_operator(WN_end(mainloop)) != OPR_GT ||
06785 WN_Simp_Compare_Trees(WN_kid0(WN_end(preloop)),
06786 WN_kid0(WN_end(postloop))) != 0 ||
06787 WN_Simp_Compare_Trees(WN_kid0(WN_end(preloop)),
06788 WN_kid0(WN_end(mainloop))) != 0)
06789 preloop = mainloop = postloop = NULL;
06790 }
06791 }
06792 }
06793 stmt = WN_next(stmt);
06794 }
06795
06796 *pre_l = preloop;
06797 *main_l = mainloop;
06798 *post_l = postloop;
06799
06800 return preloop != NULL;
06801 }
06802
06803 static void Rename_Subscripts ( WN *to, WN *from, WN *node)
06804 {
06805 if (WN_operator(node) == OPR_LDID &&
06806 WN_offset(node) == WN_offset(from))
06807 WN_offset(node) = WN_offset(to);
06808
06809
06810 for (INT kid = 0; kid < WN_kid_count(node); kid ++)
06811 Rename_Subscripts(to, from, WN_kid(node, kid));
06812 }
06813
06814 static void Misc_Loop_Fusion ( WN * wn, WN * block )
06815 {
06816 if (!VHO_Enable_Misc_Loop_Fusion)
06817 return;
06818
06819 WN *preloop = NULL;
06820 WN *mainloop = NULL;
06821 WN *postloop = NULL;
06822 if (!Is_Loop_Suitable_For_Misc_Loop_Fusion(wn, block,
06823 &preloop, &mainloop, &postloop))
06824 return;
06825
06826
06827 WN *body = WN_while_body(wn);
06828 #if 0
06829 WN *stmt = WN_first(body);
06830 WN *preloop = NULL;
06831 WN *mainloop = NULL;
06832 WN *postloop = NULL;
06833 while(stmt) {
06834 if (WN_operator(stmt) == OPR_DO_LOOP &&
06835 WN_next(stmt) && WN_operator(WN_next(stmt)) == OPR_STID &&
06836 WN_desc(WN_next(stmt)) == MTYPE_I4 &&
06837 WN_next(WN_next(stmt)) &&
06838 WN_operator(WN_next(WN_next(stmt))) == OPR_DO_LOOP &&
06839 WN_next(WN_next(WN_next(stmt))) &&
06840 WN_operator(WN_next(WN_next(WN_next(stmt)))) == OPR_DO_LOOP) {
06841 preloop = stmt;
06842 mainloop = WN_next(WN_next(stmt));
06843 postloop = WN_next(WN_next(WN_next(stmt)));
06844 break;
06845 }
06846 stmt = WN_next(stmt);
06847 }
06848 #endif
06849 FmtAssert(preloop && mainloop && postloop,
06850 ("Handle this case in Misc_Loop_Fusion"));
06851
06852
06853 WN *preloopbody = WN_COPY_Tree(WN_do_body(preloop));
06854 WN *mainloopbody = WN_do_body(mainloop);
06855 WN *postloopbody = WN_COPY_Tree(WN_do_body(postloop));
06856
06857 Rename_Subscripts(WN_index(mainloop), WN_index(preloop),
06858 WN_first(preloopbody));
06859 Rename_Subscripts(WN_index(mainloop), WN_index(postloop),
06860 WN_first(postloopbody));
06861
06862
06863 WN *innerloop = WN_first(mainloopbody);
06864 while (innerloop) {
06865 if (WN_operator(innerloop) == OPR_DO_LOOP)
06866 break;
06867 innerloop = WN_next(innerloop);
06868 }
06869
06870
06871 if (!innerloop || !WN_next(innerloop) || !WN_next(WN_next(innerloop)))
06872 return;
06873
06874 WN_INSERT_BlockAfter ( mainloopbody, innerloop, WN_first(preloopbody));
06875 WN_INSERT_BlockAfter ( mainloopbody, WN_next(WN_next(innerloop)),
06876 WN_first(postloopbody));
06877
06878 WN_next(WN_prev(preloop)) = WN_next(preloop);
06879 WN_prev(WN_next(preloop)) = WN_prev(preloop);
06880 WN_next(mainloop) = WN_next(postloop);
06881 WN_prev(WN_next(postloop)) = mainloop;
06882
06883 WN_DELETE_Tree(preloop);
06884 WN_DELETE_Tree(postloop);
06885
06886 return;
06887 }
06888
06889 static WN *vho_lower_while_do ( WN * wn, WN *block );
06890
06891 static BOOL Iload_Inside (WN* wn)
06892 {
06893 if (WN_operator(wn) == OPR_ILOAD)
06894 return TRUE;
06895 else {
06896 for (INT kid = 0; kid < WN_kid_count(wn); kid ++)
06897 if (Iload_Inside(WN_kid(wn, kid))) return TRUE;
06898 }
06899 return FALSE;
06900 }
06901
06902 static WN* Find_Iload_Iload_Opnd ( WN* wn )
06903 {
06904 if (WN_operator(wn) == OPR_ILOAD) {
06905 if (Iload_Inside(WN_kid0(wn)))
06906 return wn;
06907 else
06908 return NULL;
06909 } else {
06910 WN* opnd = NULL;
06911 WN* tree;
06912 for (INT kid = 0; kid < WN_kid_count(wn); kid ++) {
06913 if (tree = Find_Iload_Iload_Opnd(WN_kid(wn, kid))) {
06914
06915 if (opnd && tree) return NULL;
06916 else opnd = tree;
06917 }
06918 }
06919 return opnd;
06920 }
06921 }
06922
06923 static BOOL
06924 Is_Loop_Suitable_For_Misc_Loop_Distribute_And_Interchange(WN* wn, WN* block)
06925 {
06926 WN* last = WN_last(block);
06927 if (!last) return FALSE;
06928 if (WN_operator(last) != OPR_STID) {
06929 if (WN_operator(last) != OPR_LABEL) return FALSE;
06930 if (!WN_prev(last) ||
06931 WN_operator(last = WN_prev(last)) != OPR_STID) return FALSE;
06932 }
06933 ST* index_outerloop = WN_st(last);
06934 WN* test_outerloop = WN_while_test(wn);
06935 if (!OPCODE_is_compare(WN_opcode(test_outerloop))) return FALSE;
06936 BOOL index_matches = FALSE;
06937 if (WN_operator(WN_kid0(test_outerloop)) == OPR_LDID &&
06938 WN_st(WN_kid0(test_outerloop)) == index_outerloop)
06939 index_matches = TRUE;
06940 if (WN_operator(WN_kid1(test_outerloop)) == OPR_LDID &&
06941 WN_st(WN_kid1(test_outerloop)) == index_outerloop)
06942 index_matches = TRUE;
06943 if (!index_matches)
06944 return FALSE;
06945
06946
06947
06948
06949 WN* loop_body = WN_while_body(wn);
06950 WN* loop_body_start = WN_first(loop_body);
06951 if (loop_body_start && WN_operator(loop_body_start) == OPR_LABEL)
06952 loop_body_start = WN_next(loop_body_start);
06953 if (!loop_body_start ||
06954 WN_operator(loop_body_start) != OPR_ISTORE) return FALSE;
06955 if (!WN_next(loop_body_start) ||
06956 WN_operator(WN_next(loop_body_start)) != OPR_IF) return FALSE;
06957 WN* if_stmt = WN_next(loop_body_start);
06958 if (!WN_next(if_stmt)) return FALSE;
06959 if (WN_operator(WN_next(if_stmt)) == OPR_LABEL) {
06960 if (!WN_next(WN_next(if_stmt)) ||
06961 WN_operator(WN_next(WN_next(if_stmt))) != OPR_STID)
06962 return FALSE;
06963 }
06964 else if (WN_operator(WN_next(if_stmt)) != OPR_STID)
06965 return FALSE;
06966 if (WN_first(WN_else(if_stmt))) return FALSE;
06967 WN* if_then_body = WN_then(if_stmt);
06968 if (!WN_first(if_then_body) ||
06969 WN_operator(WN_first(if_then_body)) != OPR_STID) return FALSE;
06970 BOOL label_found = FALSE;
06971 if (!WN_next(WN_first(if_then_body))) return FALSE;
06972 if (WN_operator(WN_next(WN_first(if_then_body))) != OPR_WHILE_DO) {
06973 if (WN_operator(WN_next(WN_first(if_then_body))) != OPR_LABEL)
06974 return FALSE;
06975 else
06976 label_found = TRUE;
06977 }
06978
06979
06980
06981 WN *innerloop = WN_next(WN_first(if_then_body));
06982 if (label_found) innerloop = WN_next(WN_next(WN_first(if_then_body)));
06983 WN *body = WN_while_body(innerloop);
06984 WN* stmt = WN_first(body);
06985 if (stmt && WN_operator(stmt) == OPR_LABEL)
06986 stmt = WN_next(stmt);
06987 if (!stmt || WN_operator(stmt) != OPR_ISTORE ||
06988 !WN_next(stmt))
06989 return FALSE;
06990 if (WN_operator(WN_next(stmt)) == OPR_LABEL) {
06991 if (!WN_next(WN_next(stmt)) ||
06992 WN_operator(WN_next(WN_next(stmt))) != OPR_STID ||
06993 WN_next(WN_next(WN_next(stmt))))
06994 return FALSE;
06995 }
06996 else {
06997 if (WN_operator(WN_next(stmt)) != OPR_STID ||
06998 (WN_next(WN_next(stmt)) &&
06999 WN_operator(WN_next(WN_next(stmt))) != OPR_LABEL))
07000 return FALSE;
07001 }
07002
07003 WN* opnd;
07004 WN* opnd_base;
07005 WN* result_base;
07006 if (!(opnd = Find_Iload_Iload_Opnd(WN_kid0(stmt))))
07007 return FALSE;
07008 if (WN_operator(WN_kid1(stmt)) != OPR_ADD ||
07009 WN_operator(WN_kid1(WN_kid1(stmt))) != OPR_MPY ||
07010 WN_operator(result_base = WN_kid0(WN_kid1(stmt))) != OPR_LDID)
07011 return FALSE;
07012 WN *low_index, *high_index;
07013 if (WN_operator(low_index = WN_kid0(opnd)) != OPR_ADD ||
07014 WN_operator(WN_kid0(WN_kid0(opnd))) != OPR_ILOAD ||
07015 WN_operator(high_index = WN_kid0(WN_kid0(WN_kid0(opnd)))) != OPR_ADD ||
07016 WN_operator(opnd_base = WN_kid0(WN_kid0(WN_kid0(WN_kid0(opnd))))) != OPR_LDID)
07017 return FALSE;
07018
07019 if (WN_operator(WN_kid1(low_index)) != OPR_MPY ||
07020 WN_operator(WN_kid1(high_index)) != OPR_MPY)
07021 return FALSE;
07022
07023 low_index = WN_kid0(WN_kid1(low_index));
07024 high_index = WN_kid0(WN_kid1(high_index));
07025
07026 if (WN_operator(low_index) != OPR_LDID &&
07027 WN_operator(low_index) != OPR_CVT)
07028 return FALSE;
07029 if (WN_operator(low_index) == OPR_CVT)
07030 if (WN_operator(low_index = WN_kid0(low_index)) != OPR_LDID)
07031 return FALSE;
07032 if (WN_operator(high_index) != OPR_LDID &&
07033