• Main Page
  • Modules
  • Data Types
  • Files

osprey/be/vho/vho_lower.cxx

Go to the documentation of this file.
00001 /*
00002  * Copyright 2003, 2004, 2005, 2006 PathScale, Inc.  All Rights Reserved.
00003  */
00004 
00005 /*
00006 
00007   Copyright (C) 2000, 2001 Silicon Graphics, Inc.  All Rights Reserved.
00008 
00009   This program is free software; you can redistribute it and/or modify it
00010   under the terms of version 2 of the GNU General Public License as
00011   published by the Free Software Foundation.
00012 
00013   This program is distributed in the hope that it would be useful, but
00014   WITHOUT ANY WARRANTY; without even the implied warranty of
00015   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
00016 
00017   Further, this software is distributed without any warranty that it is
00018   free of the rightful claim of any third person regarding infringement 
00019   or the like.  Any license provided herein, whether implied or 
00020   otherwise, applies only to this software file.  Patent licenses, if 
00021   any, provided herein do not apply to combinations of this program with 
00022   other software, or any other product whatsoever.  
00023 
00024   You should have received a copy of the GNU General Public License along
00025   with this program; if not, write the Free Software Foundation, Inc., 59
00026   Temple Place - Suite 330, Boston MA 02111-1307, USA.
00027 
00028   Contact information:  Silicon Graphics, Inc., 1600 Amphitheatre Pky,
00029   Mountain View, CA 94043, or:
00030 
00031   http://www.sgi.com
00032 
00033   For further information regarding this notice, see:
00034 
00035   http://oss.sgi.com/projects/GenInfo/NoticeExplan
00036 
00037 */
00038 
00039 
00040 //-*-c++-*-
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"            // For Current_PU_Count
00069 #include "glob.h"               // For Show_Progress
00070 #ifdef KEY
00071 #include "w2op.h"   // For OPCODE_Can_Be_Spculative
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 /* FRONT_END */
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 } /* VHO_WN_is_zero */
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 } /* VHO_WN_has_side_effects */
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 /* Table used to promote integers less than 4 bytes into their
00172  * 4 byte counterparts in order to get the right type for OPCODE_make_op
00173  */
00174 
00175 TYPE_ID Promoted_Mtype [MTYPE_LAST + 1] = {
00176   MTYPE_UNKNOWN,  /* MTYPE_UNKNOWN */
00177   MTYPE_UNKNOWN,  /* MTYPE_B */
00178   MTYPE_I4,       /* MTYPE_I1 */
00179   MTYPE_I4,       /* MTYPE_I2 */
00180   MTYPE_I4,       /* MTYPE_I4 */
00181   MTYPE_I8,       /* MTYPE_I8 */
00182   MTYPE_U4,       /* MTYPE_U1 */
00183   MTYPE_U4,       /* MTYPE_U2 */
00184   MTYPE_U4,       /* MTYPE_U4 */
00185   MTYPE_U8,       /* MTYPE_U8 */
00186   MTYPE_F4,       /* MTYPE_F4 */
00187   MTYPE_F8,       /* MTYPE_F8 */
00188   MTYPE_F10,      /* MTYPE_F10 */
00189   MTYPE_UNKNOWN,  /* MTYPE_F16 */
00190   MTYPE_UNKNOWN,  /* MTYPE_STR */
00191   MTYPE_FQ,       /* MTYPE_FQ */
00192   MTYPE_M,        /* MTYPE_M */
00193   MTYPE_C4,       /* MTYPE_C4 */
00194   MTYPE_C8,       /* MTYPE_C8 */
00195   MTYPE_CQ,       /* MTYPE_CQ */
00196   MTYPE_V,         /* MTYPE_V */
00197 #if defined(TARG_IA64)
00198   MTYPE_UNKNOWN,  /* MTYPE_BS */
00199   MTYPE_UNKNOWN,  /* MTYPE_A4 */
00200   MTYPE_UNKNOWN,  /* MTYPE_A8 */
00201   MTYPE_C10,      /* 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 /* VHO_DEBUG */
00210 
00211 static SRCPOS    VHO_Srcpos;
00212 
00213 /* Variables related to handling of switch statements */
00214 
00215 INT32   VHO_Switch_Distance = 128;         /* max distance between values    */
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; /* table for switch cases    */
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;        /* signedness of switch index     */
00241 static OPCODE    VHO_Switch_Int_Opcode;    /* opcode for Create_Int          */
00242 static OPCODE    VHO_Switch_Sub_Opcode;    /* opcode for subtract            */
00243 static OPCODE    VHO_Switch_EQ_Opcode;     /* opcode for == comparison       */
00244 static OPCODE    VHO_Switch_LT_Opcode;     /* opcode for <  comparison       */
00245 static OPCODE    VHO_Switch_GT_Opcode;     /* opcode for >  comparison       */
00246 
00247 static LABEL_IDX VHO_Switch_Default_Label; /* default label in switch        */
00248 static INT32     VHO_Switch_Last_Label;    /* last label in switch           */
00249 static INT32   * VHO_Switch_Cluster_Table; /* table for switch clusters      */
00250 static INT32     VHO_Switch_Ncases;        /* # of cases in switch           */
00251 static INT32     VHO_Switch_Nclusters;     /* # of clusters in switch        */
00252 static WN      * VHO_Switch_Index;         /* load of switch index           */
00253 static WN      * VHO_Switch_Default_Goto;  /* goto switch default label      */
00254 static WN      * VHO_Switch_Stmt;          /* switch statement               */
00255 static FB_FREQ   VHO_Switch_Default_Freq;  /* goto switch default freq       */
00256 
00257 #ifdef KEY
00258 static BOOL VHO_In_MP_Region_Pragma = FALSE;
00259 #endif // KEY
00260 
00261 /* Variables related to struct lowering */
00262 
00263 #if defined(TARG_X8664) || defined(TARG_IA64) 
00264 INT32  VHO_Struct_Limit = 8;               /* max # of fields/statements     */
00265 #elif defined(TARG_NVISA)
00266 INT32  VHO_Struct_Limit = 24;              /* max # of fields/statements     */
00267 #else
00268 INT32  VHO_Struct_Limit = 4;               /* max # of fields/statements     */
00269 #endif
00270 
00271 // static INT32  VHO_Struct_Alignment;      /* Alignment of struct           */
00272 static BOOL   VHO_Struct_Can_Be_Lowered;    /* FALSE if cannot be lowered    */
00273 static INT32  VHO_Struct_Nfields;           /* # of fields                   */
00274 static TY_IDX VHO_Struct_Fld_Table [255]; /* table containing fields         */
00275 static INT32 VHO_Struct_Offset_Table [255]; /* table containing fields offset */
00276 // We want to use field_ids when possible,
00277 // as that gives higher-level type info about the original struct
00278 // (e.g. if want to know alignment of original struct).
00279 // However, fields that are arrays have a single field id,
00280 // but may span multiple elements, so use element types in that case.
00281 static INT32 VHO_Struct_Field_Id_Table[255]; /* table containing field ids   */
00282 static BOOL VHO_Struct_Field_Is_Array_Table[255]; /* field is array? */
00283 static INT32  VHO_Struct_Last_Field_Offset; /* offset of last field          */
00284 static INT32  VHO_Struct_Last_Field_Size;   /* size of last field            */
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 } /* VHO_Switch_Compare_Value */
00329 
00330 
00331 /* ============================================================================
00332  *
00333  * INT32
00334  * VHO_Switch_Compare_Frequency ( const void *v_item1, const void *v_item2 )
00335  *
00336  * Routine invoked by qsort to compare two case values frequencies specified
00337  * the switch statement.
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     // Order of _decreasing_ frequencies
00359 
00360     if ( freq1 > freq2 )
00361       compare_code = LESS;
00362 
00363     else // freq1 < freq2
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 } /* VHO_Switch_Compare_Frequency */
00395 
00396 #ifdef KEY
00397 /* ============================================================================
00398  *
00399  * static WN *
00400  * VHO_Switch_Generate_If_Else_Reduce_Branch ( SRCPOS srcpos )
00401  *
00402  * Generate if-else sequence for the switch statement by grouping consecutive
00403  * cases together and using a single branch for each group.
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   // Find the highest and lowest case label numbers.
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   // Create case labels map.
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   // Map each case label to the first label in the case code.  A case code will
00437   // have multiple labels if it is shared by different case values.
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       // Map only the labels in the switch stmt.
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       // Real code terminates the labels group.
00452       first_label_in_group = NULL;
00453     }
00454   }
00455 
00456   // Sort the case values.
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     // Detect consecutive case values sharing common case code.
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       // No consecutive case values.
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       // Consecutive case values sharing common case code.  Translate:
00487       //
00488       //   case k:
00489       //   case k+1:
00490       //    ...
00491       //   case k+n:  goto label
00492       //
00493       // into:
00494       //
00495       //   if ((unsigned int)(index - k) <= n)
00496       //     goto label
00497       //
00498       // If index is less than k, then (unsigned int)(index - k) will be
00499       // a large unsigned int larger than n.
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;    // Skip to the next case value.
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  * static WN *
00527  * VHO_Switch_Generate_If_Else ( SRCPOS srcpos )
00528  *
00529  * Generate if-else sequence for the switch statement.
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 } /* VHO_Switch_Generate_If_Else */
00587 /* ============================================================================
00588  *
00589  * static WN *
00590  * VHO_Switch_Opt_Case_Hoist ( SRCPOS srcpos )
00591  *
00592  * Generate if-else sequence for the highly biased cases.
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; // record only top 30 cases of frequencies
00606   INT32    num_hoist=0;
00607 
00608   if (!Cur_PU_Feedback ) return NULL;  // no switch optimization if no feedback
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) // top 30 % of cases
00628           freq_tops += VHO_SWITCH_freq(i);
00629     }
00630   }
00631   /* If lower than 70%, don't do switch optimization */
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 /* VHO_DEBUG */
00647 
00648 //    printf("WARNING: SWITCH_OPT_CASE_HOIST: %d (case %d of freq %f total:%f)\n",(INT32) srcpos, i, VHO_SWITCH_freq(i).Value(), freq_total.Value());
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   /* Remove all the cases that are hoisted */
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 } /* VHO_Switch_Opt_Case_Hoist */
00689 
00690 
00691 /* ============================================================================
00692  *
00693  * static WN *
00694  * VHO_Switch_Generate_Compgoto ( SRCPOS srcpos )
00695  *
00696  * Generate a COMPGOTO for the switch statement.
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   /* Check to see whether we can avoid generating a subtract. */
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 //      freq_new[j] = FB_FREQ_UNKNOWN;
00748         freq_new[j] = FB_FREQ(FB_FREQ_TYPE_GUESS);  //INLINING_TUNINING
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 //      = FB_FREQ_UNKNOWN; // not VHO_Switch_Default_Freq
00774         = FB_FREQ(VHO_Switch_Default_Freq.Value(), FALSE);//INLINING_TUNINING  
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 } /* VHO_Switch_Generate_Compgoto */
00784 
00785 
00786 /* ============================================================================
00787  *
00788  * static void
00789  * VHO_Switch_Generate_Binary_Search ( INT32 left, INT32 right, WN * block )
00790  *
00791  * Implement the switch statement as a binary search.
00792  * left and right give the indices in VHO_Switch_Case_Table which
00793  * contain the values to be compared with.
00794  * block contains the WHIRL block node to which statements are to be added.
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 } /* VHO_Switch_Generate_Binary_Search */
00900 
00901 /* ============================================================================
00902  *
00903  * static void
00904  * VHO_Switch_Find_Clusters ( void )
00905  *
00906  * Group the switch values into clusters.
00907  * For each cluster a COMPGOTO cna be generated.
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 /* VHO_DEBUG */
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 /* VHO_DEBUG */
01006 } /* VHO_Switch_Find_Clusters */
01007 
01008 /* ============================================================================
01009  *
01010  * static WN *
01011  * VHO_Lower_Switch ( WN * wn )
01012  *
01013  * Lower a switch statement into a combination of
01014  *
01015  *   if-else
01016  *   COMPGOTO
01017  *   binary search.
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 /* VHO_DEBUG */
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 /* VHO_DEBUG */
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 /* VHO_DEBUG */
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 /* VHO_DEBUG */
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 /* VHO_DEBUG */
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 /* VHO_DEBUG */
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 /* VHO_DEBUG */
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 /* VHO_DEBUG */
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 } /* VHO_Lower_Switch */
01232 
01233 /* ============================================================================
01234  *
01235  * static WN *
01236  * VHO_Lower_Compgoto ( WN * wn )
01237  *
01238  * ============================================================================
01239  */
01240 
01241 static WN *
01242 VHO_Lower_Compgoto ( WN * wn )
01243 {
01244   return wn;
01245 } /* VHO_Lower_Compgoto */
01246 
01247 
01248 /* ============================================================================
01249  *
01250  * static UINT
01251  * VHO_Get_Field_List ( WN_OFFSET offset, TY_IDX sty_idx )
01252  *
01253  * Flatten a struct/union 'sty' starting as 'offset' into non overlapping
01254  * fields and place them in the array VHO_Struct_Fld_Table.
01255  * Update VHO_Struct_Nfields, VHO_Struct_Last_Field_Offset
01256  * VHO_Struct_Last_Field_Size.
01257  *
01258  * If the structure contains misaligned data, holes or fields which
01259  * are out of order, then lowering is not done.
01260  * This is done by setting VHO_Struct_Can_Be_Lowered to FALSE.
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         // always increase the field_id for SCALAR and POINTER
01291         ++field_id;
01292         if ( VHO_Struct_Nfields ) {
01293           if ( field_offset >= VHO_Struct_Last_Field_Offset
01294                                  + VHO_Struct_Last_Field_Size ) {
01295             /* new field */
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             /* overlapping field with same start offset */
01306             if ( TY_size (Ty_Table [fty_idx]) > VHO_Struct_Last_Field_Size ) {
01307               /* overlapping field with larger size */
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           /* new field */
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           // Structs are their own field id, 
01340           // then each field in them gets new id.
01341           // So increment field_id,
01342           // but don't want whole struct in table, just each subfield.
01343           ++field_id;
01344       
01345           // get new field id from sub-struct 
01346           // so next field will have right value.
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         // Is_True (VHO_Struct_Nfields + array_elem_num < 255,
01368         //            ("number of flattened fields exceeds limit");
01369         if (VHO_Struct_Nfields + array_elem_num >= 255) {
01370           VHO_Struct_Can_Be_Lowered = FALSE;
01371           break;
01372         }  
01373   ++field_id; // keep same field_id for all array elements
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                 // array of structs; open up each field of struct
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                   // array of structs; open up each field of struct
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               // array of structs; open up each field of struct
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 } /* VHO_Get_Field_List */
01466 
01467 #ifdef KEY
01468 // If there is a single field that spans across the entire
01469 // struct (i.e. any other field has size zero), return the field-id,
01470 // else return 0.
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     // Else if there is a field with non-zero size, then there must be
01489     // multiple non-zero-size fields.
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  * WN *VHO_Lower_Mstore ( WN * wn )
01512  *
01513  * If the structure being copied is sufficiently small, then flatten out the
01514  * structure into a set of non overlapping fields and load/store the
01515  * individual fields, thereby replacing MSTORE/MLOAD by a sequence of
01516  * one or more (controlled by VHO_Struct_Limit) pairs of STID/ISTORE
01517  * over LDID/ILOAD.
01518  *
01519  * The following structures are not currently handled.
01520  *
01521  *   structures containing misaligned fields
01522  *   structures containing bit fields
01523  *   structures containing arrays
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   // WN_OFFSET   field_offset;
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        /* need to handle WN_opcode(src_value) == OPC_MMLDID, 
01565           see VHO_Lower_Mstid function                        */
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     // Used to check for matching struct alignment,
01581     // but we don't need alignment to match to copy fields
01582     // (may have been related to unused VHO_Struct_Alignment variable).
01583     // if (    TY_align(src_ty_idx) == TY_align(dst_ty_idx)
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 //    VHO_Struct_Alignment = TY_align(dst_ty_idx);
01592 
01593       /* Flatten out the structure into non overlapping fields */
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 /* VHO_DEBUG */
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         if (    WN_operator(src_address) == OPR_ARRAY 
01618              && WN_operator(WN_kid0(src_address)) == OPR_LDA )
01619           src_st = NULL;
01620 
01621         else {
01622 
01623           preg = Create_Preg (Pointer_Mtype, vho_lower_mstore_name);
01624 
01625           preg_st     = MTYPE_To_PREG ( Pointer_Mtype );
01626           preg_ty_idx = ptr_src_ty_idx;
01627 
01628           if ( src_offset == 0 ) {
01629 
01630             opc  = OPCODE_make_op ( OPR_STID, MTYPE_V, Pointer_Mtype );
01631             temp = WN_CreateStid ( opc, preg, preg_st, preg_ty_idx,
01632            src_address );
01633           } else {
01634             opc  = OPCODE_make_op ( OPR_INTCONST, Pointer_Mtype, MTYPE_V );
01635             temp = WN_CreateIntconst ( opc, src_offset );
01636             opc  = OPCODE_make_op ( OPR_ADD, Pointer_Mtype, MTYPE_V );
01637             temp = WN_CreateExp2 ( opc, src_address, temp );
01638             opc  = OPCODE_make_op ( OPR_STID, MTYPE_V, Pointer_Mtype );
01639             temp = WN_CreateStid ( opc, preg, preg_st, preg_ty_idx, temp );
01640           }
01641 
01642           WN_Set_Linenum(temp, srcpos);
01643 
01644           WN_INSERT_BlockAfter ( block, WN_last(block), temp );
01645 
01646           opc = OPCODE_make_op ( OPR_LDID, Pointer_Mtype, Pointer_Mtype );
01647           src_address = WN_CreateLdid ( opc, preg, preg_st, preg_ty_idx );
01648           src_st      = NULL;
01649           src_offset  = 0;
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         if (    WN_operator(dst_address) == OPR_ARRAY
01663              && WN_operator(WN_kid0(dst_address)) == OPR_LDA )
01664           dst_st = NULL;
01665 
01666         else {
01667 
01668           preg = Create_Preg (Pointer_Mtype, vho_lower_mstore_name);
01669 
01670           preg_st     = MTYPE_To_PREG ( Pointer_Mtype );
01671           preg_ty_idx = ptr_src_ty_idx;
01672 
01673           if ( dst_offset == 0 ) {
01674 
01675             opc  = OPCODE_make_op ( OPR_STID, MTYPE_V, Pointer_Mtype );
01676             temp = WN_CreateStid ( opc, preg, preg_st, preg_ty_idx,
01677            dst_address );
01678           }
01679 
01680           else {
01681 
01682             opc  = OPCODE_make_op ( OPR_INTCONST, Pointer_Mtype, MTYPE_V );
01683             temp = WN_CreateIntconst ( opc, dst_offset );
01684             opc  = OPCODE_make_op ( OPR_ADD, Pointer_Mtype, MTYPE_V );
01685             temp = WN_CreateExp2 ( opc, dst_address, temp );
01686             opc  = OPCODE_make_op ( OPR_STID, MTYPE_V, Pointer_Mtype );
01687             temp = WN_CreateStid ( opc, preg, preg_st, preg_ty_idx, temp );
01688           }
01689 
01690           WN_Set_Linenum(temp, srcpos);
01691 
01692           WN_INSERT_BlockAfter ( block, WN_last(block), temp );
01693 
01694           opc  = OPCODE_make_op ( OPR_LDID, Pointer_Mtype, Pointer_Mtype );
01695           dst_address = WN_CreateLdid ( opc, preg, preg_st, preg_ty_idx );
01696           dst_st      = NULL;
01697           dst_offset  = 0;
01698         }
01699 */
01700         // field_offset = 0;
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           // field_offset += TY_size(fty_idx);
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 /* VHO_DEBUG */
01749     }
01750   }
01751   return wn;
01752 } /* VHO_Lower_Mstore */
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 // 64bit code can have cvt above the multiply
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 // share code for finding LDID under a MMILOAD
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       // array index
01777       return WN_kid0(iload_kid);
01778       }
01779       // check other kid
01780       else if (Is_Ldid_Or_Lda(WN_kid1(iload_kid))
01781         && Is_Multiply_Or_Cvt_Multiply(WN_kid0(iload_kid)) )
01782       {
01783       // array index
01784       return WN_kid1(iload_kid);
01785       }
01786     }
01787     else if (WN_operator(iload_kid) == OPR_ARRAY) {
01788       // recurse on array index variant
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  * WN *VHO_Lower_Mstid(WN * wn)
01814  *
01815  * If the structure being copied is sufficiently small, then flatten out the
01816  * structure into a set of non overlapping fields and load/store the 
01817  * individual fields, thereby replacing MMSTID/MLDID by a sequence of 
01818  * one or more (controlled by VHO_Struct_Limit) pairs of STID/ISTORE
01819  * over LDID/ILOAD.
01820  * 
01821  * The following structures are not currently handled.
01822  * 
01823  * structures containing misaligned fields
01824  * structures containing bit fields
01825  * structures containing arrays
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   // WN_OFFSET   field_offset;
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   // field_ids complicate things, as they require generating 
01860   // (struct-type, field_id) rather than a simple field type.
01861   // We can handle field_ids by getting fty
01862   // of struct subfields for appropriate mtype, but generating field_ids
01863   // of original struct for the actual ldid/stid.
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       // will replace MSTID(MMILOAD) with STID<field1>(ILOAD<field1>),etc
01875       src_iload_kid = WN_kid0(src_value);
01876       // is indirect load, so will be pointer type
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;      // doesn't fit pattern so ignore
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;  // don't handle any other cases
01888   }
01889   else  
01890   {
01891       return wn;  // don't handle any other cases
01892   }
01893 
01894   // keep the original src_type
01895   orig_src_ty_idx = src_ty_idx;
01896   // we have a src_ty_idx type at src_field_id of orig_src_ty_idx
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   // iload of preg is okay cause iload takes the field offset
01902   if ( ST_class(WN_st(wn)) == CLASS_PREG ||
01903        (ST_class(WN_st(src_ldid)) == CLASS_PREG && !src_is_pointer)) {
01904       /* screen out PREG for now, need to change them into extract sometime */
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     /* screen out PREG for now, need to change them into extract sometime */
01915 #endif
01916 
01917 #ifdef KEY
01918     VHO_Struct_Nfields = 0;
01919     VHO_Struct_Can_Be_Lowered = TRUE;
01920 #endif
01921     
01922           // Used to check for matching struct alignment,
01923           // but we don't need alignment to match to copy fields
01924           // (may have been related to unused VHO_Struct_Alignment variable).
01925           // if(   TY_align(src_ty_idx) == TY_align(dst_ty_idx)
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       //  VHO_Struct_Alignment = TY_align(dst_ty_idx);
01936 
01937       // Flatten out the structure into non overlapping fields 
01938       // src_field_id is the starting point of type src_ty_idx
01939       // inside the outer structure of type orig_src_ty_idx
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 /* VHO_DEBUG */
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         // preserve offset from original ldid/iload
01956         src_offset = WN_offset(src_value);
01957         dst_st = WN_st(wn);
01958         dst_offset = WN_store_offset(wn);
01959 
01960         // field_offset = 0;
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                   // each element uses same field_id,
01992                   // so rather than create array refs, just do element copies
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               // each element uses same field_id,
02006               // so rather than create array refs, just do element copies
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           // field_offset += TY_size(fty_idx);
02019         } //end for
02020         wn = block;
02021       } // end if ( VHO_Struct_Can_Be_Lowered && VHO_Struct_Nfields) {
02022     } // end TY_kind(src_ty_idx) == KIND_STRUCT
02023 #ifdef KEY
02024     if (VHO_Struct_Can_Be_Lowered && VHO_Struct_Nfields)
02025       ; // we already lowered the struct
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       // bug 7741: change MTYPE_M to MTYPE_U[48]
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       // bugs 9989, 10139
02038       INT field_id;
02039       // We allow the field_id not zero, comment out the Is_True
02040       //Is_True (WN_field_id(src_value) == 0,("Expected field-id zero"));
02041       if ((TY_kind(src_ty_idx) == KIND_STRUCT) &&
02042           (field_id /* assign */ = single_field_in_struct (src_ty_idx)))
02043         WN_set_field_id (src_value, field_id);
02044 
02045       // We allow the field_id not zero, comment out the Is_True
02046       //Is_True (WN_field_id(wn) == 0,("Expected field-id zero"));
02047       if ((TY_kind(dst_ty_idx) == KIND_STRUCT) &&
02048           (field_id /* assign */ = 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 /* VHO_DEBUG */
02058     }
02059   }
02060   return wn;
02061 } /* VHO_Lower_Mstid */
02062 
02063 /* ============================================================================
02064  *
02065  * WN *VHO_Lower_Mistore ( WN * wn )
02066  *
02067  * If the structure being copied is sufficiently small, then flatten out the
02068  * structure into a set of non overlapping fields and load/istore the
02069  * individual fields, thereby replacing MISTORE/MLDID by a sequence of
02070  * one or more (controlled by VHO_Struct_Limit) pairs of STID/ISTORE
02071  * over LDID/ILOAD.
02072  *
02073  * The following structures are not currently handled.
02074  *
02075  *   structures containing misaligned fields
02076  *   structures containing bit fields
02077  *   structures containing arrays
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   // WN_OFFSET   field_offset;
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     /* otherwise, we need to get to the subfields, or generate ILOAD, later */
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       /* screen out PREG for now, need to change them into extract sometime */
02126       src_ty_idx     = WN_ty(src_value);
02127       src_ldid = src_value;
02128     }
02129     else if (WN_opcode(src_value) == OPC_MMILOAD) {
02130       // is indirect load, so will be pointer type
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;      // doesn't fit pattern so ignore
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;// don't handle other cases
02141     }
02142     else {
02143       return wn; // don't handle other cases
02144     }
02145   
02146     // Used to check for matching struct alignment,
02147     // but we don't need alignment to match to copy fields
02148     // (may have been related to unused VHO_Struct_Alignment variable).
02149     // if (    TY_align(src_ty_idx) == TY_align(dst_ty_idx)
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       //    VHO_Struct_Alignment = TY_align(dst_ty_idx);
02158       /* Flatten out the structure into non overlapping fields */
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 /* VHO_DEBUG */
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         // preserve offset from original ldid/iload
02175         src_offset = WN_offset(src_value);
02176         // field_offset = 0;
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               // each element uses same field_id,
02209               // so rather than create array refs, just do element copies
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           // field_offset += TY_size(fty_idx);
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 /* VHO_DEBUG */
02245     }
02246   }
02247 
02248   return wn;
02249 } /* VHO_Lower_Mistore */
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       st = WN_st(wn);
02291       if ( ST_sclass(st) == SCLASS_FORMAL && (ST_class(st) == CLASS_VAR ||
02292                 ST_class(st) == CLASS_FUNC ))
02293         if ( code == ADDRESS_PASSED )
02294           Set_ST_addr_taken_passed(st);
02295         else
02296           Set_ST_addr_taken_saved(st);
02297       break;
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 } /* vho_lower_set_st_addr_taken */
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 } /* vho_initialize_bool_info */
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     fprintf ( stderr, "INLINE_BODY_START\n" );
02463     fdump_tree ( stderr, comma_block );
02464 */
02465     value = NULL;
02466     preg  = 0;
02467 
02468     stmt = WN_next(first);
02469 
02470     for (;;) {
02471 /*
02472       fprintf ( stderr, "INLINE stmt\n" );
02473       fdump_tree ( stderr, stmt );
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         fprintf ( stderr, "preg = %d\n", preg );
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         fprintf ( stderr, "INLINE_BODY_END\n" );
02503         fprintf ( stderr, "result\n" );
02504         fdump_tree ( stderr, result );
02505         fprintf ( stderr, "stmt\n" );
02506         fdump_tree ( stderr, stmt );
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         fprintf ( stderr, "preg = %d\n", preg );
02532         fprintf ( stderr, "value\n" );
02533         fdump_tree ( stderr, value );
02534         fprintf ( stderr, "preg = %d\n", preg );
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           fprintf ( stderr, "vho_lower_comma: inline old\n" );
02545           fdump_tree ( stderr, wn );
02546           fprintf ( stderr, "vho_lower_comma: inline new\n" );
02547           fdump_tree ( stderr, result );
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   { // Use a temporary symbol instead of a preg
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       // This can be caused by inlining of a call inside an xpragma, where
02619       // we need to use a temporary instead of a preg.
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     // If this comma node is inside an atomic pragma, insert the lowered
02629     // comma block before the pragma node, since omp-lowerer expects the
02630     // atomic store to be the next stmt after the pragma
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 } /* vho_lower_comma */
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 } /* vho_lower_rcomma */
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   /* simplify
02723    *          ( e && e )
02724    * to
02725    *          ( e )
02726    */
02727 
02728   if ( WN_Simp_Compare_Trees ( l_wn, r_wn ) == 0 ) {
02729 
02730     wn = l_wn;
02731     simplified = TRUE;
02732   }
02733 
02734   /* simplify 
02735    *          ( e && TRUE )
02736    * to
02737    *          ( e )
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   /* simplify 
02749    *          ( e && FALSE )
02750    * to
02751    *          ( FALSE )
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   /* simplify 
02763    *          ( TRUE && e )
02764    * to
02765    *          ( e )
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   /* simplify 
02777    *          ( FALSE && e )
02778    * to
02779    *          ( FALSE )
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   /* simplify
02791    *           ( ( e1 || e2 ) && ( e1 || e3 ) )
02792    * to
02793    *           ( e1 || ( e2 && e3 ) )
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   /* simplify
02821    *          ( ( ( e & c1 ) != 0 ) && ( ( e & c2 ) != 0 ) )
02822    * to
02823    *          ( ( e & ( c1 | c2 ) ) == ( c1 | c2 ) )
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 } /* vho_simplify_cand */
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   /* simplify 
02931    *          ( e || TRUE )
02932    * to
02933    *          ( TRUE )
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   /* simplify 
02945    *          ( e && FALSE )
02946    * to
02947    *          ( e )
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   /* simplify 
02959    *          ( TRUE || e )
02960    * to
02961    *          ( TRUE )
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   /* simplify 
02973    *          ( FALSE || e )
02974    * to
02975    *          ( e )
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   /* simplify
02987    *           ( ( e1 && e2 ) || ( e1 && e3 ) )
02988    * to
02989    *           ( e1 && ( e2 || e3 ) )
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   /* simplify
03017    *          ( ( ( e & c1 ) != 0 ) || ( ( e & c2 ) != 0 ) )
03018    * to
03019    *          ( e & ( c1 | c2 ) )
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 } /* vho_simplify_cior */
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 // >> WHIRL 0.30: replaced OPC_CAND by OPC_B and OPC_I4 variants
03091 // TODO WHIRL 0.30: get rid of OPC_I4 variant
03092     case OPC_BCAND:
03093     case OPC_I4CAND:
03094 // << WHIRL 0.30: replaced OPC_CAND by OPC_B and OPC_I4 variants
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 // >> WHIRL 0.30: replaced OPC_CIOR by OPC_B and OPC_I4 variants
03102 // TODO WHIRL 0.30: get rid of OPC_I4 variant
03103     case OPC_BCIOR:
03104     case OPC_I4CIOR:
03105 // << WHIRL 0.30: replaced OPC_CIOR by OPC_B and OPC_I4 variants
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 } /* vho_simplify_cand_cior */
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   if (    bool_info->opcode != OPCODE_UNKNOWN
03163        && bool_info->opcode != opcode ) {
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       else
03210       if ( cflow_bool_info1.used_true_label ) {
03211 
03212         WN *wn_goto = WN_CreateGoto ( (ST_IDX) NULL,
03213                                       cflow_bool_info1.false_label );
03214         WN_Set_Linenum ( wn_goto, VHO_Srcpos );
03215         WN_INSERT_BlockLast ( block, wn_goto );
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       else
03307       if (    bool_info->opcode != opcode
03308            && bool_info->opcode != OPCODE_UNKNOWN ) {
03309 
03310   WN *wn_goto
03311     = WN_CreateGoto ( (ST_IDX) NULL, cflow_bool_info2.false_label );
03312         WN_Set_Linenum ( wn_goto, VHO_Srcpos );
03313         WN_INSERT_BlockLast ( block, wn_goto );
03314         cflow_bool_info2.used_false_label = TRUE;
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       // TODO: Frequency data for the following
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 } /* vho_lower_cand_cior */
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     // CSELECT                             IF
03437     //  <test>                              <test>
03438     //  <then_expr>                        THEN
03439     //  <else_expr>            ===>          <then_expr>
03440     //                                      STID <preg>
03441     //                                     ELSE
03442     //                                       <else_expr>
03443     //                                      STID <preg>
03444     //                                     END_IF
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         /* kt != 0 ? kt : 0 => kt */
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   /* (a-b) >= 0 ? (a-b) : (b-a) => abs(a-b) */
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   /* Handle saturation arithmetic SUB operator by converting it 
03534    * to an intrinsic 
03535    * x =  (y >= 0x8000) ? y - 0x8000 : 0; 
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     // Create parm nodes for intrinsic op
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         /* x > 0 ? x : -x => abs(x) */
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             fdump_tree ( stderr, wn );
03599 */
03600             return wn;
03601           }
03602         }
03603 
03604         /* x >= y ? x : y => max(x) */
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           fdump_tree ( stderr, wn );
03626 */
03627           return wn;
03628         }
03629 
03630         /* x <= y ? x : y => min(x) */
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           fdump_tree ( stderr, wn );
03652 */
03653           return wn;
03654         }
03655 #ifdef TARG_NVISA
03656         // gcc converts x += (y == 0) into a cond of x+1 or x.
03657         // Would be more efficient for us if generated straight line code
03658         // of t = (y == 0); x += t;
03659         // Rather than try to change what gcc generates,
03660         // instead look for x and x+-1 in operands,
03661         // then transform that back to above 2-stmt sequence.
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               // either adding or subtracting the condition result
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         // similar to above, but check for cond ? x|1 : x; which is just x|cond
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 // could look for other patterns, but wait and see what shows up.
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       // CSELECT                             IF
03830       //  <test>                              <test>
03831       //  <then_expr>                        THEN
03832       //  <else_expr>            ===>          <then_expr>
03833       //                                      STID <preg>
03834       //                                     ELSE
03835       //                                       <else_expr>
03836       //                                      STID <preg>
03837       //                                     END_IF
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 } /* vho_lower_cselect */
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 /* VHO_DEBUG */
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 } /* vho_lower_combine_loads */
04162 
04163 #ifdef KEY
04164 // Utility function to traverse through an aggregate type and determine
04165 // if any field/element is floating-point: bug 7770
04166 // Called by vho_lower_mparm(), if there is any FP field, the mparm cannot
04167 // be transformed.
04168 // Return 1 if OK to transform, 0 if cannot be transformed.
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 // If the struct under MPARM is of size 4 or 8, change LDID from M
04199 // type to the appropriate type (U4/U8).
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)  // bug 12809
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     // bugs 9989, 10139
04230     // bug fix for OSP_258
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 /* assign */ = 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  * WN *vho_lower_expr ( WN * wn, WN * block, BOOL_INFO * bool_info )
04245  *
04246  * Given a tree, this routine traverses the tree performing lowering
04247  * actions for
04248  *
04249  *   SWITCH into a sequence of if-else, compgoto and/or binary search
04250  *   MSTORE into STID/ISTORE over LDID/ILOAD if the structure is
04251  *     sufficiently small.
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           fprintf ( stderr, "ILOAD->LDID old\n" );
04294           fdump_tree ( stderr, wn );
04295           fprintf ( stderr, "ILOAD->LDID new\n" );
04296           fdump_tree ( stderr, wn1 );
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   // Fortran expression like a[i]**n can be vectorized if we expand 
04332   // inline before LNO. However, we do this only for small values of n.
04333   // The math library (powd) may do a better job for large values of n.
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); //bug 8576
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:  // bug fix for OSP_184
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       // check for a load past the end of the struct
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       /* No need to lower */
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       comma_block = vho_lower_block (WN_kid0(wn));
04555       WN_INSERT_BlockLast ( block, comma_block );
04556       wn = vho_lower_expr (WN_kid1(wn), block, bool_info);
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       // By default, generate rotate instruction only if it is C++ (bug 7932)
04574       // Can be crontrolled by internal flag -VHO:rotate
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         // This is now unused code, but keep the fix for the record.
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 } /* vho_lower_expr */
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 } /* vho_lower_compgoto */
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 } /* vho_lower_switch */
04637 
04638 
04639 static WN *
04640 vho_lower_casegoto ( WN * wn, WN * block )
04641 {
04642   return wn;
04643 } /* vho_lower_casegoto */
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     // TRUEBR <test> <true_label>    ===>    <test>
04674     //                                       GOTO <true_label>
04675     //                                       LABEL <false_label>
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     // Don't update feedback; let propagation handle
04687 
04688     wn = NULL;
04689   }
04690 
04691   return wn;
04692 } /* vho_lower_truebr */
04693 
04694 
04695 static WN *
04696 vho_lower_return ( WN * wn, WN * block )
04697 {
04698   return wn;
04699 } /* vho_lower_return */
04700 
04701 static BOOL
04702 vho_singleton_field (TY_IDX ty_idx)
04703 {
04704   return FALSE;
04705 } /* vho_singleton_field */
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 } /* vho_lower_return_val */
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 } /* vho_lower_istore */
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 } /* vho_lower_mstore */
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     /* lower MSTID */
04741     wn = VHO_Lower_Mstid (wn);
04742   }
04743 
04744   return wn;
04745 } /* vho_lower_stid */
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) // okay if producing C
04755   {
04756     // We only support calls to locally defined functions
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 } /* vho_lower_call */
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       //I never see a class name longer than 999
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  //NOTE: Do NOT call this routine twice. Because devirtualization more than one time will absulutely degrade the performance.
04879   //First do devirtualization transform for indirect call. Then it will call vho_lower_xxx() for 
04880   //each of the new statements introduced by this transform. 
04881   //
04882   //The devirtualization transforms as below:
04883   //
04884   //The codes:
04885   // BLODK
04886   //     ... ...
04887   //       prepare_arguments
04888   //       U8ILOAD fun_ptr
04889   //     I4ICALL 
04890   //     ... ...
04891   // END_BLODK
04892   //Will be translated into:
04893   // BLOCK
04894   //   ... ...
04895   //   IF
04896   //       U8ILOAD fun_ptr
04897   //       U8LDA foo_1's address
04898   //     U8U8EQ
04899   //   THEN
04900   //     BLODK
04901   //         prepare_arguments
04902   //       I4CALL foo_1
04903   //     END_BLODK
04904   //   ELSE
04905   //     BLOCK
04906   //       IF
04907   //           U8ILOAD fun_ptr
04908   //           U8LDA foo_2's address
04909   //         U8U8EQ
04910   //       THEN
04911   //         BLOCK
04912   //             prepare_arguments
04913   //           I4CALL foo_2
04914   //         END_BLOCK
04915   //       ELSE
04916   //         BLOCK
04917   //             prepare_arguments
04918   //             I4ILOAD fun_ptr
04919   //           I4ICALL
04920   //         END_BLOCK
04921   //       ENDIF
04922   //     END_BLOCK
04923   //   ENDIF
04924   //   ... ...  // END_BLOCK
04925 
04926   // We get the name of funtion <foo1> from profile feedback,
04927   // Then we lookup symbol table for its <TY_IDX> and <ST*>.
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       //TODO: add break to save tranverse time.
04984       // break;
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         //  DevWarn("Found similar PU(%s) for foo1(%s)\n",&Str_Table[str_idx],nameoffoo1);
05019         }
05020         else 
05021         {
05022         //  DevWarn("Found(multiple so ignore) similar PU(%s) for foo1(%s)\n",&Str_Table[str_idx],nameoffoo1);
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   //empty the stmt
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   //Delete the map info. We delete it from <Cur_PU_Feedback>
05170   Cur_PU_Feedback->Delete(wn);
05171 
05172  // wn_if = vho_lower_if_ignore_else_for_devirtualize(wn_if,block);
05173   wn_if = vho_lower_if(wn_if,block);
05174   
05175   return wn_if;
05176 } /* vho_lower_icall */
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 } /* vho_lower_intrinsic_call */
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 } /* vho_lower_eval */
05202 
05203 
05204 static WN *
05205 vho_lower_pragma ( WN * wn, WN * block )
05206 {
05207   return wn;
05208 } /* vho_lower_pragma */
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 } /* vho_lower_xpragma */
05233 
05234 
05235 static WN *
05236 vho_lower_prefetch ( WN * wn, WN * block )
05237 {
05238 #ifdef KEY // bug 9499
05239   // Kid0 may need to be lowered, for example, if it is a call.
05240   WN_kid0(wn) = vho_lower_expr ( WN_kid0(wn), block, NULL );
05241 #endif
05242   return wn;
05243 } /* vho_lower_prefetch */
05244 
05245 
05246 static WN *
05247 vho_lower_prefetchx ( WN * wn, WN * block )
05248 {
05249   return wn;
05250 } /* vho_lower_prefetchx */
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 } /* vho_lower_io */
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 } /* vho_lower_falsebr */
05301 
05302 
05303 static WN *
05304 vho_lower_trap ( WN * wn, WN * block )
05305 {
05306   return wn;
05307 } /* vho_lower_trap */
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 } /* vho_lower_asm_stmt */
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           fprintf ( stderr, "ISTORE->STID old\n" );
05422           fdump_tree ( stderr, wn );
05423           fprintf ( stderr, "ISTORE->STID new\n" );
05424           fdump_tree ( stderr, wn1 );
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 } /* vho_lower_stmt */
05537 
05538 
05539 #ifdef KEY
05540 // Returns the last statement in the region (after recursively
05541 // traversing any contained region). If EXTRACT is true, then
05542 // extract this last statement if it is XPRAGMA.
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   // Lower pragmas for MP regions
05596   if (WN_region_kind(wn) == REGION_KIND_MP)
05597   {
05598 #ifdef Is_True_On
05599     {
05600       // Verify the assumption that WN_region_pragmas does not contain any
05601       // non-pragma node before lowering
05602       // e.g. C++ EH region nodes can contain non-pragma nodes here.
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   // use fmtassert if common/com is built without debug
05610         FmtAssert (WN_operator(pragmas) == OPR_PRAGMA ||
05611              WN_operator(pragmas) == OPR_XPRAGMA ||
05612              // Allow region nodes whose last stmt is xpragma
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       // move any non-pragma stmt to before the region
05629       // bug 5130: also move inline-pragmas outside
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         // increment
05637         iter = WN_next (iter);
05638   // fail in debug mode, a pragma must be the last node
05639   Is_True (WN_next (move), ("Pragma node not found in region pragmas"));
05640   // remove the node from region-pragmas
05641   if (WN_operator(move) == OPR_REGION)
05642   { // bug 14036 */
05643     WN * stmt = vho_last_stmt_in_region (move, TRUE /* extract out */);
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   // bug 2631:
05656   // If we have a COMPGOTO stmt inside the region, move it outside the
05657   // region.
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     // Now insert the compgoto after the region
05669     WN_INSERT_BlockLast (block, last);
05670     wn = NULL;  // don't insert it again
05671   }
05672   return wn;
05673 } /* vho_lower_region */
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 } /* vho_lower_region */
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   // relax assertion, and convert it to debug mode
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   // Relax it for DO_LOOP generated for C/C++ OpenMP, when the termination
05732   // test has function call
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 //Fail_FmtAssertion ("TODO_NEW_SYMTAB: VHO_Lower: vho_lower_do_loop");
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 } /* vho_lower_do_loop */
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     // Insert a subset of:
05783     // LABEL <loop_label>
05784     // <while_body>
05785     // <test_block>
05786     // GOTO <loop_label>
05787     // <false_label>
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     // Don't update feedback; let propagate handle updating frequencies
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 } /* vho_lower_do_while */
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 } /* vho_lower_check_labels */
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 /*    vho_lower_labels_referenced = TRUE; */
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 /*    vho_lower_labels_referenced = TRUE; */
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 /*    vho_lower_labels_referenced = TRUE; */
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 /*    vho_lower_labels_referenced = TRUE; */
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 } /* vho_lower_rename_labels_defined */
06627 
06628 
06629 //LLC LLC (A)
06630 /*-----------------------------------------------------
06631 This routine replaces all the LDIDs from a temp defined 
06632 in stid by the "org" LDID from the original variable.
06633 It also sets "replaced" TRUE if any is replaced
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 { //Recursively Substitute_LDID the kids
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  This routine tries to eliminate the introduced temp in the while loop, say 264, 
06654  in the example below so that the while loop can be transformed to DO_LOOP later.
06655 
06656  BLOCK
06657   I4I4LDID 0 <2,2,len> T<4,.predef_I4,4>   --> org_var
06658  I4STID 264 <1,2,.preg_I4> T<4,.predef_I4,4> # <preg> --> st_tmp
06659    I4I4LDID 264 <1,2,.preg_I4> T<4,.predef_I4,4> # <preg>
06660    I4INTCONST constant_number
06661   I4ADD
06662  I4STID 0 <2,2,len> T<4,.predef_I4,4>
06663  END_BLOCK
06664   I4I4LDID 264 <1,2,.preg_I4> T<4,.predef_I4,4> # <preg>
06665   I4INTCONST 0 (0x0)
06666  I4I4GT   -->cmp_wn
06667 I4COMMA // only this kind of pattern will be processed
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);   //comparison 
06679       WN *block_wn = WN_kid0(test_wn); //BLOCK
06680       WN *st_tmp = WN_first(block_wn); //1st statement in BLOCK
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; //count the number of other statments in BLOCK
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           // Find the pattern that "original varialbe" is "post-incremented" by constant
06695           // by loading the value from the tmp register
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                  //Deal with the test condition -- need to subtract the post-increment
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               } //if replaced
06716           }
06717      }  
06718   } //COMMA & BLOCk
06719 } //Eliminate_Temp_In_While
06720 // LLC (A) 
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   // Check if the inner do loops can be fused.
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         // potential mainloop
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           // preloop and postloop should have only one stmt.
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   // Recurse
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   // Collect the do loops to be fused.
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   // Fuse the loops.
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   // Fuse and move definitions and uses closer together.
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   // another safety check.
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   // If more than one iload_iload_opnd then return nothing
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   // The body of the loop should contain an assignment statement then an 
06947   // if-statement that contains another loop then a label statement and a
06948   // statement to update the loop variable.
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   // Is it safe and useful to do this distribution and interchange based on the 
06980   // access patterns? If not, then return FALSE.
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   // Find the operand that is ILOAD(ILOAD(...))
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   // Extract the loop indices from the access.
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