Open64 (mfef90, whirl2f, and IR tools)  TAG: version-openad; SVN changeset: 916
wn_simp_code.h
Go to the documentation of this file.
00001 /*
00002 
00003   Copyright (C) 2000, 2001 Silicon Graphics, Inc.  All Rights Reserved.
00004 
00005   This program is free software; you can redistribute it and/or modify it
00006   under the terms of version 2 of the GNU General Public License as
00007   published by the Free Software Foundation.
00008 
00009   This program is distributed in the hope that it would be useful, but
00010   WITHOUT ANY WARRANTY; without even the implied warranty of
00011   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
00012 
00013   Further, this software is distributed without any warranty that it is
00014   free of the rightful claim of any third person regarding infringement 
00015   or the like.  Any license provided herein, whether implied or 
00016   otherwise, applies only to this software file.  Patent licenses, if 
00017   any, provided herein do not apply to combinations of this program with 
00018   other software, or any other product whatsoever.  
00019 
00020   You should have received a copy of the GNU General Public License along
00021   with this program; if not, write the Free Software Foundation, Inc., 59
00022   Temple Place - Suite 330, Boston MA 02111-1307, USA.
00023 
00024   Contact information:  Silicon Graphics, Inc., 1600 Amphitheatre Pky,
00025   Mountain View, CA 94043, or:
00026 
00027   http://www.sgi.com
00028 
00029   For further information regarding this notice, see:
00030 
00031   http://oss.sgi.com/projects/GenInfo/NoticeExplan
00032 
00033 */
00034 
00035 #if defined(BACK_END) && defined(WN_SIMP_WORKING_ON_WHIRL)
00036 #include "be_symtab.h"
00037 #endif
00038 
00039 /*===================================================================================
00040 
00041 wn_simp_code.h
00042 
00043 This file contains the routines which do the real work of the simplifier. It is 
00044 written so that it can easily be made to work on data structures other than WHIRL.
00045 
00046 How to use this:
00047 
00048 Several functions and macros need to be created by the user. These are
00049 listed below.  Although the data structure does not need to be a WHIRL
00050 node, it must have the same information as a WHIRL node accessible to
00051 it. Define the macros and functions, then include this file to get a
00052 simplifier. See the files common/com/wn_simp.{cxx,h} for an example.
00053 
00054 The example below shows all the definitions necessary to build the simplifier
00055 for WHIRL trees. 
00056 
00057 
00058 --------------------------------------------------------------------------------------
00059 
00060 
00061 // define the type simpnode as the basic data type
00062 typedef WN * simpnode;
00063 
00064 // These are accessors which take a simpnode and return the various 
00065 // attributes/children from it
00066 
00067 #define SIMPNODE_opcode WN_opcode                   // get a WHIRL opcode from a simpnode
00068 #define SIMPNODE_operator(x) WN_operator(x)  // get a WHIRL opcode from a simpnode
00069 #define SIMPNODE_rtype(x) WN_rtype(x) // get the rtype from a node
00070 #define SIMPNODE_desc(x) WN_desc(x)   // get the desc from a node
00071 #define SIMPNODE_load_offset WN_load_offset         //   " "   "   load_offset
00072 #define SIMPNODE_cvtl_bits WN_cvtl_bits             //   " "   "   cvtl_bits
00073 #define SIMPNODE_st WN_st
00074 #define SIMPNODE_kid0 WN_kid0
00075 #define SIMPNODE_kid1 WN_kid1
00076 #define SIMPNODE_element_size WN_element_size
00077 #define SIMPNODE_idname_offset WN_idname_offset
00078 #define SIMPNODE_lda_offset WN_lda_offset           // etc....
00079 #define SIMPNODE_num_dim WN_num_dim
00080 #define SIMPNODE_element_size WN_element_size
00081 #define SIMPNODE_array_base WN_array_base
00082 #define SIMPNODE_array_index WN_array_index
00083 #define SIMPNODE_array_dim WN_array_dim
00084 #define SIMPNODE_intrinsic WN_intrinsic
00085 #define SIMPNODE_kid_count WN_kid_count
00086 #define SIMPNODE_kid WN_kid
00087 #define SIMPNODE_const_val WN_const_val             // get the 64 bit immediate integer constant
00088                                                     // value from a simpnode
00089 #define SIMPNODE_fconst_val Const_Val               // get a TCON from a simpnode for all types
00090                                                     // but integer
00091 #define SIMPNODE_field_id WN_field_id               // get the field id
00092 #define SIMPNODE_i_field_id WN_field_id             // field id for indirect
00093 #define SIMPNODE_bit_offset WN_bit_offset           // get the bit offset
00094 #define SIMPNODE_i_bit_offset WN_bit_offset         // bit offset for indirect
00095 
00096 // functions required
00097 
00098 // simpnode SIMPNODE_SimpCreateExp1(OPCODE, simpnode)  // create a 1 operand expression
00099 // simpnode SIMPNODE_SimpCreateExp2(OPCODE, simpnode, simpnode)  // create a two operand expression
00100 // simpnode SIMPNODE_SimpCreateExp3(OPCODE, simpnode, simpnode, simpnode)  // create a 3 operand expression
00101 // void SIMPNODE_TREE_DELETE(simpnode)                 // delete a simpnode and all of its children
00102                                                     // This is called when the node is never used in
00103                                                     // the expression again. 
00104 // void SIMPNODE_DELETE(simpnode)                   // delete only the argument
00105                                                     // leaving the children intact
00106 // simpnode SIMPNODE_CopyNode(simpnode)             // create a copy of a node. It is guaranteed
00107                                                     // to be placed into the tree. 
00108 // simpnode SIMPNODE_CreateIntconst(OPCODE, int64)  // create an integer constant simpnode from a
00109                                                     // WHIRL T1INTCONST opcode and a value
00110 // simpnode SIMPNODE_CreateFloatconstFromTcon(TCON) // create a simpnode representing a floating
00111                                                     // point or complex constant from a TCON node
00112 
00113 
00114 #define SIMPNODE_SimpCreateExp1 WN_SimpCreateExp1
00115 #define SIMPNODE_SimpCreateExp2 WN_SimpCreateExp2
00116 #define SIMPNODE_SimpCreateExp3 WN_SimpCreateExp3
00117 #define SIMPNODE_SimpCreateExtract WN_SimpCreateExtract
00118 #define SIMPNODE_SimpCreateDeposit WN_SimpCreateDeposit
00119 #define SIMPNODE_TREE_DELETE WN_DELETE_Tree
00120 #define SIMPNODE_DELETE WN_Delete
00121 #define SIMPNODE_CopyNode WN_CopyNode
00122 #define SIMPNODE_CreateIntconst WN_CreateIntconst
00123 #define SIMPNODE_CreateFloatconstFromTcon Make_Const
00124 
00125 // Externally visible routines. These three are defined in wn_simp_code.h. They need
00126 // a name defined here and in whatever external interface file exists for this routine.
00127 // The argument lists for these are fixed. Only the names need be defined.
00128 // Each of these returns a simpnode if simplification was done, or NULL if
00129 // no simplifications could be performed.
00130 //
00131 // simpnode SIMPNODE_SimplifyExp1(OPCODE opc, simpnode k0) 
00132 // simpnode SIMPNODE_SimplifyExp2(OPCODE opc, simpnode k0, simpnode k1) 
00133 // simpnode SIMPNODE_SimplifyExp3(OPCODE opc, simpnode k0, simpnode k1, simpnode k2) 
00134 // simpnode SIMPNODE_SimplifyCvtl(OPCODE opc, INT16 cvtl_bits, simpnode k0) 
00135 
00136 #define SIMPNODE_SimplifyExp1 WN_SimplifyExp1
00137 #define SIMPNODE_SimplifyExp2 WN_SimplifyExp2
00138 #define SIMPNODE_SimplifyExp3 WN_SimplifyExp3
00139 #define SIMPNODE_SimplifyCvtl WN_SimplifyCvtl
00140 
00141 ================================================================================================
00142 ================================================================================================*/
00143 
00144 
00145 /* Size in bits of each type */
00146 #define SIMP_TYPE_SIZE(x) MTYPE_size_min(x)
00147 
00148 /* Claasification macros */
00149    
00150 #define SIMP_IS_TYPE_INTEGRAL(x) ((MTYPE_type_class(x)&MTYPE_CLASS_INTEGER)!=0)
00151 #define SIMP_IS_TYPE_UNSIGNED(x) ((MTYPE_type_class(x)&MTYPE_CLASS_UNSIGNED)!=0)
00152 #define SIMP_IS_TYPE_FLOATING(x) ((MTYPE_type_class(x)&MTYPE_CLASS_FLOAT)!=0)
00153 #define SIMP_IS_TYPE_COMPLEX(x) ((MTYPE_type_class(x)&MTYPE_CLASS_COMPLEX)!=0)
00154 
00155 /* saves a little typing */
00156 #define OPC_FROM_OPR(opr,type) (OPCODE_make_op(opr,type,MTYPE_V))
00157 
00158 /* has the package ever been initialized? */
00159 static BOOL SIMPNODE_simp_initialized = FALSE;
00160 static void SIMPNODE_Simplify_Initialize( void );
00161 
00162 /* Tracing functions */
00163 /* Dump a tree if a simplification occured */
00164 static BOOL trace_trees;
00165 #define SHOW_TREE(opc,k0,k1,result) if ((result!=NULL) && trace_trees) show_tree(opc,k0,k1,result)
00166 
00167 
00168 /* Print the rule causing a simplification */
00169 static BOOL trace_rules;
00170 
00171 #define SHOW_RULE(x) show_rule(x)
00172 
00173 static void show_rule(const char * rule) 
00174 {
00175    if (trace_rules) {
00176       fprintf(TRACEFILE,"Rule: %s\n",rule);
00177    }
00178 }
00179 
00180 
00181 /* used before their definition */
00182 static simpnode SIMPNODE_ConstantFold1(OPCODE opc, simpnode k0);
00183 static simpnode SIMPNODE_ConstantFold2(OPCODE opc, simpnode k0, simpnode k1);
00184 static simpnode SIMPNODE_SimpCreateExp3(OPCODE opc, simpnode k0, simpnode k1, simpnode k2);
00185 static simpnode SIMPNODE_SimpCreateExp2(OPCODE opc, simpnode k0, simpnode k1);
00186 static simpnode SIMPNODE_SimpCreateExp1(OPCODE opc, simpnode k0);
00187 static simpnode SIMPNODE_SimpCreateExtract(OPCODE opc, INT16 boffset, INT16 bsize, simpnode k0);
00188 static simpnode SIMPNODE_SimpCreateDeposit(OPCODE opc, INT16 boffset, INT16 bsize,
00189                                            simpnode k0, simpnode k1);
00190 
00191 #ifdef SIMPNODE_SimpCreateCvtl
00192 static simpnode SIMPNODE_SimpCreateCvtl(OPCODE opc, INT16 bits, simpnode k0);
00193 #endif
00194 
00195 /* Utility macros */
00196 
00197 /* Simple wrapper for SIMPNODE_CreateIntconst */
00198 #define SIMP_INTCONST(ty,value) SIMPNODE_CreateIntconst(OPC_FROM_OPR(OPR_INTCONST,ty),(value))
00199 
00200 /* Simple wrapper for Make_Const */
00201 #define SIMP_FLOATCONST(ty,value) SIMPNODE_CreateFloatconstFromTcon(Host_To_Targ_Float(ty,(value)))
00202 
00203 /* Delete a whirl tree. Done this way (for now) for debugging purposes */
00204 static void simp_delete_tree(simpnode w)
00205 {
00206    if (!trace_trees) SIMPNODE_TREE_DELETE(w);
00207 }
00208 
00209 static void simp_delete(simpnode w)
00210 {
00211    if (!trace_trees) SIMPNODE_DELETE(w);
00212 }
00213 
00214 #define SIMP_DELETE(x) simp_delete(x)
00215 #define SIMP_DELETE_TREE(x) simp_delete_tree(x)
00216 
00217 #define SIMP_TYPE(x) SIMPNODE_rtype(x)
00218 
00219 inline simpnode SIMPNODE_GetDefinition(simpnode x)
00220 {
00221 #ifdef BACK_END
00222 #ifdef WN_SIMP_WORKING_ON_WHIRL
00223   if (SIMPNODE_operator(x) == OPR_LDID && ST_class(WN_st(x)) == CLASS_PREG) {
00224     WN *home = Preg_Home(WN_load_offset(x));
00225     if (home) x = home;
00226   }
00227 #else
00228   // TODO: investigate how to do this with codereps in the optimizer
00229 #endif
00230 #endif
00231   return x;
00232 }
00233 
00234 /* Decide if a node is a constant or not */
00235 
00236 inline BOOL SIMP_Is_Int_Constant(simpnode x)
00237 {
00238   return SIMPNODE_operator(x)==OPR_INTCONST;
00239 }
00240 
00241 inline BOOL SIMP_Is_Flt_Constant(simpnode x)
00242 {
00243   x = SIMPNODE_GetDefinition(x);
00244   return SIMPNODE_operator(x)==OPR_CONST;
00245 }
00246 
00247 inline BOOL SIMP_Is_Constant(simpnode x)
00248 {
00249   x = SIMPNODE_GetDefinition(x);
00250   return    SIMPNODE_operator(x)==OPR_INTCONST
00251          || SIMPNODE_operator(x)==OPR_CONST;
00252 }
00253 
00254 
00255 /* Get the value of a constant node */
00256 
00257 inline INT64 SIMP_Int_ConstVal(simpnode x)
00258 {
00259   x = SIMPNODE_GetDefinition(x);
00260   return SIMPNODE_const_val(x);
00261 }
00262 
00263 inline TCON SIMP_Flt_ConstVal(simpnode x)
00264 {
00265   x = SIMPNODE_GetDefinition(x);
00266   return SIMPNODE_fconst_val(x);
00267 }
00268 
00269 
00270 #define IS_POWER_OF_2(x) (((x)!=0) && ((x) & ((x)-1))==0)
00271 
00272 /* Utility routine to create a 64 bit number with from 0 to 64 bits in it.
00273  */
00274 static INT64 create_bitmask(INT64 num_bits)
00275 {
00276    if (num_bits == 0) return (0);
00277    if (num_bits == 64) return (-1LL);
00278    return ((1LL << num_bits) - 1);
00279 }
00280 
00281 /* WEI: this conflicts with the log2 function in C library, so use a namespace around it */
00282 
00283 namespace wn_simp_code {
00284   /* Compute FLOOR(log2(x))
00285    * 
00286    */
00287   static UINT64 log2(UINT64 x)
00288     {
00289       UINT64 l;
00290       
00291       l = 0;
00292       while (x > 1) {
00293         x >>= 1;
00294         ++l;
00295       }
00296       return (l);
00297     }
00298 }
00299 
00300 /***********************************************************/
00301 /* 
00302  * Some floating point and other constant handling utilities
00303  */
00304 
00305 
00306 /* Determine if an add overflows or not, and do the add in any case */
00307 /* Return TRUE if the add is OK. */
00308 
00309 static BOOL is_add_ok(INT64 *sum, INT64 i1, INT64 i2, TYPE_ID ty)
00310 {
00311    *sum = i1 + i2;
00312 
00313    switch (ty) {
00314     case MTYPE_U4:
00315       if ((UINT64) *sum > UINT32_MAX) return(FALSE);
00316       break;
00317 
00318     case MTYPE_I4:
00319       if (*sum > INT32_MAX) return(FALSE);
00320       if (*sum < INT32_MIN) return(FALSE);
00321       break;
00322 
00323     case MTYPE_U8:
00324       if ((UINT64) *sum < (UINT64) i1) return (FALSE); 
00325       break;
00326 
00327     case MTYPE_I8:
00328       if ((i1^i2) < 0) return (TRUE); /* can't overflow if signs are different */
00329       /* Signs are the same */
00330       if ((i1 > 0 || i2 > 0) && *sum <= 0) return (FALSE);
00331       if ((i1 < 0 || i2 < 0) && *sum >= 0) return (FALSE); 
00332       break;
00333       
00334     default:
00335       /* Don't recognize the type, play it safe */
00336       return (FALSE);
00337    }
00338 
00339    return (TRUE);
00340 }
00341 
00342 static BOOL is_sub_ok(INT64 *sum, INT64 i1, INT64 i2, TYPE_ID ty)
00343 {
00344    *sum = i1 - i2;
00345 
00346    switch (ty) {
00347 
00348     case MTYPE_I4:
00349       if (*sum > INT32_MAX) return(FALSE);
00350       if (*sum < INT32_MIN) return(FALSE);
00351       break;
00352 
00353     case MTYPE_U4:
00354     case MTYPE_U8:
00355       if ((UINT64) i2 > (UINT64) i1) return FALSE;
00356       break;
00357 
00358     case MTYPE_I8:
00359       if ((i1^i2) >= 0) return (TRUE); /* can't overflow if signs are same */
00360       /* Signs are different */
00361       if ((i1 > i2) && *sum <= 0) return (FALSE);
00362       if ((i1 < i2) && *sum >= 0) return (FALSE); 
00363       break;
00364       
00365     default:
00366       /* Don't recognize the type, play it safe */
00367       return (FALSE);
00368    }
00369 
00370    return (TRUE);
00371 }
00372 
00373 
00374 
00375 /*
00376  * This utility determines if a floating point constant is equal to 
00377  * a specified double-precision value. This gets us everything we need, since we don't
00378  * need to compare against more than a few values, all of which are exact as floats,
00379  * doubles or quads.
00380  */
00381 
00382 static BOOL is_floating_equal(simpnode k, double d)
00383 {
00384    TCON kval,dval;
00385    INT64 eqval;
00386    TYPE_ID ty;
00387 
00388    if (!SIMP_Is_Constant(k)) return (FALSE);
00389    ty = SIMPNODE_rtype(k);
00390    if (SIMP_IS_TYPE_INTEGRAL(ty) || SIMP_IS_TYPE_COMPLEX(ty)) return (FALSE);
00391    
00392    kval = SIMP_Flt_ConstVal(k);
00393    
00394    switch (ty) {
00395     case MTYPE_F4:
00396     case MTYPE_F8:
00397       return (d == Targ_To_Host_Float(kval));
00398 
00399     case MTYPE_FQ:
00400       /* Tricky: we must convert d to a quad */
00401       dval = Host_To_Targ_Float(MTYPE_FQ, d);
00402       eqval = Targ_To_Host(Targ_WhirlOp(OPC_I4FQEQ,dval,kval,NULL));
00403       return (eqval != 0);
00404    }
00405    return (FALSE);
00406 }
00407 
00408 /*
00409  * This utility determines if a constant is equal to 
00410  * a specified double-precision value. This gets us everything we need, since we don't
00411  * need to compare against more than a few values, all of which are exact as floats,
00412  * doubles or quads. This routine also accept integers types, but the integer value must 
00413  * be less than 2**52. This is not checked. 
00414  */
00415 static BOOL is_numeric_equal(simpnode k, double d)
00416 {
00417    INT64 c;
00418    UINT64 uc;
00419    TYPE_ID ty;
00420 
00421    if (!SIMP_Is_Constant(k)) return (FALSE);
00422    ty = SIMPNODE_rtype(k);
00423    if (SIMP_IS_TYPE_COMPLEX(ty)) return (FALSE);
00424    if (SIMP_IS_TYPE_FLOATING(ty)) return (is_floating_equal(k,d));
00425    if (SIMP_IS_TYPE_UNSIGNED(ty)) {
00426       uc = (UINT64) SIMP_Int_ConstVal(k);
00427       return (uc == d);
00428    } else if (SIMP_IS_TYPE_INTEGRAL(ty)) {
00429       c = SIMP_Int_ConstVal(k);
00430       return (c == d);
00431    }
00432    return (FALSE);
00433 }
00434 
00435 /*================================================================
00436  * This utility routine takes an LDA node, sets up base and offset, and marks a couple of 
00437  * flags. See PV 619250 for more explanation of why the various return values are 
00438  * what they are. 
00439  */
00440 
00441 #define LDA_CANNOT_BE_ZERO 1       // Address of symbol cannot be 0
00442 #define LDA_EQUIV_POSSIBLE 2       // Might have same address as another symbol
00443 #define LDA_UNTESTABLE 4           // Can't figure out anything about the symbol
00444 typedef INT LDA_FLAGS;
00445 
00446 static LDA_FLAGS get_lda_info(simpnode lda, INT64& offset, ST_IDX& base_sym_idx)
00447 {
00448    ST_IDX base_idx=SIMPNODE_st_idx(lda);
00449    ST *base;
00450    LDA_FLAGS r = 0;
00451    
00452    base = ST_ptr(base_idx);
00453    offset = SIMPNODE_lda_offset(lda);
00454 
00455    while ( base && (ST_sclass(base) != SCLASS_TEXT) && (ST_base(base) != base)) { 
00456       offset += ST_ofst(base);
00457       base = ST_base(base); 
00458    }
00459    
00460    /* Exit if the base index isn't set properly. This could happen for
00461     * a number of legitimate reasons
00462     */
00463    if (!base) {
00464       return (LDA_UNTESTABLE | LDA_CANNOT_BE_ZERO | LDA_EQUIV_POSSIBLE);
00465    }
00466    
00467    offset += ST_ofst(base);
00468    base_sym_idx = ST_st_idx(*base);
00469    
00470    if ((ST_export(base) != EXPORT_PREEMPTIBLE) &&
00471        (ST_export(base) != EXPORT_OPTIONAL) &&
00472        (ST_sclass(base) != SCLASS_FORMAL_REF) &&
00473        (ST_sclass(base) != SCLASS_EXTERN) &&
00474        !ST_is_weak_symbol(base)) {
00475       r |= LDA_CANNOT_BE_ZERO;
00476    }
00477    
00478    if (ST_export(base) == EXPORT_PREEMPTIBLE || 
00479        ST_sclass(base) == SCLASS_EXTERN ||
00480        ST_sclass(base) == SCLASS_COMMON || 
00481        ST_sclass(base) == SCLASS_MODULE ||
00482        ST_is_weak_symbol(base)) {
00483       r |= LDA_EQUIV_POSSIBLE;
00484    }
00485 
00486    return (r);
00487 }
00488 
00489 typedef enum {
00490    NO,YES,MAYBE
00491 } YESNOMAYBE;
00492 
00493 
00494 static YESNOMAYBE LDA_Equal_Address (simpnode lda_x,simpnode lda_y) 
00495 {
00496    const ST *x;
00497    const ST *y;
00498    LDA_FLAGS fx,fy;
00499    INT64 x_offset,y_offset;
00500    ST_IDX x_base_sym_idx,y_base_sym_idx;
00501    
00502    fx = get_lda_info(lda_x, x_offset, x_base_sym_idx);
00503    fy = get_lda_info(lda_y, y_offset, y_base_sym_idx);
00504    
00505    if (((fx|fy)&LDA_UNTESTABLE)!=0) return MAYBE;
00506    if (x_base_sym_idx == y_base_sym_idx) {
00507       if (x_offset == y_offset) return YES;
00508       return NO;
00509    }
00510    // If the offsets differ, it's really not safe to say anything
00511    if (x_offset != y_offset) return MAYBE;
00512       
00513    x = ST_ptr(x_base_sym_idx);
00514    y = ST_ptr(y_base_sym_idx);
00515    
00516    // find out if x is weak or may become weak after symbol resolution
00517    // likewise for y.
00518    BOOL x_maybe_weak = (ST_is_weak_symbol (x) ||
00519                         (ST_sclass (x) == SCLASS_EXTERN && 
00520                          ST_export (x) == EXPORT_PREEMPTIBLE));
00521    BOOL y_maybe_weak = (ST_is_weak_symbol (y) ||
00522                         (ST_sclass (y) == SCLASS_EXTERN && 
00523                          ST_export (y) == EXPORT_PREEMPTIBLE));
00524    
00525    // check if x and y maybe aliased:
00526    // the first condition checks if x points to y
00527    // the second condition checks if y points to x
00528    // the third condition checks, after symbol resolution, if x and y
00529    // points to each other, of if they both point to the same variable z
00530    BOOL maybe_aliased = 
00531       (ST_is_weak_symbol (x) && ST_strong_idx (*x) == ST_st_idx (y)) ||
00532       (ST_is_weak_symbol (y) && ST_strong_idx (*y) == ST_st_idx (x)) ||
00533       (ST_export (x) == EXPORT_OPTIONAL) ||
00534       (ST_export (y) == EXPORT_OPTIONAL) ||
00535       (x_maybe_weak && y_maybe_weak);
00536    
00537    if (!maybe_aliased) return NO;
00538    else return MAYBE;
00539 }
00540 
00541 
00542 /* ====================================================================
00543  *
00544  * INT32 SIMPNODE_Simp_Compare_Trees(simpnode t1, simpnode t2)
00545  *
00546  * Compares two WHIRL trees. This routine returns 0 if the trees are the
00547  * same. Otherwise it imposes a somewhat arbitrary, but consistent ordering.
00548  * If t1 is "less than" t2, this routine returns -1, otherwise it returns 1.
00549  *
00550  * The order is computed as follows:
00551  * 1) If the root opcodes are different, the numerical value of the opcode
00552  *    determines the order.
00553  * 2) Compare children. The result will be the result of the first non-zero
00554  *    comparison. 
00555  * 3) Special cases:
00556  *    a) INTCONST compares the signed value of SIMP_Int_ConstVal.
00557  *    b) ILOAD, ILOADX, LDA, MLOAD compare the offset first.
00558  *    c) IDNAME and LDID compare offsets and then symbol table entries
00559  *    d) CONST compares symbol table entries
00560  *    e) ARRAY compares num_dim, element_size and the children
00561  *    f) CVTL compares cvtl_bits first.
00562  * ====================================================================
00563  */
00564 
00565 INT32 SIMPNODE_Simp_Compare_Trees(simpnode t1, simpnode t2)
00566 {
00567    INT32  i;
00568    INT32  rv;
00569    
00570    /* Trivial comparison, shouldn't ever happen for WHIRL nodes, but
00571     * will happen for the WOPT IR.
00572     */
00573    if (t1 == t2) return (0);
00574 
00575    /* First compare opcodes */
00576    if (SIMPNODE_opcode(t1) < SIMPNODE_opcode(t2))
00577      return (-1);
00578    else if (SIMPNODE_opcode(t1) > SIMPNODE_opcode(t2))
00579      return (1);
00580    
00581    /* Opcodes are the same, switch on operator class */
00582    switch (SIMPNODE_operator(t1)) {
00583     case OPR_INTCONST:
00584       if (SIMPNODE_const_val(t1) < SIMPNODE_const_val(t2)) return(-1);
00585       if (SIMPNODE_const_val(t1) > SIMPNODE_const_val(t2)) return(1);
00586       return (0);
00587 
00588     case OPR_CVTL:
00589       if (SIMPNODE_cvtl_bits(t1) < SIMPNODE_cvtl_bits(t2)) return (-1);
00590       if (SIMPNODE_cvtl_bits(t1) > SIMPNODE_cvtl_bits(t2)) return (1);
00591       return (SIMPNODE_Simp_Compare_Trees(SIMPNODE_kid0(t1),
00592                                           SIMPNODE_kid0(t2)));
00593       
00594 
00595     case OPR_EXTRACT_BITS:
00596       if (SIMPNODE_op_bit_offset(t1) < SIMPNODE_op_bit_offset(t2)) return (-1);
00597       if (SIMPNODE_op_bit_offset(t1) > SIMPNODE_op_bit_offset(t2)) return (1);
00598       if (SIMPNODE_op_bit_size(t1) < SIMPNODE_op_bit_size(t2)) return (-1);
00599       if (SIMPNODE_op_bit_size(t1) > SIMPNODE_op_bit_size(t2)) return (1);
00600       return (SIMPNODE_Simp_Compare_Trees(SIMPNODE_kid0(t1),
00601                                           SIMPNODE_kid0(t2)));
00602 
00603 
00604     case OPR_COMPOSE_BITS:
00605       if (SIMPNODE_op_bit_offset(t1) < SIMPNODE_op_bit_offset(t2)) return (-1);
00606       if (SIMPNODE_op_bit_offset(t1) > SIMPNODE_op_bit_offset(t2)) return (1);
00607       if (SIMPNODE_op_bit_size(t1) < SIMPNODE_op_bit_size(t2)) return (-1);
00608       if (SIMPNODE_op_bit_size(t1) > SIMPNODE_op_bit_size(t2)) return (1);
00609       rv = SIMPNODE_Simp_Compare_Trees(SIMPNODE_kid0(t1), SIMPNODE_kid0(t2));
00610       if (rv == 0) {
00611         rv = SIMPNODE_Simp_Compare_Trees(SIMPNODE_kid1(t1), SIMPNODE_kid1(t2));
00612       }
00613       return rv;
00614 
00615 
00616     case OPR_CONST:
00617       return SIMPNODE_Compare_Symbols(t1,t2);
00618       
00619     case OPR_ILOAD:
00620       if (SIMPNODE_load_offset(t1) < SIMPNODE_load_offset(t2)) return(-1);
00621       if (SIMPNODE_load_offset(t1) > SIMPNODE_load_offset(t2)) return(1);
00622       if (SIMPNODE_desc(t1) == MTYPE_BS || SIMPNODE_desc(t2) == MTYPE_BS) {
00623         if (SIMPNODE_i_field_id(t1) < SIMPNODE_i_field_id(t2)) return(-1);
00624         if (SIMPNODE_i_field_id(t1) > SIMPNODE_i_field_id(t2)) return(1);
00625       }
00626       return (SIMPNODE_Simp_Compare_Trees(SIMPNODE_kid0(t1),
00627                                           SIMPNODE_kid0(t2)));
00628 
00629     case OPR_ILDBITS:
00630       if (SIMPNODE_load_offset(t1) < SIMPNODE_load_offset(t2)) return(-1);
00631       if (SIMPNODE_load_offset(t1) > SIMPNODE_load_offset(t2)) return(1);
00632       if (SIMPNODE_i_bit_offset(t1) < SIMPNODE_i_bit_offset(t2)) return(-1);
00633       if (SIMPNODE_i_bit_offset(t1) > SIMPNODE_i_bit_offset(t2)) return(1);
00634       return (SIMPNODE_Simp_Compare_Trees(SIMPNODE_kid0(t1),
00635                                           SIMPNODE_kid0(t2)));
00636 
00637     case OPR_MLOAD:  /* Same procedure as ILOADX, though the children */
00638     case OPR_ILOADX:  /* have very different meanings */    
00639       if (SIMPNODE_load_offset(t1) < SIMPNODE_load_offset(t2)) return(-1);
00640       if (SIMPNODE_load_offset(t1) > SIMPNODE_load_offset(t2)) return(1);
00641       rv = SIMPNODE_Simp_Compare_Trees(SIMPNODE_kid0(t1),SIMPNODE_kid0(t2));
00642       if (rv != 0) return (rv);
00643       return (SIMPNODE_Simp_Compare_Trees(SIMPNODE_kid1(t1),
00644                                           SIMPNODE_kid1(t2)));
00645 
00646     case OPR_LDID:
00647       if (SIMPNODE_load_offset(t1) < SIMPNODE_load_offset(t2)) return(-1);
00648       if (SIMPNODE_load_offset(t1) > SIMPNODE_load_offset(t2)) return(1);
00649       if (SIMPNODE_desc(t1) == MTYPE_BS || SIMPNODE_desc(t2) == MTYPE_BS) {
00650         if (SIMPNODE_field_id(t1) < SIMPNODE_field_id(t2)) return(-1);
00651         if (SIMPNODE_field_id(t1) > SIMPNODE_field_id(t2)) return(1);
00652       }
00653       return SIMPNODE_Compare_Symbols(t1,t2);
00654 
00655     case OPR_LDBITS:
00656       if (SIMPNODE_load_offset(t1) < SIMPNODE_load_offset(t2)) return(-1);
00657       if (SIMPNODE_load_offset(t1) > SIMPNODE_load_offset(t2)) return(1);
00658       if (SIMPNODE_bit_offset(t1) < SIMPNODE_bit_offset(t2)) return(-1);
00659       if (SIMPNODE_bit_offset(t1) > SIMPNODE_bit_offset(t2)) return(1);
00660       return SIMPNODE_Compare_Symbols(t1,t2);
00661       
00662     case OPR_IDNAME:
00663       if (SIMPNODE_idname_offset(t1) < SIMPNODE_idname_offset(t2)) return(-1);
00664       if (SIMPNODE_idname_offset(t1) > SIMPNODE_idname_offset(t2)) return(1);
00665       return SIMPNODE_Compare_Symbols(t1,t2);
00666 
00667     case OPR_LDA:
00668       if (SIMPNODE_lda_offset(t1) < SIMPNODE_lda_offset(t2)) return(-1);
00669       if (SIMPNODE_lda_offset(t1) > SIMPNODE_lda_offset(t2)) return(1);
00670       return SIMPNODE_Compare_Symbols(t1,t2);
00671 
00672     case OPR_ARRAY:
00673       if (SIMPNODE_num_dim(t1) < SIMPNODE_num_dim(t2)) return (-1);
00674       if (SIMPNODE_num_dim(t1) > SIMPNODE_num_dim(t2)) return (1);
00675       if (SIMPNODE_element_size(t1) < SIMPNODE_element_size(t2)) return (-1);
00676       if (SIMPNODE_element_size(t1) > SIMPNODE_element_size(t2)) return (1);
00677       /* Compare bases */
00678       rv = SIMPNODE_Simp_Compare_Trees(SIMPNODE_array_base(t1),
00679                                        SIMPNODE_array_base(t2));
00680       if (rv != 0) return (rv);
00681       
00682       /* Compare array_index and array_dim */
00683       for (i=0; i < SIMPNODE_num_dim(t1); i++) {
00684          rv = SIMPNODE_Simp_Compare_Trees(SIMPNODE_array_index(t1,i),
00685                                           SIMPNODE_array_index(t2,i));
00686          if (rv != 0) return (rv);
00687          rv = SIMPNODE_Simp_Compare_Trees(SIMPNODE_array_dim(t1,i),
00688                                           SIMPNODE_array_dim(t2,i));
00689          if (rv != 0) return (rv);
00690       }
00691       /* everything compares */
00692       return (0);
00693 
00694     case OPR_INTRINSIC_OP:
00695       if (SIMPNODE_intrinsic(t1) < SIMPNODE_intrinsic(t2)) return (-1);
00696       if (SIMPNODE_intrinsic(t1) > SIMPNODE_intrinsic(t2)) return (1);
00697       if (SIMPNODE_kid_count(t1) < SIMPNODE_kid_count(t2)) return (-1);
00698       if (SIMPNODE_kid_count(t1) > SIMPNODE_kid_count(t2)) return (1);
00699       
00700       for (i=0; i<SIMPNODE_kid_count(t1); i++) {
00701         rv = SIMPNODE_Simp_Compare_Trees(SIMPNODE_kid(t1,i),
00702                                          SIMPNODE_kid(t2,i));
00703         if (rv != 0) return (rv);
00704       }
00705       return (0);
00706 
00707     case OPR_COMMA:
00708     case OPR_RCOMMA:
00709     case OPR_CSELECT:
00710 
00711       return ((INTPS)t1 - (INTPS)t2);
00712 
00713     default:
00714        if (OPCODE_is_expression(SIMPNODE_opcode(t1))) {
00715           for (i=0; i<SIMPNODE_kid_count(t1); i++) {
00716              rv = SIMPNODE_Simp_Compare_Trees(SIMPNODE_kid(t1,i),
00717                                               SIMPNODE_kid(t2,i));
00718              if (rv != 0) return (rv);
00719           }
00720           return (0);
00721        } else {
00722           /* Non-expression opcode. Return arbitrary */
00723           return ((INTPS)t1 - (INTPS)t2);
00724        }
00725    }
00726 }
00727 
00728 
00729 
00730 /* ====================================================================
00731  *
00732  * static OPCODE is_logop(OPCODE opc)
00733  *
00734  * If opc is an operator logop (LIOR, LAND) return it. If it's a relop,
00735  * return the inverse. If it's not one of these, return OPCODE_UNKNOWN.
00736  * ====================================================================
00737  */
00738 
00739 static OPCODE is_logop(OPCODE opc)
00740 {
00741    OPERATOR op;
00742    
00743    op = OPCODE_operator(opc);
00744    if (op == OPR_LAND || op == OPR_LIOR) return (opc);
00745    return OPCODE_UNKNOWN;
00746 }
00747 
00748 
00749 /* ====================================================================
00750  *
00751  * static BOOL is_ok_to_reassociate(OPCODE opc)
00752  *
00753  * If opc is an operator which can be reassociated under the current set 
00754  * of compile time flags, return TRUE. The current operators which
00755  * can be reassociated are 
00756  * &, &&, |, ||, ^, MAX, MIN under all circumstances, all types
00757  * +, * for floating point types if roundoff is 2 or greater
00758  * +, * for all integer types.
00759  * ====================================================================
00760  */
00761 
00762 static BOOL is_ok_to_reassociate(OPCODE opc)
00763 {
00764    switch (OPCODE_operator(opc)) {
00765     case OPR_MAX:
00766     case OPR_MIN:
00767     case OPR_BAND:
00768     case OPR_BIOR:
00769     case OPR_BXOR:
00770     case OPR_LAND:
00771     case OPR_LIOR:
00772       return (TRUE);
00773 
00774     case OPR_ADD:
00775     case OPR_MPY:
00776       if (SIMP_IS_TYPE_INTEGRAL(OPCODE_rtype(opc))) {
00777          return (TRUE);
00778 #ifdef __FP_REASSOCIATE__
00779       } else if (SIMP_IS_TYPE_FLOATING(OPCODE_rtype(opc))) {
00780          return (Enable_Cfold_Reassociate);
00781 #endif
00782       } else {
00783          /* Don't know what to do */
00784          return (FALSE);
00785       }
00786       
00787     default:
00788       return (FALSE);
00789    }
00790 }
00791 
00792 
00793 /* ====================================================================
00794  *
00795  * OPCODE get_inverse_relop( OPCODE opc )
00796  *
00797  * For a relational operator, return the inverse operator. Return 0
00798  * for non-relational operators.
00799  *
00800  * ====================================================================
00801  */
00802 
00803 static OPCODE get_inverse_relop( OPCODE opc )
00804 {
00805    OPCODE iopc;
00806    OPERATOR iopr;
00807 
00808    switch (OPCODE_operator(opc)) {
00809    case OPR_LT: iopr = OPR_GE; break;
00810    case OPR_LE: iopr = OPR_GT; break;
00811    case OPR_GT: iopr = OPR_LE; break;
00812    case OPR_GE: iopr = OPR_LT; break;
00813    case OPR_EQ: iopr = OPR_NE; break;
00814    case OPR_NE: iopr = OPR_EQ; break;
00815    default: return OPCODE_UNKNOWN;
00816    }
00817 
00818    iopc = OPCODE_make_op(iopr, OPCODE_rtype(opc), OPCODE_desc(opc));
00819    return iopc;
00820 }
00821 
00822 /*
00823  * This routine returns the "real" type of an operand. The "real" type
00824  * differs from the WHIRL type for loads of the short types.
00825  */
00826 
00827 static TYPE_ID get_value_type(simpnode k0)
00828 {
00829    TYPE_ID ty;
00830    OPERATOR op;
00831    op = SIMPNODE_operator(k0);
00832    if (op == OPR_ILOAD || op == OPR_LDID || op == OPR_LDBITS) {
00833       ty = OPCODE_desc(SIMPNODE_opcode(k0));
00834    } else {
00835       ty = SIMPNODE_rtype(k0);
00836    }
00837    return (ty);
00838 }
00839 
00840 /*
00841  * This utility routine returns NULL if the trees are not comparable, 
00842  * otherwise it returns an INTCONST representing the difference of the two trees
00843  */
00844 static simpnode simp_diff_value(simpnode k0, simpnode k1, BOOL negate_result)
00845 {
00846    INT64 resultval;
00847    simpnode r;
00848    TYPE_ID ty;
00849    
00850    r = NULL;
00851    /* Special case for difference of two LDA's */
00852    if (SIMPNODE_operator(k0) == OPR_LDA &&
00853        SIMPNODE_operator(k1) == OPR_LDA &&
00854        SIMPNODE_Compare_Symbols(k0,k1) == 0) {
00855       resultval = SIMPNODE_lda_offset(k0) - SIMPNODE_lda_offset(k1);
00856       if (negate_result) resultval = -resultval;
00857       if (SIMPNODE_rtype(k0) == MTYPE_U4) {
00858          r = SIMP_INTCONST(MTYPE_I4,resultval);
00859       } else {
00860          r = SIMP_INTCONST(MTYPE_I8,resultval);
00861       }
00862    } else if (SIMPNODE_Simp_Compare_Trees(k0,k1) == 0) {
00863       ty = SIMPNODE_rtype(k0);
00864       if (SIMP_IS_TYPE_FLOATING(ty)) {
00865          r = SIMP_FLOATCONST(ty,0.0);
00866       } else {
00867          r = SIMP_INTCONST(ty,0);
00868       }
00869    }
00870    return (r);
00871 }
00872 
00873 #define FACTOR_11 1
00874 #define FACTOR_12 2
00875 #define FACTOR_21 4
00876 #define FACTOR_22 8
00877 #define FACTOR_ALL (FACTOR_11 | FACTOR_12 | FACTOR_21 | FACTOR_22)
00878 #define FACTOR_OK(flag,type) ((flag&type)!=0)
00879 
00880 /*
00881  * Factor flag is a flag which tells the simp_factor routine which operands to 
00882  * check for equivalence. For example, FACTOR_12 says that it is OK to factor 
00883  * something like (i op j) op (k op i).
00884  */
00885 
00886 static simpnode simp_factor (simpnode k0, simpnode k1, OPERATOR op1,
00887                              OPCODE opc2, TYPE_ID ty, INT32 flag)
00888      /*
00889         This routine handles the generalized factor transformation
00890         (i op1 j) op2 (i op2 k) -> i op1 (j op2 k).
00891         
00892         k0, k1 - The two operands
00893         op1 - the multiply-like operator
00894         opc2 - the add-like opcode (to save having to create it for the types
00895         ty - the type of the result
00896         
00897         returns either a simplified tree or NULL
00898         
00899         */
00900 {
00901    simpnode r = NULL;
00902    OPCODE opc1;
00903    
00904    if (!Enable_Cfold_Aggressive ||
00905        (!Enable_Cfold_Reassociate && SIMP_IS_TYPE_FLOATING(ty)))  return (r);
00906    opc1 = OPC_FROM_OPR(op1,ty);
00907    if (SIMPNODE_opcode(k0) == opc1 && 
00908        SIMPNODE_opcode(k1) == opc1) {
00909       
00910       /* Compare the trees, and factor */
00911       if (FACTOR_OK(flag,FACTOR_11) &&
00912           SIMPNODE_Simp_Compare_Trees(SIMPNODE_kid0(k0),SIMPNODE_kid0(k1))==0) {
00913          SHOW_RULE("z*x op z*y");
00914          r = SIMPNODE_SimpCreateExp2(opc1,SIMPNODE_kid0(k0),
00915                                      SIMPNODE_SimpCreateExp2(opc2,SIMPNODE_kid1(k0),
00916                                                              SIMPNODE_kid1(k1)));
00917          SIMP_DELETE_TREE(SIMPNODE_kid0(k1)); 
00918          SIMP_DELETE(k0);
00919          SIMP_DELETE(k1);
00920          
00921       } else if (FACTOR_OK(flag,FACTOR_22) &&
00922                  SIMPNODE_Simp_Compare_Trees(SIMPNODE_kid1(k0),SIMPNODE_kid1(k1))==0) {
00923          SHOW_RULE("x*z op y*z");
00924          r = SIMPNODE_SimpCreateExp2(opc1, SIMPNODE_SimpCreateExp2(opc2,SIMPNODE_kid0(k0),
00925                                                                    SIMPNODE_kid0(k1)),
00926                                      SIMPNODE_kid1(k0));
00927          SIMP_DELETE_TREE(SIMPNODE_kid1(k1)); 
00928          SIMP_DELETE(k0);
00929          SIMP_DELETE(k1);
00930          
00931       } else if (FACTOR_OK(flag,FACTOR_21) &&
00932                  SIMPNODE_Simp_Compare_Trees(SIMPNODE_kid1(k0),SIMPNODE_kid0(k1))==0) {
00933          SHOW_RULE("x*z op z*y");
00934          r = SIMPNODE_SimpCreateExp2(opc1,SIMPNODE_kid1(k0),
00935                                      SIMPNODE_SimpCreateExp2(opc2,SIMPNODE_kid0(k0),
00936                                                              SIMPNODE_kid1(k1)));
00937          SIMP_DELETE_TREE(SIMPNODE_kid0(k1)); 
00938          SIMP_DELETE(k0);
00939          SIMP_DELETE(k1);
00940       } else if (FACTOR_OK(flag,FACTOR_12) &&
00941                  SIMPNODE_Simp_Compare_Trees(SIMPNODE_kid0(k0),SIMPNODE_kid1(k1))==0) {
00942          SHOW_RULE("z*x op y*z");
00943          r = SIMPNODE_SimpCreateExp2(opc1,SIMPNODE_kid0(k0),
00944                                      SIMPNODE_SimpCreateExp2(opc2,SIMPNODE_kid1(k0),
00945                                                              SIMPNODE_kid0(k1)));
00946          SIMP_DELETE_TREE(SIMPNODE_kid1(k1)); 
00947          SIMP_DELETE(k0);
00948          SIMP_DELETE(k1);
00949       }
00950    }
00951    return (r);
00952 
00953 }
00954 
00955 
00956 /* Make the identity operator for an operator/type pair */
00957 static simpnode make_identity(OPERATOR opr,TYPE_ID ty)
00958 {
00959    simpnode r = NULL;
00960    switch (opr) {
00961     case OPR_ADD:
00962     case OPR_SUB:
00963     case OPR_BIOR:
00964     case OPR_BXOR:
00965     case OPR_LIOR:
00966       if (SIMP_IS_TYPE_FLOATING(ty)) {
00967          r = SIMP_FLOATCONST(ty,0.0);
00968       } else {
00969          r = SIMP_INTCONST(ty,0);
00970       }
00971       break;
00972 
00973     case OPR_MPY:
00974     case OPR_LAND:
00975       if (SIMP_IS_TYPE_FLOATING(ty)) {
00976          r = SIMP_FLOATCONST(ty,1.0);
00977       } else {
00978          r = SIMP_INTCONST(ty,1);
00979       }
00980       break;
00981     case OPR_BAND:
00982       r = SIMP_INTCONST(ty,-1);
00983       break;
00984     default:
00985       FmtAssert(FALSE,
00986                 ("unknown identity value requested in simplifier"));
00987       /*NOTREACHED*/
00988    }
00989    return (r);
00990 }
00991 
00992 static simpnode simp_factor_idty (simpnode k0, simpnode k1, OPERATOR op1,
00993                              OPCODE opc2, TYPE_ID ty, INT32 const_only)
00994      /*
00995         This routine handles the generalized factor transformation
00996         (i op1 j) op2 i -> i op1 (j op2 k).
00997         
00998         k0, k1 - The two operands
00999         op1 - the multiply-like operator
01000         opc2 - the add-like opcode (to save having to create it for the types
01001         ty - the type of the result
01002         const_only - indicates factor only if the non-common term is a constant
01003         
01004         returns either a simplified tree or NULL
01005         
01006         */
01007 {
01008    simpnode r = NULL;
01009    OPCODE opc1;
01010 
01011    if (!Enable_Cfold_Aggressive ||
01012        (!Enable_Cfold_Reassociate && SIMP_IS_TYPE_FLOATING(ty)))  return (r);
01013 
01014    opc1 = OPC_FROM_OPR(op1,ty);
01015    if (SIMPNODE_opcode(k0) == opc1) {
01016       /* Compare the trees, and factor */
01017       if (SIMPNODE_Simp_Compare_Trees(SIMPNODE_kid0(k0),k1)==0) {
01018          if (!const_only || SIMP_Is_Constant(SIMPNODE_kid1(k0))) {
01019             SHOW_RULE("z*x op z");
01020             r = SIMPNODE_SimpCreateExp2(opc1,SIMPNODE_kid0(k0),
01021                                         SIMPNODE_SimpCreateExp2(opc2,SIMPNODE_kid1(k0),
01022                                                                 make_identity(op1,ty)));
01023             SIMP_DELETE(k0);
01024             SIMP_DELETE_TREE(k1);
01025          }
01026       } else if (SIMPNODE_Simp_Compare_Trees(SIMPNODE_kid1(k0),k1)==0) {
01027          if (!const_only || SIMP_Is_Constant(SIMPNODE_kid0(k0))) {
01028             SHOW_RULE("x*z op z");
01029             r = SIMPNODE_SimpCreateExp2(opc1, SIMPNODE_SimpCreateExp2(opc2,SIMPNODE_kid0(k0),
01030                                                                       make_identity(op1,ty)),
01031                                         SIMPNODE_kid1(k0));
01032             SIMP_DELETE(k0);
01033             SIMP_DELETE_TREE(k1);
01034          }
01035       }
01036    } else if (SIMPNODE_opcode(k1) == opc1) {
01037       if (SIMPNODE_Simp_Compare_Trees(k0,SIMPNODE_kid0(k1))==0) {
01038          if (!const_only || SIMP_Is_Constant(SIMPNODE_kid1(k1))) {
01039             SHOW_RULE("z op z*y");
01040             r = SIMPNODE_SimpCreateExp2(opc1,SIMPNODE_kid0(k1),
01041                                         SIMPNODE_SimpCreateExp2(opc2,make_identity(op1,ty),
01042                                                                 SIMPNODE_kid1(k1)));
01043             
01044             SIMP_DELETE_TREE(k0);
01045             SIMP_DELETE(k1);
01046          }
01047       } else if (SIMPNODE_Simp_Compare_Trees(k0,SIMPNODE_kid1(k1))==0) {
01048          if (!const_only || SIMP_Is_Constant(SIMPNODE_kid0(k1))) {
01049             SHOW_RULE("z op y*z");
01050             r = SIMPNODE_SimpCreateExp2(opc1,SIMPNODE_SimpCreateExp2(opc2,make_identity(op1,ty),
01051                                                                      SIMPNODE_kid0(k1)),
01052                                         SIMPNODE_kid1(k1));
01053             SIMP_DELETE_TREE(k0);
01054             SIMP_DELETE(k1);
01055          }
01056       }
01057    }
01058    return (r);
01059 }
01060 
01061 
01062 /**************************************************************************/
01063 /**************************************************************************/
01064 /**************************************************************************/
01065 /*
01066  *  Here follow all the simplification routines for unary operations
01067  *  These are all of the form 
01068  *
01069  *  static simpnode  simp_thing( OPCODE opc, simpnode k0)
01070  *        opc - the opcode of the node we wish to build/simplify
01071  *        k0 - the child of the operation
01072  * The return value is either a simplified WHIRL node or NULL if no simplification
01073  * was done.
01074  */
01075 /**************************************************************************/
01076 /**************************************************************************/
01077 /**************************************************************************/
01078 
01079 /*------------------------------------------------ 
01080    Simplifications for ABS:
01081    ABS(ABS(x))     ABS(X)
01082    ABS(-x)         ABS(x)
01083    ABS(CVT)        CVT(ABS) 
01084 -------------------------------------------------*/
01085 
01086 /* opc, k1, k0const, k1const not used, compiler parses next comment */
01087 /* ARGSUSED */
01088 static simpnode  simp_abs(OPCODE opc, simpnode k0, simpnode k1,
01089                           BOOL k0const, BOOL k1const)
01090 {
01091    simpnode r = NULL;
01092    OPERATOR opr;
01093    TYPE_ID  sty,dty;
01094    OPCODE   cvt_op,abs_op;
01095 
01096    opr = SIMPNODE_operator(k0);
01097    if (opr == OPR_ABS) {
01098       SHOW_RULE("ABS(ABS(x)) -> ABS(X)");
01099       r = k0;
01100    } else if (opr == OPR_NEG) {
01101       SHOW_RULE("ABS(-x) -> ABS(x)");     
01102       r = SIMPNODE_SimpCreateExp1(opc,SIMPNODE_kid0(k0));
01103       SIMP_DELETE(k0);
01104    } else if (opr == OPR_CVT) {
01105       cvt_op = SIMPNODE_opcode(k0);
01106       sty = OPCODE_desc(cvt_op);
01107       dty = OPCODE_rtype(cvt_op);
01108       if (dty == OPCODE_rtype(opc) && 
01109           SIMP_IS_TYPE_FLOATING(sty) && !SIMP_IS_TYPE_COMPLEX(sty)) {
01110          SHOW_RULE("ABS(CVT) -> CVT(ABS)");
01111          abs_op = OPC_FROM_OPR(OPR_ABS,sty);
01112          r = SIMPNODE_SimpCreateExp1(abs_op,SIMPNODE_kid0(k0));
01113          r = SIMPNODE_SimpCreateExp1(cvt_op,r);
01114          SIMP_DELETE(k0);
01115       }
01116    }
01117 
01118    return (r);
01119 }
01120 
01121 
01122 /*------------------------------------------------ 
01123    Simplifications for ~ and !:
01124    
01125    ! ! j                        j
01126    ~ ~ j                        j
01127    ! <comp>                     inverse comp, IEEE_comparisons false for floating point
01128    ~(a | b)                     a nor b
01129    ~(a nor b)                   a or b
01130 
01131 -------------------------------------------------*/
01132 /* k1, k0const, k1const not used, compiler parses next comment */
01133 /* ARGSUSED */
01134 static simpnode  simp_not(OPCODE opc, simpnode k0, simpnode k1,
01135                           BOOL k0const, BOOL k1const)
01136 {
01137    simpnode r = NULL;
01138    OPCODE  inverse_relop;
01139    
01140    if (opc == SIMPNODE_opcode(k0)) {
01141       SHOW_RULE("~ ~ j -> j");
01142       r = SIMPNODE_kid0(k0);
01143       SIMP_DELETE(k0);
01144    } else if (SIMPNODE_operator(k0) == OPR_BIOR && OPCODE_operator(opc) == OPR_BNOT &&
01145               ARCH_generate_nor) {
01146       SHOW_RULE("~(a | b) -> a nor b");
01147       r = SIMPNODE_SimpCreateExp2(OPC_FROM_OPR(OPR_BNOR,OPCODE_rtype(opc)),
01148                                   SIMPNODE_kid0(k0),SIMPNODE_kid1(k0));
01149       SIMP_DELETE(k0);
01150    } else if (SIMPNODE_operator(k0) == OPR_BNOR && OPCODE_operator(opc) == OPR_BNOT) {
01151       SHOW_RULE("~(a nor b) -> a | b");
01152       r = SIMPNODE_SimpCreateExp2(OPC_FROM_OPR(OPR_BIOR,OPCODE_rtype(opc)),
01153                                   SIMPNODE_kid0(k0),SIMPNODE_kid1(k0));
01154       SIMP_DELETE(k0);
01155    } else {
01156       inverse_relop = get_inverse_relop(SIMPNODE_opcode(k0));
01157 // >> WHIRL 0.30: replaced OPC_LNOT by OPC_BLNOT or OPC_I4LNOT
01158 // TODO WHIRL 0.30: get rid of OPC_I4LNOT
01159       if ((opc == OPC_I4LNOT || opc == OPC_BLNOT) && inverse_relop != 0 &&
01160 // << WHIRL 0.30: replaced OPC_LNOT by OPC_BLNOT or OPC_I4LNOT
01161           (! (Force_IEEE_Comparisons && 
01162               SIMP_IS_TYPE_FLOATING(OPCODE_desc(inverse_relop)))))
01163         {
01164            SHOW_RULE("! <relop>");
01165            inverse_relop = OPCODE_make_op(OPCODE_operator(inverse_relop),
01166                                           OPCODE_rtype(opc),
01167                                           OPCODE_desc(inverse_relop));
01168            r = SIMPNODE_SimpCreateExp2(inverse_relop,SIMPNODE_kid0(k0),SIMPNODE_kid1(k0));
01169            SIMP_DELETE(k0);
01170         }
01171    }
01172 
01173    return (r);
01174 }
01175 
01176 
01177 /*------------------------------------------------ 
01178    Simplifications for unary - :
01179 
01180    -(-x)                        x
01181    -(x-y)                       y-x
01182    -(x*c1)                      x*-c
01183    -(x/c1)                      x/-c
01184    -(c1/x)                      -c/x
01185 -------------------------------------------------*/
01186 /* k1, k0const, k1const not used, compiler parses next comment */
01187 /* ARGSUSED */
01188 static simpnode  simp_neg(OPCODE opc, simpnode k0, simpnode k1,
01189                           BOOL k0const, BOOL k1const)
01190 {
01191    simpnode r = NULL;
01192    TYPE_ID ty;
01193    
01194    ty = SIMPNODE_rtype(k0);
01195    
01196    if (opc == SIMPNODE_opcode(k0)) {
01197       SHOW_RULE("-(-x)");
01198       r = SIMPNODE_kid0(k0);
01199       SIMP_DELETE(k0);
01200 
01201    } else if (SIMPNODE_operator(k0) == OPR_SUB) {
01202       SHOW_RULE("-(x-y)");
01203       r = SIMPNODE_SimpCreateExp2(SIMPNODE_opcode(k0),SIMPNODE_kid1(k0),
01204                                   SIMPNODE_kid0(k0));
01205       SIMP_DELETE(k0);
01206    } else if (((SIMPNODE_operator(k0) == OPR_MPY) || (SIMPNODE_operator(k0) == OPR_DIV)) &&
01207               SIMP_Is_Constant(SIMPNODE_kid1(k0)) && !SIMP_IS_TYPE_UNSIGNED(ty)) {
01208       SHOW_RULE(" - x*/c");
01209       ty = SIMPNODE_rtype(SIMPNODE_kid1(k0));
01210       r = SIMPNODE_SimpCreateExp1(OPC_FROM_OPR(OPR_NEG,ty),SIMPNODE_kid1(k0));
01211       r = SIMPNODE_SimpCreateExp2(SIMPNODE_opcode(k0),SIMPNODE_kid0(k0),r);
01212       SIMP_DELETE(k0);
01213    } else if (SIMPNODE_operator(k0) == OPR_DIV &&
01214               SIMP_Is_Constant(SIMPNODE_kid0(k0)) && !SIMP_IS_TYPE_UNSIGNED(ty)) {
01215       SHOW_RULE(" - c/x");
01216       ty = SIMPNODE_rtype(SIMPNODE_kid0(k0));
01217       r = SIMPNODE_SimpCreateExp1(OPC_FROM_OPR(OPR_NEG,ty),SIMPNODE_kid0(k0));
01218       r = SIMPNODE_SimpCreateExp2(SIMPNODE_opcode(k0),r,SIMPNODE_kid1(k0));
01219       SIMP_DELETE(k0);
01220    }
01221                                   
01222    
01223    return (r);
01224 }
01225 
01226 /*------------------------------------------------ 
01227    Simplifications for sqrt, recip and rsqrt:
01228 
01229    SQRT(RECIP(x))     RSQRT(x)   
01230    RECIP(SQRT(x))     RSQRT(x)   
01231    RECIP(RECIP(x))    x          Roundoff:ROUNDOFF_SIMPLE needed
01232    RECIP(RSQRT(x))    SQRT(x)
01233    RSQRT(RECIP(x))    SQRT(x)
01234 
01235 All of these require Rsqrt_Allowed to generate RSQRT,
01236 
01237 -------------------------------------------------*/
01238 /* k1, k0const, k1const not used, compiler parses next comment */
01239 /* ARGSUSED */
01240 static simpnode  simp_recip(OPCODE opc, simpnode k0, simpnode k1,
01241                           BOOL k0const, BOOL k1const)
01242 {
01243    simpnode r = NULL;
01244    OPERATOR op,child_op;
01245    TYPE_ID ty;
01246    
01247    op = OPCODE_operator(opc);
01248    child_op = SIMPNODE_operator(k0);
01249    ty = OPCODE_rtype(opc);
01250 
01251    if (op == OPR_RECIP) {
01252       switch (child_op) {
01253        case OPR_RECIP:
01254          SHOW_RULE("RECIP(RECIP(X))");
01255          if (Roundoff_Level >= ROUNDOFF_SIMPLE) {
01256             r = SIMPNODE_kid0(k0);
01257             SIMP_DELETE(k0);
01258          }
01259          break;
01260 
01261        case OPR_SQRT:
01262          SHOW_RULE(" RECIP(SQRT(x))     RSQRT(x) ");
01263          if (Rsqrt_Allowed) {
01264             r = SIMPNODE_SimpCreateExp1(OPC_FROM_OPR(OPR_RSQRT,ty),SIMPNODE_kid0(k0));
01265             SIMP_DELETE(k0);
01266          }
01267          break;
01268 
01269        case OPR_RSQRT:
01270          SHOW_RULE(" RECIP(RSQRT(x))    SQRT(x) ");
01271          r = SIMPNODE_SimpCreateExp1(OPC_FROM_OPR(OPR_SQRT,ty),SIMPNODE_kid0(k0));
01272          SIMP_DELETE(k0);
01273          break;
01274 
01275        default:
01276          break;
01277       }
01278    } else if (op == OPR_SQRT && child_op == OPR_RECIP && 
01279               Rsqrt_Allowed) {
01280       SHOW_RULE(" SQRT(RECIP(x))     RSQRT(x)   ");
01281       r = SIMPNODE_SimpCreateExp1(OPC_FROM_OPR(OPR_RSQRT,ty),SIMPNODE_kid0(k0));
01282       SIMP_DELETE(k0);
01283    } else if (op == OPR_RSQRT && child_op == OPR_RECIP) {
01284       SHOW_RULE(" RSQRT(RECIP(x))    SQRT(x) ");
01285       r = SIMPNODE_SimpCreateExp1(OPC_FROM_OPR(OPR_SQRT,ty),SIMPNODE_kid0(k0));
01286       SIMP_DELETE(k0);
01287    }
01288 
01289    return (r);
01290 }
01291 
01292 
01293 /*------------------------------------------------ 
01294    Simplifications for conversions:
01295 
01296    REALPART (COMPLEX(a,b)) a
01297    IMAGPART (COMPLEX(a,b)) b
01298    t1CVT(t2CVT(a))      x, if x is of type t1 and t2 is a more precise type than t1.
01299    t1CVT(t2CVT(x))      t1CVT(x) if t2CVT(x) can represent all possible values of x
01300    t1TRUNC(t2CVT(x))    t1TRUNC or t1CVT(x) if t2CVT(x) can represent all possible values of x
01301    
01302    t1TAS(a)    a if type of A is t1
01303 
01304 -------------------------------------------------*/
01305 
01306 
01307 /* Helper routine for precise conversions. Returns TRUE if the conversion
01308  *  from type1 to type 2 will preserve all values of type1.
01309  */
01310 
01311 /* Define a bunch of bit constants. Note that if the definitions of any of the
01312  *  MTYPES results in a constant > 32, this might not work. Each bit constant
01313  *  is the list of types this type can be converted into without loss of information
01314  */
01315 #define B(t) (1<<t)
01316 #define PRECISE_I1 B(MTYPE_F4)|B(MTYPE_F8)|B(MTYPE_FQ)|B(MTYPE_I1)|B(MTYPE_I2)|B(MTYPE_I4)|B(MTYPE_I8)
01317 #define PRECISE_I2 B(MTYPE_F4)|B(MTYPE_F8)|B(MTYPE_FQ)|B(MTYPE_I2)|B(MTYPE_I4)|B(MTYPE_I8)
01318 #define PRECISE_I4 B(MTYPE_F8)|B(MTYPE_FQ)|B(MTYPE_I4)|B(MTYPE_I8)
01319 #define PRECISE_I8 B(MTYPE_FQ)|B(MTYPE_I8)
01320 #define PRECISE_U1 B(MTYPE_F4)|B(MTYPE_F8)|B(MTYPE_FQ)|B(MTYPE_U1)|B(MTYPE_U2)|B(MTYPE_U4)|B(MTYPE_U8)
01321 #define PRECISE_U2 B(MTYPE_F4)|B(MTYPE_F8)|B(MTYPE_FQ)|B(MTYPE_U2)|B(MTYPE_U4)|B(MTYPE_U8)
01322 #define PRECISE_U4 B(MTYPE_F8)|B(MTYPE_FQ)|B(MTYPE_I8)
01323 #define PRECISE_U8 B(MTYPE_FQ)
01324 #define PRECISE_F4 B(MTYPE_F4)|B(MTYPE_F8)|B(MTYPE_FQ)
01325 #define PRECISE_F8 B(MTYPE_F8)|B(MTYPE_FQ)
01326 #define PRECISE_FQ B(MTYPE_FQ)
01327 #define TESTABLE_TYPE (B(MTYPE_U1)|B(MTYPE_U2)|B(MTYPE_U4)|B(MTYPE_U8)|\
01328                        B(MTYPE_I1)|B(MTYPE_I2)|B(MTYPE_I4)|B(MTYPE_I8)|\
01329                        B(MTYPE_F4)|B(MTYPE_F8)|B(MTYPE_FQ))
01330 #define TYPEISIN(t,b) ( ((1<<(t)) & (b)) !=0)
01331 
01332 static BOOL convert_precise(TYPE_ID t1, TYPE_ID t2)
01333 {
01334    BOOL r = FALSE;
01335    INT32 precise_bits;
01336 
01337    if (TYPEISIN(t1,TESTABLE_TYPE) && TYPEISIN(t2,TESTABLE_TYPE)) {
01338       switch (t1) {
01339        case MTYPE_U1:
01340          precise_bits = PRECISE_U1;
01341          break;
01342        case MTYPE_U2:
01343          precise_bits = PRECISE_U2;
01344          break;
01345        case MTYPE_U4:
01346          precise_bits = PRECISE_U4;
01347          break;
01348        case MTYPE_U8:
01349          precise_bits = PRECISE_U8;
01350          break;
01351        case MTYPE_I1:
01352          precise_bits = PRECISE_I1;
01353          break;
01354        case MTYPE_I2:
01355          precise_bits = PRECISE_I2;
01356          break;
01357        case MTYPE_I4:
01358          precise_bits = PRECISE_I4;
01359          break;
01360        case MTYPE_I8:
01361          precise_bits = PRECISE_I8;
01362          break;
01363        case MTYPE_F4:
01364          precise_bits = PRECISE_F4;
01365          break;
01366        case MTYPE_F8:
01367          precise_bits = PRECISE_F8;
01368          break;
01369        case MTYPE_FQ:
01370          precise_bits = PRECISE_FQ;
01371          break;
01372        default:
01373          precise_bits = 0;
01374          break;
01375       }
01376       r = TYPEISIN(t2,precise_bits);
01377    }
01378    return (r);
01379 }
01380 
01381 
01382 /* k1, k0const, k1const not used, the compiler parses the next comment */
01383 /* ARGSUSED */
01384 static simpnode  simp_cvt(OPCODE opc, simpnode k0, simpnode k1,
01385                           BOOL k0const, BOOL k1const)
01386 {
01387    simpnode r = NULL;
01388    simpnode k0k0;
01389    OPCODE   k0opc,newopc;
01390    OPERATOR op, k0op;
01391    TYPE_ID source_type, dest_type, inter_type,source_value_type;
01392 
01393    op = OPCODE_operator(opc);
01394    k0opc = SIMPNODE_opcode(k0);
01395    k0op = OPCODE_operator(k0opc);
01396 
01397    if (OPCODE_desc(k0opc) == MTYPE_BS)
01398      return (NULL);
01399 
01400 #ifdef WN_SIMP_WORKING_ON_WHIRL
01401    /* Several converts are nops and can be removed right away */
01402    if (!WHIRL_Keep_Cvt_On) {
01403       if (opc == OPC_I8I4CVT || opc == OPC_U8I4CVT) {
01404          SHOW_RULE("Removed CVT");
01405          return (k0);
01406       }
01407    }
01408 
01409    /* Fix up converts of loads which just change the size of the loaded object */
01410    /* Note: this is only done for WHIRL simplification */ 
01411    if (op == OPR_CVT &&
01412        (k0op == OPR_LDID || k0op == OPR_ILOAD) &&
01413        !WN_Is_Volatile_Mem(k0)) {
01414       source_type = OPCODE_desc(k0opc);
01415       inter_type = OPCODE_rtype(k0opc);
01416       dest_type = OPCODE_rtype(opc);
01417       if (OPCODE_rtype(k0opc) == OPCODE_desc(opc) &&
01418           (SIMP_IS_TYPE_UNSIGNED(source_type))==(SIMP_IS_TYPE_UNSIGNED(dest_type))) {
01419          /* Replace the LDID or ILOAD opcode with one which does the conversion directly */
01420          /* For example, U8U4CVT(U4U1ILOAD) becomes U8U1ILOAD */
01421          if (Is_Valid_Opcode_Parts(k0op,dest_type,source_type)) {
01422             newopc = OPCODE_make_op(k0op,dest_type,source_type);
01423          } else {
01424             newopc = OPCODE_UNKNOWN;
01425          }
01426          if (k0op == OPR_LDID && ST_class(WN_st(k0))==CLASS_PREG) {
01427             newopc = OPCODE_UNKNOWN; /* Suppress for PREGs */
01428          }
01429 
01430          if (newopc != OPCODE_UNKNOWN) {
01431             SHOW_RULE("CVT(LOAD)");
01432             WN_set_opcode(k0,newopc);
01433             return (k0);
01434          }
01435       }
01436    }
01437 #endif   
01438 
01439 #ifndef EMULATE_LONGLONG
01440 
01441    /* A couple of additional extraneous convert conditions */
01442    if (opc == OPC_U4I8CVT || opc == OPC_U4U8CVT) {
01443       if ((k0op == OPR_BAND && SIMP_Is_Constant(SIMPNODE_kid1(k0))
01444            && (UINT64) SIMP_Int_ConstVal(SIMPNODE_kid1(k0)) <= 0x7fffffff) ||
01445           (k0op == OPR_LSHR && SIMP_Is_Constant(SIMPNODE_kid1(k0))
01446            && SIMP_Int_ConstVal(SIMPNODE_kid1(k0)) >= 33)) {
01447          SHOW_RULE("Removed U4I8/U4U8CVT");
01448          return (k0);
01449       }
01450    } else if (opc == OPC_I4I8CVT || opc == OPC_I4U8CVT) {
01451       if ((k0op == OPR_ASHR && SIMP_Is_Constant(SIMPNODE_kid1(k0))
01452           && SIMP_Int_ConstVal(SIMPNODE_kid1(k0)) >= 32) ||
01453           (k0op == OPR_BAND && SIMP_Is_Constant(SIMPNODE_kid1(k0))
01454            && (UINT64) SIMP_Int_ConstVal(SIMPNODE_kid1(k0)) <= 0x7fffffff) ||
01455           (k0op == OPR_LSHR && SIMP_Is_Constant(SIMPNODE_kid1(k0))
01456           && SIMP_Int_ConstVal(SIMPNODE_kid1(k0)) >= 33)) {
01457          SHOW_RULE("Removed I4I8/I4U8CVT");
01458          return (k0);
01459       }
01460    }
01461 
01462 #endif /* EMULATE_LONGLONG */
01463 
01464    
01465    if (op == OPR_REALPART &&
01466        k0op == OPR_COMPLEX) {
01467       SHOW_RULE(" REALPART (COMPLEX(a,b))    a ");
01468       r = SIMPNODE_kid0(k0);
01469       SIMP_DELETE_TREE(SIMPNODE_kid1(k0));
01470       SIMP_DELETE(k0);
01471       return (r);
01472       
01473    } if (op == OPR_IMAGPART &&
01474          k0op == OPR_COMPLEX) {
01475       SHOW_RULE(" IMAGPART (COMPLEX(a,b)) b ");
01476       r = SIMPNODE_kid1(k0);
01477       SIMP_DELETE_TREE(SIMPNODE_kid0(k0));
01478       SIMP_DELETE(k0);
01479       return (r);
01480    }
01481    
01482    if (op == OPR_CVT &&
01483        k0op == OPR_CVT) {
01484       source_type = OPCODE_desc(k0opc);
01485       inter_type = OPCODE_rtype(k0opc);
01486       dest_type = OPCODE_rtype(opc);
01487       k0k0 = SIMPNODE_kid0(k0);
01488       source_value_type = get_value_type(k0k0);
01489       
01490       if (convert_precise(source_value_type,inter_type)) {
01491          if (Is_Valid_Opcode_Parts(OPR_CVT,dest_type,source_type)) {
01492             newopc = OPCODE_make_op(OPR_CVT,dest_type,source_type);
01493          } else {
01494             newopc = OPCODE_UNKNOWN;
01495          }
01496          if (newopc != OPCODE_UNKNOWN) {
01497             SHOW_RULE("t1CVT(t2CVT(a)) -> t1CVT(a)");
01498             r = SIMPNODE_SimpCreateExp1(newopc,k0k0);
01499             SIMP_DELETE(k0);
01500          } else if (source_type == dest_type) {
01501             SHOW_RULE("t1CVT(t2CVT(a)) -> a");
01502             r = k0k0;
01503             SIMP_DELETE(k0);
01504          }
01505       }
01506    }
01507    
01508    if (op == OPR_TRUNC &&
01509        k0op == OPR_CVT) {
01510       source_type = OPCODE_desc(k0opc);
01511       inter_type = OPCODE_rtype(k0opc);
01512       dest_type = OPCODE_rtype(opc);
01513       k0k0 = SIMPNODE_kid0(k0);
01514       source_value_type = get_value_type(k0k0);
01515       if (convert_precise(source_value_type,inter_type)) {
01516          if (Is_Valid_Opcode_Parts(OPR_TRUNC,dest_type,source_type)) {
01517             newopc = OPCODE_make_op(OPR_TRUNC,dest_type,source_type);
01518          } else {
01519             newopc = OPCODE_UNKNOWN;
01520          }
01521          if (newopc != OPCODE_UNKNOWN) {
01522             SHOW_RULE("t1TRUNC(t2CVT(a)) -> t1TRUNC(a)");
01523             r = SIMPNODE_SimpCreateExp1(newopc,k0k0);
01524             SIMP_DELETE(k0);
01525          } else if (source_type == dest_type) {
01526             SHOW_RULE("t1TRUNC(t2CVT(a)) -> a");
01527             r = k0k0;
01528             SIMP_DELETE(k0);
01529          } else {
01530             if (Is_Valid_Opcode_Parts(OPR_CVT,dest_type,source_type)) {
01531                newopc = OPCODE_make_op(OPR_CVT,dest_type,source_type);
01532                SHOW_RULE("t1TRUNC(t2CVT(a)) -> t1CVT(a)");
01533                r = SIMPNODE_SimpCreateExp1(newopc,k0k0);
01534                SIMP_DELETE(k0);
01535             }
01536          }
01537       }
01538    }
01539    
01540    
01541    if (op == OPR_TAS && 
01542        OPCODE_rtype(opc) == OPCODE_rtype(k0opc)) {
01543       r = k0;
01544       return (r);
01545    }
01546 
01547 
01548    return (r);
01549 }
01550 
01551 
01552 
01553 /**************************************************************************/
01554 /**************************************************************************/
01555 /**************************************************************************/
01556 /*
01557  *  Here follow all the simplification routines for binary operations
01558  *  These are all of the form 
01559  *
01560  *  static simpnode  simp_thing( OPCODE opc, simpnode k0, simpnode k1,
01561  *                          BOOL k0const, BOOL k1const)
01562  *        opc - the opcode of the node we wish to build/simplify
01563  *        k0,k1 - the children of the operation
01564  *        k0const, k1const - true if the appropriate child is a constant
01565  * The return value is either a simplified WHIRL node or NULL if no simplification
01566  * was done.
01567  */
01568 /**************************************************************************/
01569 /**************************************************************************/
01570 /**************************************************************************/
01571 
01572 
01573 
01574 
01575 /*------------------------------------------------ 
01576    Simplifications for +, -
01577 
01578 x +- 0                  x
01579 0 - x                   -x
01580 -x + y                  y - x
01581 x - (-y)                x + y
01582 x + (-y)                x - y
01583 -x - y                  -(x+y)
01584 x - c                   x + (-c)
01585 
01586 Aggressive:
01587 x - x                   0   R:2 for floating point (so that Inf-Inf=0 is acceptable)
01588 
01589 The following are done for floating-point only if reassociation is on:
01590 
01591 (x+c1) - c2             x + (c1 - c2)           R:2 for floating types (comments on the 2?)
01592 (x-c) + y               (x+y) +- c              R:2 for floating types (comments on the 2?)
01593 (x-c1) +- c2            x + (-c1 +- c2)         R:2 for floating types (comments on the 2?)
01594 (c1-x) +- c2            (c1 +- c2) - x          R:2 for floating types (comments on the 2?)
01595 (x+-c) - y              (x-y) +- c              R:2 for floating types (comments on the 2?)
01596 (c-x) + y               (y-x) + c               R:2 for floating types (comments on the 2?)
01597 (c-x) - y               c - (x+y)               R:2 for floating types (comments on the 2?)
01598 
01599 x + (y - x)             y                       R:2 for floating types (comments on the 2?)
01600 x - (x + y)             -y                      R:2 for floating types (comments on the 2?)
01601 x - (y + x)             -y                      R:2 for floating types (comments on the 2?)
01602 x - (x - y)             y                       R:2 for floating types (comments on the 2?)
01603 also all 4 op cases of the form 
01604 (x op y) op (w op z) are check for constant fols and cancellation.
01605 
01606 
01607 z*x + z*(y - x)         y*z                     R:2 for floating types (comments on the 2?)
01608 z*x - z*(x + y)         -y*z                    R:2 for floating types (comments on the 2?)
01609 z*x - z*(y + x)         -y*z                    R:2 for floating types (comments on the 2?)
01610 z*x - z*(x - y)         y*z                     R:2 for floating types (comments on the 2?)
01611 
01612 
01613 -------------------------------------------------*/
01614 
01615 /* Pick the subop if x is true */
01616 #define SELECT_ADD_SUB(x) ((x)? subop : addop)
01617 
01618 static simpnode  simp_add_sub(OPCODE opc,
01619                          simpnode k0, simpnode k1, BOOL k0const, BOOL k1const)
01620 {
01621    simpnode r = NULL;
01622    BOOL reassoc, issub;
01623    TYPE_ID  ty;
01624    OPCODE  subop,addop,negop;
01625    simpnode x[4], t, dt;
01626    BOOL s[4], bt, constant_moved;
01627    INT32 num_const,num_ops,i,j,k,ic1,ic2,d1,d2;
01628 
01629    ty = OPCODE_rtype(opc);
01630    issub = (OPCODE_operator(opc) == OPR_SUB);
01631    if (issub) {
01632       subop = opc;
01633       addop = OPC_FROM_OPR(OPR_ADD,ty);
01634    } else {
01635       addop = opc;
01636       subop = OPC_FROM_OPR(OPR_SUB,ty);
01637    }
01638    negop = OPC_FROM_OPR(OPR_NEG,ty);
01639 
01640    /* Decide if we can reassasociate */ 
01641    reassoc = FALSE;
01642    if (SIMP_IS_TYPE_INTEGRAL(ty)) {
01643       reassoc = TRUE;
01644    } else if (SIMP_IS_TYPE_FLOATING(ty)) {
01645       reassoc = Enable_Cfold_Reassociate;
01646    }
01647 
01648    /* Try the simple ones first */
01649    /* eraxxon: a constant can be either OPR_INTCONST or OPR_CONST
01650       (cf. SIMP_Is_Constant()).  We must check for INTCONST before
01651       trying to extract its value! */
01652    if (k1const && SIMP_Is_Int_Constant(k1) &&
01653        (SIMP_IS_TYPE_INTEGRAL(ty) && SIMP_Int_ConstVal(k1)==0) ||
01654        (SIMP_IS_TYPE_FLOATING(ty) && is_floating_equal(k1,0.0))) {
01655       SHOW_RULE(" x +- 0 ");
01656       r = k0;
01657       SIMP_DELETE(k1);
01658       return (r);
01659    }
01660    if (k1const && issub && !SIMP_IS_TYPE_UNSIGNED(ty)) {
01661       SHOW_RULE("x - c => x + -c");
01662       r = SIMPNODE_SimpCreateExp2(addop,k0,SIMPNODE_ConstantFold1(negop,k1));
01663       return (r);
01664    }
01665 
01666    /* eraxxon: Test for INTCONST (see above) */
01667    if (k0const && issub && SIMP_Is_Int_Constant(k0) &&
01668        (SIMP_IS_TYPE_INTEGRAL(ty) && SIMP_Int_ConstVal(k0)==0) ||
01669        (SIMP_IS_TYPE_FLOATING(ty) && is_floating_equal(k0,0.0))) {
01670       SHOW_RULE(" 0 - x ");
01671       r = SIMPNODE_SimpCreateExp1(negop,k1);
01672       SIMP_DELETE(k0);
01673       return (r);
01674    }                        
01675    
01676    if (issub) {
01677       if (SIMPNODE_operator(k1)==OPR_NEG) {
01678          SHOW_RULE(" x - (-y) ");
01679          r = SIMPNODE_SimpCreateExp2(addop,k0,SIMPNODE_kid0(k1));
01680          SIMP_DELETE(k1);
01681       } else if (SIMPNODE_operator(k0)==OPR_NEG) {
01682          if (k1const && !SIMP_IS_TYPE_UNSIGNED(ty)) {
01683             SHOW_RULE("-x - c -> (-c)-x");
01684             r = SIMPNODE_ConstantFold1(negop,k1);
01685             r = SIMPNODE_SimpCreateExp2(subop,r,SIMPNODE_kid0(k0));
01686             SIMP_DELETE(k0);
01687          } else {
01688             SHOW_RULE(" -x - y ");
01689             r = SIMPNODE_SimpCreateExp1(negop,
01690                               SIMPNODE_SimpCreateExp2(addop,SIMPNODE_kid0(k0),k1));
01691             SIMP_DELETE(k0);
01692          }
01693       }
01694    } else {
01695       if (SIMPNODE_operator(k0)==OPR_NEG) {
01696          SHOW_RULE(" -x + y ");
01697          r = SIMPNODE_SimpCreateExp2(subop,k1,SIMPNODE_kid0(k0));
01698          SIMP_DELETE(k0);
01699       } else if (SIMPNODE_operator(k1)==OPR_NEG) {
01700          SHOW_RULE(" x + (-y) ");
01701          r = SIMPNODE_SimpCreateExp2(subop,k0,SIMPNODE_kid0(k1));
01702          SIMP_DELETE(k1);
01703       }
01704    }
01705    if (r) return (r);
01706 
01707    /* This must be done after the previous opts */
01708    if (Enable_Cfold_Aggressive && reassoc) {
01709       if (issub && (r=simp_diff_value(k0,k1,FALSE))) {
01710          SHOW_RULE("x-x");
01711          SIMP_DELETE_TREE(k0);
01712          SIMP_DELETE_TREE(k1);
01713          return (r);
01714       }
01715    }
01716 
01717    /* General reassociation */
01718    /* 4 op case:
01719     *  op is always the main op.
01720     *  (x0 op1 x1) op (x2 op3 x3)
01721     *
01722     * 3 op cases:
01723     *  (x0 op1 x1) op x2
01724     *  x0 op (x1 op2 x1)
01725     *
01726     * The prior simplifications guarantee no unary minuses to complicate things 
01727     */
01728    num_const = 0;
01729    num_ops = 0;
01730    if((SIMPNODE_operator(k0)==OPR_ADD || SIMPNODE_operator(k0)==OPR_SUB) &&
01731       (SIMPNODE_operator(k1)==OPR_ADD || SIMPNODE_operator(k1)==OPR_SUB)) {
01732       /* x[0] to x[3] represent the ops */
01733       /* s[0] to s[3] represent the sign of the 4 ops (TRUE is negative) */
01734       
01735       x[0] = SIMPNODE_kid0(k0);
01736       x[1] = SIMPNODE_kid1(k0);
01737       x[2] = SIMPNODE_kid0(k1);
01738       x[3] = SIMPNODE_kid1(k1);
01739 
01740       s[0] = FALSE;
01741       s[1] = (SIMPNODE_operator(k0) == OPR_SUB);
01742       s[2] = FALSE;
01743       s[3] = (SIMPNODE_operator(k1) == OPR_SUB);
01744       if (issub) {
01745          s[2] = !s[2];
01746          s[3] = !s[3];
01747       }
01748       num_ops = 4;
01749 
01750    } else if ((SIMPNODE_operator(k0)==OPR_ADD || SIMPNODE_operator(k0)==OPR_SUB) &&
01751               !(SIMPNODE_operator(k1)==OPR_ADD || SIMPNODE_operator(k1)==OPR_SUB)) {
01752       x[0] = SIMPNODE_kid0(k0);
01753       x[1] = SIMPNODE_kid1(k0);
01754       x[2] = k1;
01755       
01756       s[0] = FALSE;
01757       s[1] = (SIMPNODE_operator(k0) == OPR_SUB);
01758       s[2] = issub;
01759       num_ops = 3;
01760 
01761    } else if (!(SIMPNODE_operator(k0)==OPR_ADD || SIMPNODE_operator(k0)==OPR_SUB) &&
01762               (SIMPNODE_operator(k1)==OPR_ADD || SIMPNODE_operator(k1)==OPR_SUB)) {
01763       x[0] = k0;
01764       x[1] = SIMPNODE_kid0(k1);
01765       x[2] = SIMPNODE_kid1(k1);
01766       
01767       s[0] = FALSE;
01768       s[1] = FALSE;
01769       s[2] = (SIMPNODE_operator(k1) == OPR_SUB);
01770       if (issub) {
01771          s[1] = !s[1];
01772          s[2] = !s[2];
01773       }
01774       num_ops = 3;
01775       /* Need to guard against the case of c - x - y where neither x nor y is
01776        * constant.  This interacts with other things in the simplifier to 
01777        * produce an infinite loop.
01778        */
01779       if (SIMP_Is_Constant(x[0]) && !SIMP_Is_Constant(x[1]) && !SIMP_Is_Constant(x[2]) &&
01780           s[1] && s[2]) {
01781          num_ops = 0;
01782       }
01783    }
01784    
01785    /* Guard against reassociating when we shouldn't */
01786    if (!reassoc) num_ops = 0;
01787    
01788    /* check that all types are the same size */
01789    for (k=0; k < num_ops; k++) {
01790       if (MTYPE_size_reg(SIMPNODE_rtype(x[k])) != MTYPE_size_reg(ty)) {
01791          /* disable the rest of the reassociation */
01792          num_ops = 0;
01793       }
01794    }
01795    
01796    if (num_ops != 0) {
01797       /* There is some potential reassociation to be done */
01798             
01799       /* Step 1, collect all the constants to the right */
01800       constant_moved = FALSE;
01801       for (i=0, j=num_ops-1; i <= j; ) {
01802          if (SIMP_Is_Constant(x[i])) {
01803             /* Move the constant to the jth position,
01804                shift down the rest (to preserve order),
01805                decrement j */
01806             if (i != j) {
01807                bt = s[i];
01808                t = x[i];
01809                for (k=i; k<j; k++) {
01810                   s[k] = s[k+1];
01811                   x[k] = x[k+1];
01812                }
01813                s[j] = bt;
01814                x[j] = t;
01815                constant_moved = TRUE;
01816             }
01817             --j;
01818             ++num_const;
01819             continue;
01820          } else {
01821             ++i;
01822             continue;
01823          }
01824       }
01825          
01826       /* numconst can now be 0, 1 or 2. If it's 3 or 4 
01827          we had a foul up earlier, but simplify now anyway */
01828       if (num_const == 4) {
01829          SHOW_RULE("Questionable 4 const add fold");
01830          /* This can only happen if the simplifier is called on unsimplified trees.
01831           * Do the folding now
01832           */
01833          if (s[0]) {
01834             r = SIMPNODE_ConstantFold1(negop,x[0]); 
01835          } else {
01836             r = x[0];
01837          }
01838          for (i = 1; i <= 3; i++) {
01839             if (s[i]) {
01840                r = SIMPNODE_ConstantFold2(subop,r,x[i]);
01841             } else {
01842                r = SIMPNODE_ConstantFold2(addop,r,x[i]);
01843             }
01844          }
01845          return (r);
01846       } else  if (num_const == 3) {
01847          SHOW_RULE("Questionable 3 const add fold");
01848          /* This can only happen if the simplifier is called on unsimplified trees.
01849           * Do the folding now
01850           */
01851          ic1 = num_ops-3;
01852          ic2 = num_ops-1;
01853          if (s[ic1]) {
01854             r = SIMPNODE_ConstantFold1(negop,x[ic1]); 
01855          } else {
01856             r = x[ic1];
01857          }
01858          for (i = ic1+1; i <= ic2; i++) {
01859             if (s[i]) {
01860                r = SIMPNODE_ConstantFold2(subop,r,x[i]);
01861             } else {
01862                r = SIMPNODE_ConstantFold2(addop,r,x[i]);
01863             }
01864          }
01865          if (ic1 == 0) return (r); /* 3 ops, all constant */
01866          if (s[0]) {
01867             r = SIMPNODE_SimpCreateExp2(subop,r,x[0]);
01868          } else {
01869             r = SIMPNODE_SimpCreateExp2(addop,x[0],r);
01870          }
01871          return (r);
01872       } else  if (num_const==2) {
01873          /* Fold the constants */
01874          ic1 = num_ops-2;
01875          ic2 = num_ops-1;
01876          /* Take care of the first op */
01877          if (s[ic1]) x[ic1] = SIMPNODE_ConstantFold1(negop,x[ic1]);
01878          /* Now fold the two together */
01879          if (s[ic2]) {
01880             x[ic1] = SIMPNODE_ConstantFold2(subop,x[ic1],x[ic2]);
01881          } else {
01882             x[ic1] = SIMPNODE_ConstantFold2(addop,x[ic1],x[ic2]);
01883          }
01884          s[ic1] = FALSE;
01885          --num_ops;
01886          num_const = 1;
01887       }
01888 
01889       switch (num_ops) {
01890        case 2:
01891          if (num_const != 1) {
01892             /* nothing to do, but this shouldn't happen */
01893             SHOW_RULE("Reassociation goof?");
01894             return(r);
01895          } else {
01896             /* Add back the constant */
01897             if (s[0]) {
01898                SHOW_RULE("-x0 + c1 + c2");
01899                r = SIMPNODE_SimpCreateExp2(subop,x[1],x[0]);
01900             } else {
01901                SHOW_RULE("x0 + c1 + c2");
01902                r = SIMPNODE_SimpCreateExp2(addop,x[0],x[1]);
01903             }
01904             return (r);
01905          }
01906        case 3:
01907          /* Three remaining ops */
01908          /* either we have 
01909             s0 x1 + s1 x1 + c1   or
01910             s0 x1 + s1 x1 + s2 x2.
01911             
01912             */   
01913            
01914          if (num_const == 1 && constant_moved) {
01915             if (s[0]) {
01916                if (s[1]) {
01917                   SHOW_RULE(" -x0 - x1 + c => c - (x0 + x1) ");
01918                   r = SIMPNODE_SimpCreateExp2(addop,x[0],x[1]);
01919                   if (s[2]) {  /* This shouldn't happen, but just in case */
01920                      x[2] = SIMPNODE_SimpCreateExp1(negop,x[2]);
01921                   }
01922                   r = SIMPNODE_SimpCreateExp2(subop,x[2],r);
01923                } else {
01924                   SHOW_RULE(" -x0 + x1 + c => (x1 - x0) + c");
01925                   r = SIMPNODE_SimpCreateExp2(subop,x[1],x[0]);
01926                   r = SIMPNODE_SimpCreateExp2(SELECT_ADD_SUB(s[2]),r,x[2]);
01927                }
01928             } else {
01929                SHOW_RULE(" x0 + s1 x1 + c => (x0 + s1 x1) + c ");
01930                r = SIMPNODE_SimpCreateExp2(SELECT_ADD_SUB(s[1]),x[0],x[1]);
01931                r = SIMPNODE_SimpCreateExp2(SELECT_ADD_SUB(s[2]),r,x[2]);
01932             }
01933          } else if (Enable_Cfold_Aggressive) {
01934             /* We want to look for potential cancellations */
01935             if ((s[0] != s[1]) && (r = simp_diff_value(x[0],x[1],s[0]))) {
01936                SHOW_RULE("x - x op y");
01937                SIMP_DELETE_TREE(x[0]);
01938                SIMP_DELETE_TREE(x[1]);
01939                /* two cancel! */
01940                r = SIMPNODE_SimpCreateExp2(SELECT_ADD_SUB(s[2]),r,x[2]);
01941             } else if ((s[1] != s[2]) && (r = simp_diff_value(x[1],x[2],s[1]))) {
01942                /* two cancel! */
01943                SHOW_RULE("y op x - x");
01944                SIMP_DELETE_TREE(x[1]);
01945                SIMP_DELETE_TREE(x[2]);
01946                r = SIMPNODE_SimpCreateExp2(SELECT_ADD_SUB(s[0]),r,x[0]);
01947             } else if ((s[2] != s[0]) && (r = simp_diff_value(x[2],x[0],s[2]))) {
01948                /* two cancel! */
01949                SHOW_RULE("x op y - x");
01950                SIMP_DELETE_TREE(x[0]);
01951                SIMP_DELETE_TREE(x[2]);
01952                r = SIMPNODE_SimpCreateExp2(SELECT_ADD_SUB(s[1]),r,x[1]);
01953             } else {
01954                /* Generic 3 op case, none of which are constant (or were 
01955                   constant). Do nothing.
01956                   */
01957                r = NULL;
01958             }
01959          }
01960          return (r);
01961 
01962        case 4:
01963          if (!Enable_Cfold_Aggressive) return (r);
01964          /* Four remaining ops */
01965          /* either we have 
01966             s0 x1 + s1 x1 + s2 x2 + c3   or
01967             s0 x1 + s1 x1 + s2 x2 + s3 x3.
01968             
01969             we can't have two constants, since they will have already been folded out
01970             
01971             */   
01972 
01973          /* Search for cancellations */
01974          if (num_const==1) {
01975             i = -1;
01976             if ((s[0] != s[1]) && (dt = simp_diff_value(x[0],x[1],s[0]))) {
01977                SHOW_RULE("4 op, 1 const, cancel 0,1");
01978                i = 2;
01979                d1 = 0; d2 = 1;
01980             } else if ((s[1] != s[2]) && (dt = simp_diff_value(x[1],x[2],s[1]))) {
01981                SHOW_RULE("4 op, 1 const cancel 1,2");
01982                i = 0;
01983                d1 = 1; d2 = 2;
01984             } else if ((s[2] != s[0]) && (dt = simp_diff_value(x[2],x[0],s[2]))) {
01985                SHOW_RULE("4 op, 1 const cancel 0,2");
01986                i = 1;
01987                d1 = 0; d2 = 2;
01988             } else {
01989                /* Just give up */
01990                r = NULL;
01991             }
01992             if (i != -1) {
01993                if (s[i]) {
01994                   if (s[3]) {
01995                      r = SIMPNODE_SimpCreateExp2(addop,x[i],x[3]);
01996                      r = SIMPNODE_SimpCreateExp1(negop,r);
01997                   } else {
01998                      r = SIMPNODE_SimpCreateExp2(subop,x[3],x[i]);
01999                   }
02000                } else {
02001                   r = SIMPNODE_SimpCreateExp2(SELECT_ADD_SUB(s[3]),x[i],x[3]);
02002                }
02003                r = SIMPNODE_SimpCreateExp2(addop,r,dt);
02004                SIMP_DELETE_TREE(x[d1]);
02005                SIMP_DELETE_TREE(x[d2]);
02006             }
02007          } else {
02008             i = -1; j = -1;
02009             /* now we have 6 cases */
02010             if ((s[0] != s[1]) && (dt = simp_diff_value(x[0],x[1],s[0]))) {
02011                SHOW_RULE("4 op, cancel 0,1");
02012                i = 2; j = 3;
02013                d1 = 0; d2 = 1;
02014             } else if ((s[0] != s[2]) && (dt = simp_diff_value(x[0],x[2],s[0]))) {
02015                SHOW_RULE("4 op, cancel 0,2");
02016                i = 1; j = 3;
02017                d1 = 0; d2 = 2;
02018             } else if ((s[0] != s[3]) && (dt = simp_diff_value(x[0],x[3],s[0]))) {
02019                SHOW_RULE("4 op, cancel 0,3");
02020                i = 1; j = 2;
02021                d1 = 0; d2 = 3;
02022             } else if ((s[1] != s[2]) && (dt = simp_diff_value(x[1],x[2],s[1]))) {
02023                SHOW_RULE("4 op, cancel 1,2");
02024                i = 0; j = 3;
02025                d1 = 1; d2 = 2;
02026             } else if ((s[1] != s[3]) && (dt = simp_diff_value(x[1],x[3],s[1]))) {
02027                SHOW_RULE("4 op, cancel 1,3");
02028                i = 0; j = 2;
02029                d1 = 1; d2 = 3;
02030             } else if ((s[2] != s[3]) && (dt = simp_diff_value(x[2],x[3],s[2]))) {
02031                SHOW_RULE("4 op, cancel 2,3");
02032                i = 0; j = 1;
02033                d1 = 2; d2 = 3;
02034             }
02035             if (i == -1) {
02036                /* we found nothing useful, give up */
02037                r = NULL;
02038             } else {
02039                /* i and j point to two operands */
02040                if (s[i]) {
02041                   if (s[j]) {
02042                      r = SIMPNODE_SimpCreateExp2(addop,x[i],x[j]);
02043                      r = SIMPNODE_SimpCreateExp1(negop,r);
02044                   } else {
02045                      r = SIMPNODE_SimpCreateExp2(subop,x[j],x[i]);
02046                   }
02047                } else {
02048                   r = SIMPNODE_SimpCreateExp2(SELECT_ADD_SUB(s[j]),x[i],x[j]);
02049                }
02050                r = SIMPNODE_SimpCreateExp2(addop,r,dt);
02051                SIMP_DELETE_TREE(x[d1]);
02052                SIMP_DELETE_TREE(x[d2]);
02053             }
02054          }
02055          return (r);
02056       }   /* switch (num_ops) */
02057    }
02058    
02059    if (r) return (r);
02060    /*------------------------------------------------------*/
02061    /* Try to distribute, if possible */
02062    /* z*x op z*y           z*(x op y)              r:2 for floating types */
02063    
02064    r = simp_factor(k0,k1,OPR_MPY,opc,ty,FACTOR_ALL);
02065    if (!r) r = simp_factor_idty(k0,k1,OPR_MPY,opc,ty,TRUE);
02066 #ifdef WN_SIMP_WORKING_ON_WHIRL
02067 
02068    if (r) return (r);
02069 
02070    /* Simplify ADD(LDA[offset], CONSTANT) into LDA[offset+constant] */
02071    if (k1const && 
02072        SIMP_IS_TYPE_INTEGRAL(ty) &&
02073        SIMPNODE_operator(k0) == OPR_LDA) {
02074       INT64 offset;
02075       INT64 newoffset;
02076       INT64 k1val;
02077       offset = SIMPNODE_lda_offset(k0);
02078       k1val = SIMP_Int_ConstVal(k1);
02079       if (issub) k1val = -k1val;
02080       if (WN_Simp_Fold_LDA &&
02081           is_add_ok(&newoffset,k1val,offset,MTYPE_I4)) {
02082          SHOW_RULE("c1 + LDA");
02083          SIMPNODE_lda_offset(k0) = newoffset;
02084          r = k0;
02085          SIMP_DELETE(k1);
02086       }
02087    }
02088 
02089 #endif
02090 
02091    return (r);
02092 }
02093 
02094 
02095 /*------------------------------------------------ 
02096    Simplifications for *
02097  x * 1                  x
02098  x * 0                  0                       I:1 (because of 0*Infinity)
02099  x * -1                 -x
02100  -x * c                 x * (-c)
02101  -x * -y                simplify(x*y)
02102  -x * y                 -simplify(x*y)
02103  x * -y                 -simplify(x*y)
02104  (a +- c1)*c2           a*c2 +- c1*c2   
02105  (c1 - a)*c2            c1*c2 - c2*a    
02106  (c1 - c2*a)*c3         c1*c3 - c2*c3*a 
02107  (c2*a +- c1)*c3        c2*c3*a +- c1*c3
02108 
02109  Aggressive:
02110  a*rsqrt(a)             sqrt(a)    Round >= Roundoff_simple
02111  sqrt(a)*recip(a)       1/sqrt(a)  "
02112 
02113 -------------------------------------------------*/
02114 
02115 static simpnode  simp_times( OPCODE opc,
02116                        simpnode k0, simpnode k1, BOOL k0const, BOOL k1const)
02117 {
02118    simpnode r = NULL;
02119    INT64   c1;
02120    TYPE_ID  ty;
02121    OPERATOR first_op,second_op;
02122    simpnode  addend;
02123    
02124 
02125    /* k0const should always be false. If it isn't we messed up
02126       some canonicalizations */
02127    if (k0const) {
02128       return (r);
02129    }
02130    ty = OPCODE_rtype(opc);
02131    first_op = SIMPNODE_operator(k0);
02132    second_op = SIMPNODE_operator(k1);
02133 
02134    /* Cases involving unary - */
02135 
02136    if (first_op==OPR_NEG && second_op==OPR_NEG) {
02137       SHOW_RULE(" -x*-y ");
02138       r = SIMPNODE_SimpCreateExp2(opc,SIMPNODE_kid0(k0),SIMPNODE_kid0(k1));
02139       SIMP_DELETE(k0);
02140       SIMP_DELETE(k1);
02141       return (r);
02142    } else if (first_op==OPR_NEG && !k1const) {
02143       SHOW_RULE(" -x * y ");
02144       r = SIMPNODE_SimpCreateExp2(opc,SIMPNODE_kid0(k0),k1);
02145       r = SIMPNODE_SimpCreateExp1(OPC_FROM_OPR(OPR_NEG,ty),r);
02146       SIMP_DELETE(k0);
02147       return (r);
02148    } else if (second_op==OPR_NEG) {
02149       SHOW_RULE(" x * -y ");
02150       r = SIMPNODE_SimpCreateExp2(opc,k0,SIMPNODE_kid0(k1));
02151       r = SIMPNODE_SimpCreateExp1(OPC_FROM_OPR(OPR_NEG,ty),r);
02152       SIMP_DELETE(k1);
02153       return (r);
02154    } else if (first_op==OPR_NEG && k1const) {
02155       SHOW_RULE(" -x * c ");
02156       r = SIMPNODE_SimpCreateExp1(OPC_FROM_OPR(OPR_NEG,ty),k1);
02157       r = SIMPNODE_SimpCreateExp2(opc,SIMPNODE_kid0(k0),r);
02158       SIMP_DELETE(k0);
02159       return(r);
02160    }
02161       
02162    if (k1const) {
02163       if (SIMP_IS_TYPE_INTEGRAL(ty)) {
02164          c1 = SIMP_Int_ConstVal(k1);
02165          if (c1 == 1) {
02166             SHOW_RULE(" j * 1 ");
02167             r = k0;
02168             SIMP_DELETE(k1);
02169          } else if (c1 == -1 && !SIMP_IS_TYPE_UNSIGNED(ty)) {
02170             SHOW_RULE(" j * -1 ");
02171             r = SIMPNODE_SimpCreateExp1(OPC_FROM_OPR(OPR_NEG,ty),k0);
02172             SIMP_DELETE(k1);
02173          } else if (c1 == 0) {
02174             SHOW_RULE(" j * 0 ");
02175             r = SIMP_INTCONST(ty,0);
02176             SIMP_DELETE_TREE(k0);
02177             SIMP_DELETE(k1);
02178          }
02179       } else if (SIMP_IS_TYPE_FLOATING(ty) && !SIMP_IS_TYPE_COMPLEX(ty)) {
02180          if (is_floating_equal(k1,1.0)) {
02181             SHOW_RULE(" a * 1 ");
02182             r = k0;
02183             SIMP_DELETE(k1);
02184          } else if (is_floating_equal(k1,-1.0)) {
02185             SHOW_RULE(" a * -1 ");
02186             r = SIMPNODE_SimpCreateExp1(OPC_FROM_OPR(OPR_NEG,ty),k0);
02187             SIMP_DELETE(k1);
02188          } else if (is_floating_equal(k1,0.0)) {
02189             if (IEEE_Arithmetic >= IEEE_INEXACT) {
02190                SHOW_RULE(" j * 0 ");
02191                r = SIMP_FLOATCONST(ty,0.0);
02192                SIMP_DELETE_TREE(k0);
02193                SIMP_DELETE(k1);
02194             }
02195          }
02196       }
02197       if (r) {
02198          return (r);
02199       }
02200       
02201       if ((first_op == OPR_ADD || first_op == OPR_SUB) &&
02202           SIMPNODE_rtype(k0) == ty &&
02203           SIMPNODE_rtype(k1) == ty && 
02204           is_ok_to_reassociate(opc)) {
02205          if (SIMP_Is_Constant(SIMPNODE_kid1(k0))) {
02206             /*
02207              * Distribute multiplies by constants over the first 
02208              * child.
02209              *
02210              * (c2*a +- c1)*c3  c2*c3*a +- c1*c3
02211              * (a +- c1)*c2     a*c2 +- c1*c2   
02212              * (c1 - a)*c2              c1*c2 - c2*a    
02213              * (c1 - c2*a)*c3   c1*c3 - c2*c3*a
02214              */
02215             SHOW_RULE("(a op c1)*c2");
02216             /* Make a copy of k1 */
02217             r = SIMPNODE_CopyNode(k1);
02218             addend = SIMPNODE_SimpCreateExp2(opc,SIMPNODE_kid1(k0),k1);
02219             r = SIMPNODE_SimpCreateExp2(opc,SIMPNODE_kid0(k0),r);
02220             r = SIMPNODE_SimpCreateExp2(SIMPNODE_opcode(k0),r,addend);
02221             SIMP_DELETE(k0);
02222          } else if (SIMP_Is_Constant(SIMPNODE_kid0(k0))) {
02223             SHOW_RULE("(c1 op a )*c2");
02224             /* Make a copy of k1 */
02225             r = SIMPNODE_CopyNode(k1);
02226             addend = SIMPNODE_SimpCreateExp2(opc,SIMPNODE_kid0(k0),k1);
02227             r = SIMPNODE_SimpCreateExp2(opc,SIMPNODE_kid1(k0),r);
02228             r = SIMPNODE_SimpCreateExp2(SIMPNODE_opcode(k0),addend,r);
02229             SIMP_DELETE(k0);
02230          }
02231       }
02232    }
02233    
02234    if (r) return(r);
02235 
02236    if (Enable_Cfold_Aggressive && Roundoff_Level >= ROUNDOFF_SIMPLE) {
02237       if (first_op==OPR_SQRT && second_op==OPR_RECIP
02238           && SIMPNODE_Simp_Compare_Trees(SIMPNODE_kid0(k0),SIMPNODE_kid0(k1))==0) {
02239          SHOW_RULE("sqrt(a)*recip(a)");
02240          r = SIMPNODE_SimpCreateExp2(OPC_FROM_OPR(OPR_DIV,ty),
02241                                      SIMP_FLOATCONST(ty,1.0) ,k0);
02242          SIMP_DELETE_TREE(k1);
02243       } else if (second_op==OPR_SQRT && first_op==OPR_RECIP
02244           && SIMPNODE_Simp_Compare_Trees(SIMPNODE_kid0(k0),SIMPNODE_kid0(k1))==0) {
02245          SHOW_RULE("recip(a)*sqrt(a)");
02246          r = SIMPNODE_SimpCreateExp2(OPC_FROM_OPR(OPR_DIV,ty),SIMP_FLOATCONST(ty,1.0) ,k1);
02247          SIMP_DELETE_TREE(k0);
02248       } else if (first_op == OPR_RSQRT && SIMPNODE_Simp_Compare_Trees(k1,SIMPNODE_kid0(k0))==0) {
02249          SHOW_RULE("rsqrt(a)*a");
02250          r = SIMPNODE_SimpCreateExp1(OPC_FROM_OPR(OPR_SQRT,ty),k1);
02251          SIMP_DELETE_TREE(k0);
02252       } else if (second_op == OPR_RSQRT && SIMPNODE_Simp_Compare_Trees(k0,SIMPNODE_kid0(k1))==0) {
02253          SHOW_RULE("a*rsqrt(a)");
02254          r = SIMPNODE_SimpCreateExp1(OPC_FROM_OPR(OPR_SQRT,ty),k0);
02255          SIMP_DELETE_TREE(k1);
02256       }
02257    }
02258 
02259    return (r);
02260 }
02261 
02262 
02263 /*------------------------------------------------ 
02264    Simplifications for /
02265 
02266 -x/-y                   x/y
02267 x / 1                   x
02268 x / (-1)                -x
02269 1.0/a                   RECIP(a)
02270 -1.0/a                  -RECIP(a)
02271 j/(2**N)                j ASHR N (if J is unsigned)
02272 j/N                     TRUNC(DBLE(j)*((1.0d0/DBLE(N)*(1+2**-40)))),
02273                         if j is 32 bits. (Yes, this really works).
02274 a / c                   a * 1.0/c, if |c| is 2**k
02275 a / b                   a * RECIP(b)            R:3,I:3 (this is a very bad thing to do)
02276 
02277 Aggressive:
02278 a / sqrt(a)             sqrt(a) R:2
02279 sqrt(a) / a             1/sqrt(a) r:2 [simplifier will turn this into RSQRT if allowed]
02280 a/a                     1         
02281 
02282 -------------------------------------------------*/
02283 
02284 static simpnode  simp_div( OPCODE opc,
02285                      simpnode k0, simpnode k1, BOOL k0const, BOOL k1const)
02286 {
02287 
02288    /* TODO: DIVISION by 0 checks */
02289 
02290    simpnode r = NULL;
02291    INT64  c1;
02292    TYPE_ID ty;
02293    TCON recip,dval;
02294 
02295    ty = OPCODE_rtype(opc);
02296 
02297    if (SIMPNODE_operator(k0)==OPR_NEG && SIMPNODE_operator(k1)==OPR_NEG) {
02298       SHOW_RULE(" -x/-y ");
02299       r = SIMPNODE_SimpCreateExp2(opc,SIMPNODE_kid0(k0),SIMPNODE_kid0(k1));
02300       SIMP_DELETE(k0);
02301       SIMP_DELETE(k1);
02302       return (r);
02303    }
02304 
02305    if (k1const && SIMP_IS_TYPE_INTEGRAL(ty)) {
02306       c1 = SIMP_Int_ConstVal(k1);
02307       if (c1 == 1) {
02308          SHOW_RULE(" x / 1      ");
02309          r = k0;
02310          SIMP_DELETE(k1);
02311       } else if (c1==-1 && !SIMP_IS_TYPE_UNSIGNED(ty)) {
02312          SHOW_RULE(" x / (-1) ");
02313          r = SIMPNODE_SimpCreateExp1(OPC_FROM_OPR(OPR_NEG,ty),k0);
02314          SIMP_DELETE(k1);
02315       }
02316    } /* Integral with constant divisor */
02317    else if (k1const && SIMP_IS_TYPE_FLOATING(ty)) {
02318       /* 
02319        * x / 1                  x
02320        * x / (-1)               -x
02321        */
02322       /* bail out on division by 0 */
02323       if (is_floating_equal(k1,0.0)) {
02324          /* Division by 0 */
02325          return(r); 
02326       }
02327       if (is_floating_equal(k1,1.0)) {
02328          SHOW_RULE("x/1");
02329          r = k0;
02330          SIMP_DELETE(k1);
02331       } else if (is_floating_equal(k1,-1.0)) {
02332          SHOW_RULE("x/-1");
02333          r = SIMPNODE_SimpCreateExp1(OPC_FROM_OPR(OPR_NEG,ty),k0);
02334          SIMP_DELETE(k1);
02335       } else if (Targ_Is_Power_Of_Two(SIMP_Flt_ConstVal(k1))) {
02336          SHOW_RULE(" a / c  a * 1.0/c, if |c| is 2**k ");
02337 
02338          /* Take the reciprocal of a floating point-constant */
02339          dval = SIMP_Flt_ConstVal(k1);
02340          recip = Targ_WhirlOp (opc,
02341                                Host_To_Targ_Float (ty, 1.0 ),
02342                                dval, 0 );
02343          r = SIMPNODE_CreateFloatconstFromTcon(recip);
02344          
02345          r = SIMPNODE_SimpCreateExp2(OPC_FROM_OPR(OPR_MPY,ty),k0,r);
02346          SIMP_DELETE(k1);
02347       }
02348    }
02349    /* Bail out for simplicity */
02350    if (r) return (r);
02351    if (k0const && SIMP_IS_TYPE_FLOATING(ty) && !SIMP_IS_TYPE_COMPLEX(ty)) {
02352       /*  1.0/a                 RECIP(a)
02353        * -1.0/a                 -RECIP(a)
02354        */
02355       if ((is_floating_equal(k0,1.0) ||
02356            is_floating_equal(k0,-1.0)) && 
02357           Recip_Allowed) {
02358          SHOW_RULE("+-1.0 / a");
02359          r = SIMPNODE_SimpCreateExp1(OPC_FROM_OPR(OPR_RECIP,ty),k1);
02360          if (is_floating_equal(k0,-1.0)) {
02361             r = SIMPNODE_SimpCreateExp1(OPC_FROM_OPR(OPR_NEG,ty),r);
02362          }
02363          SIMP_DELETE(k0);
02364       }
02365    } else if (SIMP_IS_TYPE_FLOATING(ty) && !SIMP_IS_TYPE_COMPLEX(ty)
02366               && Div_Split_Allowed && Recip_Allowed) {
02367       SHOW_RULE(" a / b    a * RECIP(b)  ");
02368       r = SIMPNODE_SimpCreateExp1(OPC_FROM_OPR(OPR_RECIP,ty),k1);
02369       r = SIMPNODE_SimpCreateExp2(OPC_FROM_OPR(OPR_MPY,ty),k0,r);
02370    }
02371 
02372    if (!Enable_Cfold_Aggressive || r) return(r);
02373 
02374    if (Roundoff_Level >= ROUNDOFF_SIMPLE) {
02375       if (SIMPNODE_operator(k0)==OPR_SQRT 
02376           && SIMPNODE_Simp_Compare_Trees(SIMPNODE_kid0(k0),k1)==0) {
02377          SHOW_RULE("sqrt(a)/a");
02378          r = SIMPNODE_SimpCreateExp2(opc, SIMP_FLOATCONST(ty,1.0) ,k0);
02379          SIMP_DELETE_TREE(k1);
02380       } else if (SIMPNODE_operator(k1)==OPR_SQRT
02381                  && SIMPNODE_Simp_Compare_Trees(SIMPNODE_kid0(k1),k0)==0) {
02382          SHOW_RULE("a/sqrt(a)");
02383          r = k1;
02384          SIMP_DELETE_TREE(k0);
02385       }
02386    }
02387    
02388    if (SIMPNODE_Simp_Compare_Trees(k0,k1) == 0) {
02389       SHOW_RULE("x/x");
02390       if (SIMP_IS_TYPE_INTEGRAL(ty)) {
02391          r = SIMP_INTCONST(ty,1);
02392       } else if (SIMP_IS_TYPE_FLOATING(ty) && !Force_IEEE_Comparisons && 
02393                  IEEE_Arithmetic >= IEEE_INEXACT) {
02394          r = SIMP_FLOATCONST(ty,1.0);
02395       }
02396    }
02397 
02398    return (r);
02399 }
02400 
02401 
02402 /*------------------------------------------------ 
02403    Simplifications for MOD and REM
02404 
02405 j mod 1                 0
02406 j mod -1                0
02407 0 mod j                 0
02408 j rem 1                 0
02409 j rem -1                0
02410 0 rem j                 0
02411 j mod (2**N)            j & (2**N-1)    
02412 j mod -(2**N)           (j & (2**N-1)) - 2**N   If j is signed
02413 j rem (2**N)            j & (2**N-1)            If j is unsigned
02414 
02415 To be done:
02416 j rem (2**N)            (j & (2**N-1)) -
02417                          ((-(j.lt.0) & (2**N))) If j is signed
02418 j rem -(2**N)           (j & (2**N-1)) -
02419                          ((-(j.lt.0) & (2**N))) If j is signed
02420 
02421 -------------------------------------------------*/
02422 
02423 static simpnode  simp_mod_rem(OPCODE opc,
02424                          simpnode k0, simpnode k1, BOOL k0const, BOOL k1const)
02425 {
02426    simpnode r = NULL;
02427    INT64 c0,c1;
02428    BOOL isrem,isunsigned;
02429    TYPE_ID ty;
02430    
02431    ty = OPCODE_rtype(opc);
02432 
02433    if (k0const) {
02434       SHOW_RULE(" 0 rem or mod j ");
02435       c0 = SIMP_Int_ConstVal(k0);
02436       if (c0 == 0) {
02437          r = SIMP_INTCONST(ty,0);
02438          SIMP_DELETE(k0);
02439          SIMP_DELETE_TREE(k1);
02440       } 
02441       return(r);
02442    }
02443 
02444    /* Bail out if neither is constant */
02445    if (!(k0const || k1const)) return(r);
02446 
02447    /* at this point, we know k1 to be a constant */
02448    c1 = SIMP_Int_ConstVal(k1);
02449    isrem = (OPCODE_operator(opc) == OPR_REM);
02450    isunsigned = SIMP_IS_TYPE_UNSIGNED(ty);
02451    
02452    if (c1 == 1 || (c1 == -1 && !isunsigned)) {
02453       /* 
02454        * j mod 1                0
02455        * j mod -1               0
02456        * j rem 1                0
02457        * j rem -1               0
02458        *
02459        */
02460       SHOW_RULE("j mod/rem +-1");
02461       r = SIMP_INTCONST(ty,0);
02462       SIMP_DELETE_TREE(k0);
02463       SIMP_DELETE(k1);
02464    } else if (!isrem && IS_POWER_OF_2(c1)) {
02465       if (isunsigned || (!isunsigned && (c1 > 0))) {
02466          SHOW_RULE(" j mod (2**N)               j & (2**N-1) ");
02467          r = SIMPNODE_SimpCreateExp2(OPC_FROM_OPR(OPR_BAND,ty),k0,
02468                            SIMP_INTCONST(ty,c1-1));
02469          SIMP_DELETE(k1);
02470       }
02471    } else if (!isrem && IS_POWER_OF_2(-c1) && !isunsigned) {
02472       SHOW_RULE(" j mod -(2**N) (j & (2**N-1)) - 2**N   If j is signed      ");
02473       /* Note that this works as well for the largest negative integer */
02474       c1 = -c1;
02475       r = SIMPNODE_SimpCreateExp2(OPC_FROM_OPR(OPR_BAND,ty),k0,
02476                         SIMP_INTCONST(ty,c1-1));
02477       r = SIMPNODE_SimpCreateExp2(OPC_FROM_OPR(OPR_SUB,ty),r,
02478                         SIMP_INTCONST(ty,c1));
02479       SIMP_DELETE(k1);
02480    } else if (isrem && IS_POWER_OF_2(c1) && isunsigned) {
02481       SHOW_RULE(" j rem (2**N) ");
02482       r = SIMPNODE_SimpCreateExp2(OPC_FROM_OPR(OPR_BAND,ty),k0,
02483                         SIMP_INTCONST(ty,c1-1));
02484       SIMP_DELETE(k1);
02485    }
02486 
02487    return (r);
02488 }
02489 
02490 
02491 /*------------------------------------------------ 
02492    Simplifications for **
02493 
02494 1 ** x                  1
02495 -1 ** N                 1 - (N&1)<<1
02496 x ** 0                  1
02497 x ** 1                  x
02498 a ** 0.5                SQRT(a)
02499 a ** -0.5               1.0/SQRT(a) (RSQRT will be generated by simplifier)
02500 a ** -1.0               1.0/a       (RECIP will be generated by the simplifier)
02501 
02502 -------------------------------------------------*/
02503 
02504 static simpnode  simp_power( OPCODE opc,
02505                        simpnode k0, simpnode k1, BOOL k0const, BOOL k1const)
02506 {
02507    simpnode r = NULL;
02508    TYPE_ID ty;
02509 
02510    if (!(k0const || k1const)) return (r);
02511    ty = OPCODE_rtype(opc);
02512 
02513    if (k0const) {
02514       if (is_numeric_equal(k0,1.0)) {
02515          SHOW_RULE(" 1 ** x     1 ");
02516          if (SIMP_IS_TYPE_FLOATING(ty)) {
02517             r = SIMP_FLOATCONST(ty,1.0);
02518             SIMP_DELETE(k0);
02519             SIMP_DELETE_TREE(k1);
02520          } else if (SIMP_IS_TYPE_INTEGRAL(ty)) {
02521             r = SIMP_INTCONST(ty,1);
02522             SIMP_DELETE(k0);
02523             SIMP_DELETE_TREE(k1);
02524          }
02525       } else if (SIMP_IS_TYPE_INTEGRAL(ty) && !SIMP_IS_TYPE_UNSIGNED(ty) &&
02526                  SIMP_Int_ConstVal(k0)==-1) {
02527          SHOW_RULE(" -1 ** N    1-(N&1)<<1 ");
02528          r = SIMPNODE_SimpCreateExp2(OPC_FROM_OPR(OPR_BAND,ty),k1,
02529                            SIMP_INTCONST(ty,1));
02530          r = SIMPNODE_SimpCreateExp2(OPC_FROM_OPR(OPR_SHL,ty),r,
02531                            SIMP_INTCONST(ty,1));
02532          r = SIMPNODE_SimpCreateExp2(OPC_FROM_OPR(OPR_SUB,ty),
02533                            SIMP_INTCONST(ty,1),r);
02534          SIMP_DELETE(k0);
02535       }
02536    } else if (k1const) {
02537       if (is_numeric_equal(k1,1.0)) {
02538          SHOW_RULE(" x ** 1     x ");
02539          r = k0;
02540          SIMP_DELETE(k1);
02541       } else if (is_numeric_equal(k1,0.0)) {
02542          SHOW_RULE(" x ** 0     1 ");
02543          /*** NOTE: this means that 0**0 will not signal an exception */
02544          if (SIMP_IS_TYPE_FLOATING(ty)) {
02545             r = SIMP_FLOATCONST(ty,1.0);
02546             SIMP_DELETE_TREE(k0);
02547             SIMP_DELETE(k1);
02548          } else if (SIMP_IS_TYPE_INTEGRAL(ty)) {
02549             r = SIMP_INTCONST(ty,1);
02550             SIMP_DELETE_TREE(k0);
02551             SIMP_DELETE(k1);
02552          }
02553       } else if (SIMP_IS_TYPE_FLOATING(ty)) {
02554          if (is_floating_equal(k1,-1.0)) {
02555             SHOW_RULE(" a ** -1    1/a ");
02556             r = SIMPNODE_SimpCreateExp2(OPC_FROM_OPR(OPR_DIV,ty),
02557                               SIMP_FLOATCONST(ty,1.0),k0);
02558             SIMP_DELETE(k1);
02559          } else if (is_floating_equal(k1,0.5)) {
02560             SHOW_RULE(" a ** 0.5                SQRT(a) ");
02561             r = SIMPNODE_SimpCreateExp1(OPC_FROM_OPR(OPR_SQRT,ty),k0);
02562             SIMP_DELETE(k1);
02563          } else if (is_floating_equal(k1,-0.5)) {
02564             SHOW_RULE(" a ** -0.5       1/SQRT(a) ");
02565             r = SIMPNODE_SimpCreateExp1(OPC_FROM_OPR(OPR_SQRT,ty),k0);
02566             r = SIMPNODE_SimpCreateExp2(OPC_FROM_OPR(OPR_DIV,ty),
02567                               SIMP_FLOATCONST(ty,1.0),r);
02568             SIMP_DELETE(k1);
02569          }
02570       }
02571       
02572    }
02573    return (r);
02574 }
02575 
02576 
02577 /*------------------------------------------------ 
02578    Simplifications for MIN and MAX
02579 
02580 MAX(x,c)                x if c is smallest possible value
02581 MIN(x,c)                x if c is largest possible value
02582 MAX(x,c)                c if c is largest possible value
02583 MIN(x,c)                c if c is smallest possible value
02584 
02585 The above are currently only done for integer types 
02586 
02587 Aggressive:
02588 MAX(x,x), MIN(x,x)      x
02589 -------------------------------------------------*/
02590 
02591 /* k0const not used, compiler parses next comment */
02592 /* ARGSUSED */
02593 static simpnode  simp_min_max(OPCODE opc,
02594                          simpnode k0, simpnode k1, BOOL k0const, BOOL k1const)
02595 {
02596    simpnode r = NULL;
02597    BOOL  ismax;
02598    INT64 c1;
02599 
02600    ismax = (OPCODE_operator(opc) == OPR_MAX);
02601    if (k1const && SIMP_Is_Int_Constant(k1)) {
02602       c1 = SIMP_Int_ConstVal(k1);
02603       switch (OPCODE_rtype(opc)) {
02604        case MTYPE_I4:
02605          if ((ismax && c1==INT32_MIN) ||
02606              (!ismax && c1==INT32_MAX)) {
02607             r = k0;
02608             SIMP_DELETE(k1);
02609          } else if ((ismax && c1==INT32_MAX) ||
02610                     (!ismax && c1==INT32_MIN)){
02611             r = k1;
02612             SIMP_DELETE_TREE(k0);
02613          }
02614          break;
02615 
02616        case MTYPE_U4:
02617          if ((ismax && c1==0) ||
02618              (!ismax && c1==UINT32_MAX)) {
02619             r = k0;
02620             SIMP_DELETE(k1);
02621          } else if ((ismax && c1==UINT32_MAX) ||
02622                     (!ismax && c1==0)){
02623             r = k1;
02624             SIMP_DELETE_TREE(k0);
02625          }
02626          break;
02627 
02628        case MTYPE_I8:
02629          if ((ismax && c1==0x8000000000000000LL) ||
02630              (!ismax && c1==0x7fffffffffffffffLL)) {
02631             r = k0;
02632             SIMP_DELETE(k1);
02633          } else if ((ismax && c1==0x7fffffffffffffffLL) ||
02634                     (!ismax && c1==0x8000000000000000LL)){
02635             r = k1;
02636             SIMP_DELETE_TREE(k0);
02637          }
02638          break;
02639 
02640        case MTYPE_U8:
02641          if ((ismax && c1==0) ||
02642              (!ismax && c1==(UINT64) -1)) {
02643             r = k0;
02644             SIMP_DELETE(k1);
02645          } else if ((ismax && c1==(UINT64) -1) ||
02646                     (!ismax && c1==0)){
02647             r = k1;
02648             SIMP_DELETE_TREE(k0);
02649          }
02650          break;
02651       }
02652    }
02653 
02654    if (r) {
02655       SHOW_RULE("MIN/MAX(x, largest/smallest)");
02656       return (r);
02657    }
02658 
02659    if (!Enable_Cfold_Aggressive) return (r);
02660    if (SIMPNODE_Simp_Compare_Trees(k0,k1)==0) {
02661       SHOW_RULE(" MAX(x,x), MIN(x,x) ");
02662       r = k0;
02663       SIMP_DELETE_TREE(k1);
02664    }
02665    return (r);
02666 }
02667 
02668 
02669 /*------------------------------------------------ 
02670    Simplifications for &
02671 j & 0                   0
02672 j & -1                  j
02673 (j==0) & (k==0)         (j|k)==0
02674 ~j & ~k                 ~(j|k)                  Generates NOR
02675 <comp> & 1              <comp>
02676 (j | c1) & c2           j & c2    if (c1&c2 == 0)
02677 (j >> shift) & c1       j >> shift if mask has ones in the shift_size - shift lower bits
02678  Aggressive:
02679 ~j & j                  0
02680 j & j                   j
02681 
02682 (j >> c2) & mask        extract (if enabled)
02683 
02684 -------------------------------------------------*/
02685 
02686 static simpnode  simp_band( OPCODE opc,
02687                       simpnode k0, simpnode k1, BOOL k0const, BOOL k1const)
02688 {
02689 
02690    simpnode r = NULL;
02691    INT64   c1,mask_bits;
02692    TYPE_ID  ty;
02693 
02694    /* k0const should always be false. If it isn't we messed up
02695       some canonicalizations */
02696    if (k0const) {
02697       return (r);
02698    }
02699    ty = OPCODE_rtype(opc);
02700 
02701    if (k1const) {
02702       c1 = SIMP_Int_ConstVal(k1); 
02703       if (c1 == 0) {
02704          SHOW_RULE("j&0");
02705          r = SIMP_INTCONST(ty,0);
02706          SIMP_DELETE_TREE(k0);
02707          SIMP_DELETE(k1);
02708       } else if (c1 == -1) {
02709          SHOW_RULE("j&-1");
02710          r = k0;
02711          SIMP_DELETE(k1);
02712       } else if ((c1 == 1) && (get_inverse_relop(SIMPNODE_opcode(k0))!=0)) {
02713          SHOW_RULE("<comp> & 1");
02714          r = k0;
02715          SIMP_DELETE(k1);
02716       } else if ((SIMPNODE_operator(k0) == OPR_BIOR) && SIMP_Is_Constant(SIMPNODE_kid1(k0)) &&
02717                  ((SIMP_Int_ConstVal(SIMPNODE_kid1(k0)) & c1) == 0)) {
02718          SHOW_RULE("(j|c1) & c2, c1&c2=0");
02719          r = SIMPNODE_SimpCreateExp2(opc,SIMPNODE_kid0(k0),k1);
02720          SIMP_DELETE(SIMPNODE_kid1(k0));
02721          SIMP_DELETE(k0);
02722       } else if ((SIMPNODE_operator(k0) == OPR_LSHR) &&
02723                  SIMP_Is_Constant(SIMPNODE_kid1(k0)) &&
02724                  (MTYPE_bit_size(SIMPNODE_rtype(k0)) == MTYPE_bit_size(ty))) {
02725          INT32 shift_count = SIMP_Int_ConstVal(SIMPNODE_kid1(k0));
02726          mask_bits = create_bitmask(MTYPE_bit_size(ty) - shift_count);
02727          if ((mask_bits & c1) == mask_bits) {
02728            SHOW_RULE("(j LSHR c2) & c1)");
02729            r = k0;
02730            SIMP_DELETE(k1);
02731          } else if (Enable_extract_compose && IS_POWER_OF_2(c1+1)) {
02732            r = SIMPNODE_SimpCreateExtract(MTYPE_bit_size(ty) == 32 ? OPC_U4EXTRACT_BITS : OPC_U8EXTRACT_BITS,
02733                                           shift_count,wn_simp_code::log2(c1+1),
02734                                           SIMPNODE_kid0(k0));
02735            SIMP_DELETE(k1);
02736            SIMP_DELETE(SIMPNODE_kid1(k0));
02737          }
02738       }   
02739    } else if ((SIMPNODE_operator(k0)==OPR_BNOT) && (SIMPNODE_operator(k1)==OPR_BNOT)) {
02740       SHOW_RULE(" ~j & ~k ");
02741       r = SIMPNODE_SimpCreateExp1(OPC_FROM_OPR(OPR_BNOT,ty),
02742                         SIMPNODE_SimpCreateExp2(OPC_FROM_OPR(OPR_BIOR,ty),
02743                                       SIMPNODE_kid0(k0),SIMPNODE_kid0(k1)));
02744       SIMP_DELETE(k0);
02745       SIMP_DELETE(k1);
02746    } else if ((SIMPNODE_operator(k0)==OPR_EQ) && (SIMPNODE_operator(k1)==OPR_EQ) &&
02747               SIMP_Is_Int_Constant(SIMPNODE_kid1(k0)) &&
02748               SIMP_Is_Int_Constant(SIMPNODE_kid1(k1)) &&
02749               SIMP_Int_ConstVal(SIMPNODE_kid1(k0)) == 0 &&
02750               SIMP_Int_ConstVal(SIMPNODE_kid1(k1)) == 0 &&
02751               (SIMP_TYPE(SIMPNODE_kid0(k0)) == SIMP_TYPE(SIMPNODE_kid0(k1))) &&
02752               (ty == SIMP_TYPE(SIMPNODE_kid0(k0)))) {
02753       SHOW_RULE(" (j==0) & (k==0) ");
02754       
02755       r = SIMPNODE_SimpCreateExp2(SIMPNODE_opcode(k0),
02756                         SIMPNODE_SimpCreateExp2(OPC_FROM_OPR(OPR_BIOR,ty),
02757                                       SIMPNODE_kid0(k0), SIMPNODE_kid0(k1)),
02758                         SIMPNODE_kid1(k0));
02759       SIMP_DELETE(k0);
02760       SIMP_DELETE(SIMPNODE_kid1(k1));
02761       SIMP_DELETE(k1);
02762    }
02763 
02764    if (!Enable_Cfold_Aggressive || r) return (r);
02765 
02766    if ((SIMPNODE_operator(k0)==OPR_BNOT && SIMPNODE_Simp_Compare_Trees(SIMPNODE_kid0(k0),k1)==0) ||
02767        (SIMPNODE_operator(k1)==OPR_BNOT && SIMPNODE_Simp_Compare_Trees(SIMPNODE_kid0(k1),k0)==0)) {
02768       SHOW_RULE(" ~j & j ");
02769       r = SIMP_INTCONST(ty,0);
02770       SIMP_DELETE_TREE(k0);
02771       SIMP_DELETE_TREE(k1);
02772    } else if (SIMPNODE_Simp_Compare_Trees(k0,k1)==0) {
02773       SHOW_RULE(" j & j ");
02774       r = k0;
02775       SIMP_DELETE_TREE(k1);
02776    }
02777 
02778    if (r) return (r);
02779 
02780    r = simp_factor(k0,k1,OPR_BIOR,opc,ty,FACTOR_ALL);
02781    if (r) return (r);
02782 
02783    r = simp_factor_idty(k0,k1,OPR_BIOR,opc,ty,FALSE);
02784    if (r) return (r);
02785 
02786    /* catch the a & b & c & b type cases */
02787    r = simp_factor(k0,k1,OPR_BAND,opc,ty,FACTOR_ALL);
02788    if (r) return (r);
02789 
02790    r = simp_factor_idty(k0,k1,OPR_BAND,opc,ty,FALSE);
02791    if (r) return (r);
02792 
02793    r = simp_factor(k0,k1,OPR_SHL,opc,ty,FACTOR_22);
02794    if (r) return (r);
02795 
02796    r = simp_factor(k0,k1,OPR_ASHR,opc,ty,FACTOR_22);
02797    if (r) return (r);
02798 
02799    r = simp_factor(k0,k1,OPR_LSHR,opc,ty,FACTOR_22);
02800        
02801    return (r);
02802 }
02803 
02804 
02805 /*------------------------------------------------ 
02806    Simplifications for |
02807 j | 0                   j
02808 j | -1                  -1
02809 (j & c2) | c1           (j | c1) & (c1|c2)      might simplify if c1|c2 = -1  
02810 ~j | ~k                 ~(j & k)
02811 (j!=0) | (k!=0)         (j|k)!=0
02812 <comp> | 1              1 
02813 
02814 x & mask1 | compose (0,y) (if appropriate)
02815                          compose (x,y)
02816 
02817  Aggressive:
02818 ~j | j                  -1
02819 j | j                   j
02820 
02821 -------------------------------------------------*/
02822 
02823 static simpnode  simp_bior( OPCODE opc,
02824                       simpnode k0, simpnode k1, BOOL k0const, BOOL k1const)
02825 {
02826    simpnode r = NULL;
02827    INT64   c1,c2;
02828    TYPE_ID  ty;
02829 
02830    /* k0const should always be false. If it isn't we messed up
02831       some canonicalizations */
02832    if (k0const) {
02833       return (r);
02834    }
02835    ty = OPCODE_rtype(opc);
02836 
02837    if (k1const) {
02838       c1 = SIMP_Int_ConstVal(k1); 
02839       if (c1 == 0) {
02840          SHOW_RULE("j|0");
02841          r = k0;
02842          SIMP_DELETE(k1);
02843       } else if (c1 == -1) {
02844          SHOW_RULE("j|-1");
02845          r = SIMP_INTCONST(ty,-1);
02846          SIMP_DELETE_TREE(k0);
02847          SIMP_DELETE(k1);
02848       } else if ((c1 == 1) && (get_inverse_relop(SIMPNODE_opcode(k0))!=0)) {
02849          SHOW_RULE("<comp> | 1");
02850          r = SIMP_INTCONST(ty,1);
02851          SIMP_DELETE_TREE(k0);
02852          SIMP_DELETE(k1);
02853       } else if ((SIMPNODE_operator(k0) == OPR_BAND) &&
02854                  (SIMP_Is_Constant(SIMPNODE_kid1(k0)))) {
02855          c2 = SIMP_Int_ConstVal(SIMPNODE_kid1(k0));
02856          if ((c2 | c1) == -1) {
02857             SHOW_RULE("(j & c2) | c1");
02858             r = SIMPNODE_SimpCreateExp2(opc,SIMPNODE_kid0(k0),k1);
02859             SIMP_DELETE(k0);
02860             SIMP_DELETE(SIMPNODE_kid1(k0));
02861          }
02862       }
02863           
02864    } else if ((SIMPNODE_operator(k0)==OPR_BNOT) && (SIMPNODE_operator(k1)==OPR_BNOT)) {
02865       SHOW_RULE(" ~j | ~k ");
02866       r = SIMPNODE_SimpCreateExp1(OPC_FROM_OPR(OPR_BNOT,ty),
02867                         SIMPNODE_SimpCreateExp2(OPC_FROM_OPR(OPR_BAND,ty),
02868                                       SIMPNODE_kid0(k0),SIMPNODE_kid0(k1)));
02869       SIMP_DELETE(k0);
02870       SIMP_DELETE(k1);
02871 
02872    } else if ((SIMPNODE_operator(k0)==OPR_NE) && (SIMPNODE_operator(k1)==OPR_NE) &&
02873               SIMP_Is_Int_Constant(SIMPNODE_kid1(k0)) &&
02874               SIMP_Is_Int_Constant(SIMPNODE_kid1(k1)) &&
02875               SIMP_Int_ConstVal(SIMPNODE_kid1(k0)) == 0 &&
02876               SIMP_Int_ConstVal(SIMPNODE_kid1(k1)) == 0 &&
02877               (SIMP_TYPE(SIMPNODE_kid0(k0)) == SIMP_TYPE(SIMPNODE_kid0(k1))) &&
02878               (OPCODE_rtype(opc) == (SIMP_TYPE(SIMPNODE_kid0(k0))))) {
02879       SHOW_RULE(" (j!=0) | (k!=0) ");
02880       
02881       r = SIMPNODE_SimpCreateExp2(SIMPNODE_opcode(k0),
02882                         SIMPNODE_SimpCreateExp2(opc, SIMPNODE_kid0(k0), SIMPNODE_kid0(k1)),
02883                         SIMPNODE_kid1(k0));
02884       SIMP_DELETE(k0);
02885       SIMP_DELETE(SIMPNODE_kid1(k1));
02886       SIMP_DELETE(k1);
02887    }
02888 
02889    if (!Enable_Cfold_Aggressive || r) return (r);
02890 
02891    if ((SIMPNODE_operator(k0)==OPR_BNOT && SIMPNODE_Simp_Compare_Trees(SIMPNODE_kid0(k0),k1)==0) ||
02892        (SIMPNODE_operator(k1)==OPR_BNOT && SIMPNODE_Simp_Compare_Trees(SIMPNODE_kid0(k1),k0)==0)) {
02893       SHOW_RULE(" ~j | j ");
02894       r = SIMP_INTCONST(ty,-1);
02895       SIMP_DELETE_TREE(k0);
02896       SIMP_DELETE_TREE(k1);
02897    } else if (SIMPNODE_Simp_Compare_Trees(k0,k1)==0) {
02898       SHOW_RULE(" j | j ");
02899       r = k0;
02900       SIMP_DELETE_TREE(k1);
02901    }
02902 
02903    if (r) return (r);
02904 
02905    if (SIMPNODE_operator(k0) == OPR_BAND && SIMPNODE_operator(k1) == OPR_COMPOSE_BITS &&
02906        SIMP_Is_Constant(SIMPNODE_kid1(k0)) && SIMP_Is_Constant(SIMPNODE_kid0(k1)) &&
02907        SIMP_Int_ConstVal(SIMPNODE_kid0(k1)) == 0)
02908    {
02909      
02910      UINT64 dep_mask = create_bitmask(SIMPNODE_op_bit_size(k1))<<SIMPNODE_op_bit_offset(k1);
02911      UINT64 type_mask = create_bitmask(MTYPE_bit_size(ty));
02912      c1 = SIMP_Int_ConstVal(SIMPNODE_kid1(k0));
02913      if (((dep_mask & c1) == 0) && (((dep_mask | c1) & type_mask) == type_mask)) {
02914        SHOW_RULE("(j&mask)|compose(0,k)");
02915        r = SIMPNODE_SimpCreateDeposit(SIMPNODE_opcode(k1),SIMPNODE_op_bit_offset(k1),
02916                                       SIMPNODE_op_bit_size(k1),SIMPNODE_kid0(k0),SIMPNODE_kid1(k1));
02917        SIMP_DELETE(SIMPNODE_kid1(k0));
02918        SIMP_DELETE(SIMPNODE_kid0(k1));
02919        SIMP_DELETE(k0);
02920        SIMP_DELETE(k1);
02921      }
02922    }
02923    if (Enable_extract_compose && SIMPNODE_operator(k0) == OPR_BAND && SIMPNODE_operator(k1) == OPR_BAND
02924        && SIMP_Is_Constant(SIMPNODE_kid1(k0)) && SIMP_Is_Constant(SIMPNODE_kid1(k1)))
02925    {
02926      c1 = SIMP_Int_ConstVal(SIMPNODE_kid1(k0));
02927      c2 = SIMP_Int_ConstVal(SIMPNODE_kid1(k1));
02928      UINT64 type_mask = create_bitmask(MTYPE_bit_size(ty));
02929      
02930      if (IS_POWER_OF_2(c1+1) && ((c2 & c1) == 0) && (((c2 | c1) & type_mask) == type_mask)) {
02931        SHOW_RULE("(J&mask1) | (k & mask2)");
02932        r = SIMPNODE_SimpCreateDeposit(OPC_FROM_OPR(OPR_COMPOSE_BITS,ty),0,wn_simp_code::log2(c1+1),
02933                                       SIMPNODE_kid0(k1),SIMPNODE_kid0(k0));
02934        SIMP_DELETE(SIMPNODE_kid1(k0));
02935        SIMP_DELETE(SIMPNODE_kid1(k1));
02936        SIMP_DELETE(k0);
02937        SIMP_DELETE(k1);
02938      } else if (IS_POWER_OF_2(c2+1) && ((c2 & c1) == 0) && (((c2 | c1) & type_mask) == type_mask)) {
02939        SHOW_RULE("(J&mask2) | (k & mask1)");
02940        r = SIMPNODE_SimpCreateDeposit(OPC_FROM_OPR(OPR_COMPOSE_BITS,ty),0,wn_simp_code::log2(c2+1),
02941                                       SIMPNODE_kid0(k0),SIMPNODE_kid0(k1));
02942        SIMP_DELETE(SIMPNODE_kid1(k0));
02943        SIMP_DELETE(SIMPNODE_kid1(k1));
02944        SIMP_DELETE(k0);
02945        SIMP_DELETE(k1);
02946      }
02947    }
02948    if (r) return (r);
02949 
02950    r = simp_factor(k0,k1,OPR_BAND,opc,ty,FACTOR_ALL);
02951    if (r) return (r);
02952 
02953    r = simp_factor_idty(k0,k1,OPR_BAND,opc,ty,FALSE);
02954    if (r) return (r);
02955 
02956    /* catch the a | b | c | b type cases */
02957    r = simp_factor(k0,k1,OPR_BIOR,opc,ty,FACTOR_ALL);
02958    if (r) return (r);
02959 
02960    r = simp_factor_idty(k0,k1,OPR_BIOR,opc,ty,FALSE);
02961    if (r) return (r);
02962 
02963    r = simp_factor(k0,k1,OPR_SHL,opc,ty,FACTOR_22);
02964    if (r) return (r);
02965 
02966    r = simp_factor(k0,k1,OPR_ASHR,opc,ty,FACTOR_22);
02967    if (r) return (r);
02968 
02969    r = simp_factor(k0,k1,OPR_LSHR,opc,ty,FACTOR_22);
02970 
02971    return (r);
02972 }
02973 
02974 /*------------------------------------------------ 
02975    Simplifications for bitwise Nor
02976 
02977 Just create NOT (a|b). The NOT simplifier will create BNOR if necessary
02978 
02979 -------------------------------------------------*/
02980 static simpnode  simp_bnor( OPCODE opc,
02981                       simpnode k0, simpnode k1, BOOL k0const, BOOL k1const)
02982 {
02983    simpnode r = NULL;
02984    TYPE_ID   ty; 
02985    
02986    ty = OPCODE_rtype(opc);
02987    r = SIMPNODE_SimplifyExp2(OPC_FROM_OPR(OPR_BIOR,ty),k0,k1);
02988    if (r) {
02989       /* The OR simplified to something */
02990       r = SIMPNODE_SimpCreateExp1(OPC_FROM_OPR(OPR_BNOT,ty),r);
02991    }
02992    if (r) {
02993       SHOW_RULE("BNOR simplified");
02994    }
02995    return (r);
02996 }
02997 
02998 
02999 /*------------------------------------------------ 
03000    Simplifications for ^
03001 
03002 j ^ 0                   j
03003 j ^ -1                  ~j
03004 <comp> ^ 1              <inverse comp>          IEEE_comparisons off for floating
03005                                                 compares
03006 Aggressive:
03007 
03008 j ^ j                   0
03009 j ^ ~j                  -1
03010 -------------------------------------------------*/
03011 
03012 static simpnode  simp_bxor( OPCODE opc,
03013                       simpnode k0, simpnode k1, BOOL k0const, BOOL k1const)
03014 {
03015    simpnode r = NULL;
03016    INT64   c1;
03017    OPCODE  inv_opc;
03018    TYPE_ID   ty; 
03019    
03020    /* k0const should always be false. If it isn't we messed up
03021       some canonicalizations */
03022    if (k0const) {
03023       return (r);
03024    }
03025 
03026    ty = OPCODE_rtype(opc);
03027 
03028    if (k1const) {
03029       c1 = SIMP_Int_ConstVal(k1); 
03030       if (c1 == 0) {
03031          SHOW_RULE("j^0");
03032          r = k0;
03033          SIMP_DELETE(k1);
03034       } else if (c1 == -1) {
03035          SHOW_RULE("j^-1");
03036          r = SIMPNODE_SimpCreateExp1(OPC_FROM_OPR(OPR_BNOT,OPCODE_rtype(opc)),
03037                            k0);
03038          SIMP_DELETE(k1);
03039       } else if ((c1 == 1) && ((inv_opc=get_inverse_relop(SIMPNODE_opcode(k0)))!=0)) {
03040          if (! (Force_IEEE_Comparisons && 
03041                 SIMP_IS_TYPE_FLOATING(OPCODE_desc(inv_opc)))) {
03042             SHOW_RULE("<comp> ^ 1 ");
03043             r = SIMPNODE_SimpCreateExp2(inv_opc,SIMPNODE_kid0(k0),SIMPNODE_kid1(k0));
03044             SIMP_DELETE(k0);
03045             SIMP_DELETE(k1);
03046          }
03047       }
03048    }
03049 
03050    if (!Enable_Cfold_Aggressive || r) return (r);
03051 
03052    if ((SIMPNODE_operator(k0)==OPR_BNOT && SIMPNODE_Simp_Compare_Trees(SIMPNODE_kid0(k0),k1)==0) ||
03053        (SIMPNODE_operator(k1)==OPR_BNOT && SIMPNODE_Simp_Compare_Trees(SIMPNODE_kid0(k1),k0)==0)) {
03054       SHOW_RULE(" ~j ^ j ");
03055       r = SIMP_INTCONST(ty,-1);
03056       SIMP_DELETE_TREE(k0);
03057       SIMP_DELETE_TREE(k1);
03058    } else if (SIMPNODE_Simp_Compare_Trees(k0,k1)==0) {
03059       SHOW_RULE(" j ^ j ");
03060       r = SIMP_INTCONST(ty,0);
03061       SIMP_DELETE_TREE(k0);
03062       SIMP_DELETE_TREE(k1);
03063    }
03064 
03065    if (r) return (r);
03066 
03067    r = simp_factor(k0,k1,OPR_BAND,opc,ty,FACTOR_ALL);
03068    if (r) return (r);
03069 
03070    r = simp_factor_idty(k0,k1,OPR_BAND,opc,ty,FALSE);
03071    if (r) return (r);
03072 
03073    r = simp_factor(k0,k1,OPR_SHL,opc,ty,FACTOR_22);
03074    if (r) return (r);
03075 
03076    r = simp_factor(k0,k1,OPR_ASHR,opc,ty,FACTOR_22);
03077    if (r) return (r);
03078 
03079    r = simp_factor(k0,k1,OPR_LSHR,opc,ty,FACTOR_22);
03080 
03081    return (r);
03082 }
03083 
03084 
03085 /*------------------------------------------------ 
03086    Simplifications for &&
03087 
03088 j && 0                  0
03089 j && 1                  j
03090 !j && !k                !(j || k)               Generates NOR
03091 
03092 Aggressive:
03093 
03094 !j && j                 0                       A
03095 j && j                  j                       A
03096 
03097 -------------------------------------------------*/
03098 
03099 static simpnode  simp_land( OPCODE opc,
03100                       simpnode k0, simpnode k1, BOOL k0const, BOOL k1const)
03101 {
03102    simpnode r = NULL;
03103    INT64   c1;
03104    TYPE_ID  ty;
03105 
03106    /* k0const should always be false. If it isn't we messed up
03107       some canonicalizations */
03108    if (k0const) {
03109       return (r);
03110    }
03111    ty = OPCODE_rtype(opc);
03112 
03113    if (k1const) {
03114       c1 = SIMP_Int_ConstVal(k1); 
03115       if (c1 == 0) {
03116          SHOW_RULE(" j&&0");
03117          r = SIMP_INTCONST(ty,0);
03118          SIMP_DELETE_TREE(k0);
03119          SIMP_DELETE(k1);
03120       } else {
03121          SHOW_RULE(" j&&1");
03122          r = k0;
03123          SIMP_DELETE(k1);
03124       }
03125           
03126    } else if ((SIMPNODE_operator(k0)==OPR_LNOT) && (SIMPNODE_operator(k1)==OPR_LNOT)) {
03127       SHOW_RULE(" !j && !k ");
03128       r = SIMPNODE_SimpCreateExp1(OPC_FROM_OPR(OPR_LNOT,ty),
03129                         SIMPNODE_SimpCreateExp2(OPC_FROM_OPR(OPR_LIOR,ty),
03130                                       SIMPNODE_kid0(k0),SIMPNODE_kid0(k1)));
03131       SIMP_DELETE(k0);
03132       SIMP_DELETE(k1);
03133    }
03134 
03135    if (!Enable_Cfold_Aggressive || r) return (r);
03136 
03137    if ((SIMPNODE_operator(k0)==OPR_LNOT && SIMPNODE_Simp_Compare_Trees(SIMPNODE_kid0(k0),k1)==0) ||
03138        (SIMPNODE_operator(k1)==OPR_LNOT && SIMPNODE_Simp_Compare_Trees(SIMPNODE_kid0(k1),k0)==0)) {
03139       SHOW_RULE(" !j && j ");
03140       r = SIMP_INTCONST(ty,0);
03141       SIMP_DELETE_TREE(k0);
03142       SIMP_DELETE_TREE(k1);
03143    } else if (SIMPNODE_Simp_Compare_Trees(k0,k1)==0) {
03144       SHOW_RULE(" j && j ");
03145       r = k0;
03146       SIMP_DELETE_TREE(k1);
03147    }
03148 
03149    if (r) return (r);
03150 
03151    r = simp_factor(k0,k1,OPR_LIOR,opc,ty,FACTOR_ALL);
03152    if (!r) r = simp_factor_idty(k0,k1,OPR_LIOR,opc,ty,FALSE);
03153 
03154    return (r);
03155 }
03156 
03157 
03158 /*------------------------------------------------ 
03159    Simplifications for ||
03160 
03161 j || 0                  j
03162 j || 1                  1
03163 !j || !k                !(j && k)
03164 
03165 Aggressive:
03166 !j || j                 1                       A
03167 j || j                  j                       A
03168 
03169 -------------------------------------------------*/
03170 
03171 static simpnode  simp_lior( OPCODE opc, 
03172                       simpnode k0, simpnode k1, BOOL k0const, BOOL k1const)
03173 {
03174    simpnode r = NULL;
03175    INT64   c1;
03176    TYPE_ID  ty;
03177 
03178    /* k0const should always be false. If it isn't we messed up
03179       some canonicalizations */
03180    if (k0const) {
03181       return (r);
03182    }
03183    ty = OPCODE_rtype(opc);
03184 
03185    if (k1const) {
03186       c1 = SIMP_Int_ConstVal(k1); 
03187       if (c1 == 0) {
03188          SHOW_RULE("j||0");
03189          r = k0;
03190          SIMP_DELETE(k1);
03191       } else {
03192          SHOW_RULE("j||1");
03193          r = SIMP_INTCONST(ty,1);
03194          SIMP_DELETE_TREE(k0);
03195          SIMP_DELETE(k1);
03196       }
03197    } else if ((SIMPNODE_operator(k0)==OPR_LNOT) && (SIMPNODE_operator(k1)==OPR_LNOT)) {
03198       SHOW_RULE(" !j || !k ");
03199       r = SIMPNODE_SimpCreateExp1(OPC_FROM_OPR(OPR_LNOT,ty),
03200                         SIMPNODE_SimpCreateExp2(OPC_FROM_OPR(OPR_LAND,ty),
03201                                       SIMPNODE_kid0(k0),SIMPNODE_kid0(k1)));
03202       SIMP_DELETE(k0);
03203       SIMP_DELETE(k1);
03204    }
03205 
03206    if (!Enable_Cfold_Aggressive || r) return (r);
03207 
03208    if ((SIMPNODE_operator(k0)==OPR_LNOT && SIMPNODE_Simp_Compare_Trees(SIMPNODE_kid0(k0),k1)==0) ||
03209        (SIMPNODE_operator(k1)==OPR_LNOT && SIMPNODE_Simp_Compare_Trees(SIMPNODE_kid0(k1),k0)==0)) {
03210       SHOW_RULE(" !j || j ");
03211       r = SIMP_INTCONST(ty,1);
03212       SIMP_DELETE_TREE(k0);
03213       SIMP_DELETE_TREE(k1);
03214    } else if (SIMPNODE_Simp_Compare_Trees(k0,k1)==0) {
03215       SHOW_RULE(" j || j ");
03216       r = k0;
03217       SIMP_DELETE_TREE(k1);
03218    }
03219 
03220    if (r) return (r);
03221 
03222    r = simp_factor(k0,k1,OPR_LAND,opc,ty,FACTOR_ALL);
03223    if (!r) r = simp_factor_idty(k0,k1,OPR_LAND,opc,ty,TRUE);
03224 
03225    return (r);
03226 }
03227 
03228 /*------------------------------------------------ 
03229    Simplifications for && (with control flow)
03230 
03231 j && 1                  j
03232 0 && j                  0
03233 1 && j                  j
03234 
03235 -------------------------------------------------*/
03236 
03237 static simpnode  simp_cand( OPCODE opc,
03238                       simpnode k0, simpnode k1, BOOL k0const, BOOL k1const)
03239 {
03240    simpnode r = NULL;
03241    INT64   c1;
03242 
03243    if (k0const) {
03244      c1 = SIMP_Int_ConstVal(k0); 
03245      if (c1 == 0) {
03246        SHOW_RULE(" 0 c&& j");
03247        r = SIMP_INTCONST(OPCODE_rtype(opc),0);
03248        SIMP_DELETE(k0);
03249        SIMP_DELETE_TREE(k1);
03250       } else {
03251         SHOW_RULE(" 1 c&& j");
03252         r = k1;
03253         SIMP_DELETE(k0);
03254       }
03255    } else if (k1const) {
03256      c1 = SIMP_Int_ConstVal(k1); 
03257      if (c1 != 0) {
03258        SHOW_RULE(" j c&& 1");
03259        r = k0;
03260        SIMP_DELETE(k1);
03261      }
03262    } 
03263    
03264    return (r);
03265 }
03266 
03267 
03268 /*------------------------------------------------ 
03269    Simplifications for || (with control flow)
03270 
03271 j || 0                  j
03272 0 || j                  j
03273 1 || j                  1
03274 
03275 -------------------------------------------------*/
03276 
03277 static simpnode  simp_cior( OPCODE opc, 
03278                       simpnode k0, simpnode k1, BOOL k0const, BOOL k1const)
03279 {
03280    simpnode r = NULL;
03281    INT64   c1;
03282 
03283    /* k0const should always be false. If it isn't we messed up
03284       some canonicalizations */
03285    if (k0const) {
03286       return (r);
03287    }
03288 
03289    if (k0const) {
03290      c1 = SIMP_Int_ConstVal(k0); 
03291      if (c1 == 0) {
03292        SHOW_RULE("0 c|| j");
03293        r = k1;
03294        SIMP_DELETE(k0);
03295      } else {
03296        SHOW_RULE("1 c|| j");
03297        r = SIMP_INTCONST(OPCODE_rtype(opc),1);
03298        SIMP_DELETE(k0);
03299        SIMP_DELETE_TREE(k1);
03300      }
03301    } else if (k1const) {
03302      c1 = SIMP_Int_ConstVal(k1); 
03303       if (c1 == 0) {
03304         SHOW_RULE("j c|| 0");
03305         r = k0;
03306         SIMP_DELETE(k1);
03307       } 
03308    }
03309 
03310    return (r);
03311 }
03312 
03313 /*------------------------------------------------ 
03314    Simplifications for <<, >>
03315 
03316 j >> c1                 j  if (c1 & shiftsize-1) == 0
03317 j << c1                 j  if (c1 & shiftsize-1) == 0
03318 (j << c2) << c1         j << c1+c2, unless c1 + c2 >= max shift, in which case 0
03319 (j >> c2) >> c1         j >> c1+c2, unless c1 + c2 >= max shift, in which case 0
03320 (j >> c1) << c1         j & ~((1<<c1)-1)
03321 (j << c1) lshr c1       j & ((1<<(wordsize-c1))-1)
03322 
03323 (j<<c1) >> c2           appropriate EXTRACT
03324 (j & mask) << c1        appropriate COMPOSE
03325 
03326 
03327 (j >> c1)               0 if j is a load of an unsigned
03328                           short type and (c1 mod lengthofshift) > (lengthoftype)
03329 
03330 (integerCVT(X) << c1)   X if c1 >= 32
03331 (j << 32) ashr 32       I8U4CVT (j)
03332 
03333 
03334 j shift (k & mask)      j << k  if mask & (shift_size-1) == shift_size-1
03335 
03336 (j & mask) << k         j << k if lower (shift_length - k) bits are all 1's.
03337 
03338 (j & c1) >> k           j >> k &
03339 -------------------------------------------------*/
03340 
03341 static simpnode  simp_shift( OPCODE opc,
03342                        simpnode k0, simpnode k1, BOOL k0const, BOOL k1const)
03343 {
03344    simpnode r = NULL;
03345    INT64   c1,c2,mask;
03346    TYPE_ID  ty,rty;
03347    INT64  shift_size;
03348    BOOL   firstop_is_shift=FALSE;
03349    INT64  shift_size2;
03350    OPERATOR  firstop, op;
03351    OPCODE    first_opcode;
03352    simpnode tmp; 
03353 
03354    op = OPCODE_operator(opc);
03355    ty = OPCODE_rtype(opc);
03356    if (ty==MTYPE_U8 || ty==MTYPE_I8) {
03357       shift_size = 64;
03358    } else {
03359       shift_size = 32;
03360    }
03361    first_opcode = SIMPNODE_opcode(k0);
03362    firstop = OPCODE_operator(first_opcode);
03363    if (firstop == OPR_SHL || firstop == OPR_ASHR ||
03364        firstop == OPR_LSHR) {
03365       firstop_is_shift=TRUE;
03366       if (SIMPNODE_rtype(k0) == MTYPE_U8 ||
03367           SIMPNODE_rtype(k0) == MTYPE_I8) {
03368          shift_size2 = 64;
03369       } else {
03370          shift_size2 = 32;
03371       }
03372    }
03373 
03374    if (k1const) {
03375       if (ARCH_mask_shift_counts) {
03376          c1 = SIMP_Int_ConstVal(k1) & (shift_size-1);
03377       } else {
03378          c1 = MIN((UINT64) SIMP_Int_ConstVal(k1),shift_size);
03379       }
03380      
03381       /* 
03382        * j >> c1, c1=0
03383        * j << c1, c1=0
03384        */
03385       if (c1 == 0) {
03386          SHOW_RULE("j shift 0");
03387          r = k0;
03388          SIMP_DELETE(k1);
03389          return (r);
03390       }
03391       /* 
03392        * j >> c1, c1 >= shift_size
03393        */
03394       if (c1 >= shift_size) {
03395          if (op != OPR_ASHR) {
03396             /* The two shifts shift off all the bits, so we get 0 */
03397             SHOW_RULE("j shift big count -> 0");
03398             r = SIMP_INTCONST(OPCODE_rtype(opc),0);
03399             SIMP_DELETE_TREE(k0);
03400             SIMP_DELETE(k1);
03401          } else {  /* ASHR, just do one shift of size shift_size-1 */
03402             SHOW_RULE("j ASHR bigcount");
03403             r = SIMPNODE_SimpCreateExp2(opc,k0,SIMP_INTCONST(ty, shift_size-1));
03404             SIMP_DELETE(k1);
03405          }
03406          return (r);
03407       }
03408       if (!WHIRL_Keep_Cvt_On &&
03409           op == OPR_SHL &&
03410           firstop == OPR_CVT &&
03411           SIMP_IS_TYPE_INTEGRAL(OPCODE_rtype(first_opcode)) &&
03412           SIMP_IS_TYPE_INTEGRAL(OPCODE_desc(first_opcode)) &&
03413           c1 >= 32) {
03414          SHOW_RULE("Integer CVT << c1, c1>=32");
03415          r = SIMPNODE_SimpCreateExp2(opc,SIMPNODE_kid0(k0),k1);
03416          SIMP_DELETE(k0);
03417       } else if (firstop_is_shift && shift_size==shift_size2 && 
03418                  SIMP_Is_Constant(SIMPNODE_kid1(k0))) {
03419          if (ARCH_mask_shift_counts) {
03420             c2 = SIMP_Int_ConstVal(SIMPNODE_kid1(k0)) & (shift_size-1);
03421          } else {
03422             c2 = MIN((UINT64) SIMP_Int_ConstVal(SIMPNODE_kid1(k0)),shift_size);
03423          }
03424          if (firstop == op ) {
03425             /* 
03426              * (j << c2) << c1          j << min(c1+c2,max possible shift)
03427              * (j >> c2) >> c1          j >> min(c1+c2,max possible shift)
03428              */
03429             if ((c1 + c2) >= shift_size) {
03430                if (op != OPR_ASHR) {
03431                   /* The two shifts shift off all the bits, so we get 0 */
03432                   SHOW_RULE("j shift c2 shift c1 -> 0");
03433                   r = SIMP_INTCONST(OPCODE_rtype(opc), 0);
03434                   SIMP_DELETE_TREE(k0);
03435                   SIMP_DELETE_TREE(k1);
03436                } else {  /* ASHR, just do one shift of size shift_size-1 */
03437                   SHOW_RULE("j ASHR c2 ASHR c1");
03438                   r = SIMPNODE_SimpCreateExp2(opc,SIMPNODE_kid0(k0),SIMP_INTCONST(ty, shift_size-1));
03439                   SIMP_DELETE(SIMPNODE_kid1(k0));
03440                   SIMP_DELETE(k0);
03441                   SIMP_DELETE(k1);
03442                }
03443             } else {
03444                /* We can combine the two shifts */      
03445                SHOW_RULE("j shift c2 shift c1");
03446                r = SIMPNODE_SimpCreateExp2(opc,SIMPNODE_kid0(k0),SIMP_INTCONST(ty, c1+c2));
03447                SIMP_DELETE(SIMPNODE_kid1(k0));
03448                SIMP_DELETE(k0);
03449                SIMP_DELETE(k1);
03450             }
03451          } else if (firstop != OPR_SHL && op == OPR_SHL && c1==c2) {
03452             SHOW_RULE("(j >> c1) << c1");
03453             c2 = ~create_bitmask(c1);
03454             r = SIMPNODE_SimpCreateExp2(OPC_FROM_OPR(OPR_BAND,ty),
03455                               SIMPNODE_kid0(k0),
03456                              SIMP_INTCONST(ty,c2));
03457             SIMP_DELETE(SIMPNODE_kid1(k0));
03458             SIMP_DELETE(k0);
03459             SIMP_DELETE(k1);
03460          } else if (firstop == OPR_SHL && op == OPR_LSHR && c1==c2) {
03461             SHOW_RULE("(j << c1) LSHR c1");
03462             c2 = create_bitmask(shift_size-c1);
03463             r = SIMPNODE_SimpCreateExp2(OPC_FROM_OPR(OPR_BAND,ty),
03464                               SIMPNODE_kid0(k0),
03465                              SIMP_INTCONST(ty,c2));
03466             SIMP_DELETE(SIMPNODE_kid1(k0));
03467             SIMP_DELETE(k0);
03468             SIMP_DELETE(k1);
03469          } else if (firstop == OPR_SHL && op == OPR_LSHR && Enable_extract_compose && c1 > c2) {
03470            SHOW_RULE("(j << c1) LSHR c2");
03471            INT16 boffset = c1 - c2;
03472            INT16 bsize = shift_size - c1;
03473            if (bsize < 1) bsize = 1;
03474            r = SIMPNODE_SimpCreateExtract(shift_size == 32 ? OPC_U4EXTRACT_BITS : OPC_U8EXTRACT_BITS,
03475                                        boffset, bsize,
03476                                        SIMPNODE_kid0(k0));
03477            SIMP_DELETE(SIMPNODE_kid1(k0));
03478            SIMP_DELETE(k0);
03479            SIMP_DELETE(k1);
03480          } else if (firstop == OPR_SHL && op == OPR_ASHR && c1 == 32 && c2 == 32) {
03481            rty = SIMPNODE_rtype(SIMPNODE_kid0(k0));
03482            if (rty == MTYPE_I4 || rty == MTYPE_U4) {
03483               SHOW_RULE("(j << 32) ASHR 32");
03484               r = SIMPNODE_SimpCreateExp1(OPC_I8I4CVT,SIMPNODE_kid0(k0));
03485               SIMP_DELETE(SIMPNODE_kid1(k0));
03486               SIMP_DELETE(k0);
03487               SIMP_DELETE(k1);
03488            }
03489            // This next one must follow this preceeding one, so that we preference
03490            // the case c1 == c2 == 32
03491          } else if (firstop == OPR_SHL && op == OPR_ASHR && Enable_extract_compose && c1 >= c2) {
03492            SHOW_RULE("(j << c1) ASHR c2");
03493            INT16 boffset = c1 - c2;
03494            INT16 bsize = shift_size - c1;
03495            if (bsize < 1) bsize = 1;
03496            r = SIMPNODE_SimpCreateExtract(shift_size == 32 ? OPC_I4EXTRACT_BITS : OPC_I8EXTRACT_BITS,
03497                                        boffset, bsize,
03498                                        SIMPNODE_kid0(k0));
03499            SIMP_DELETE(SIMPNODE_kid1(k0));
03500            SIMP_DELETE(k0);
03501            SIMP_DELETE(k1);
03502          }
03503       } else if (firstop == OPR_BAND && op == OPR_SHL &&
03504                  SIMP_Is_Constant(SIMPNODE_kid1(k0))) {
03505          c2 = SIMP_Int_ConstVal(SIMPNODE_kid1(k0));
03506          /* See if the mask is all 1's in the right places */
03507          mask = create_bitmask(shift_size-c1);
03508          if ((c2 & mask) == mask) {
03509             SHOW_RULE("(j & mask) << c1");
03510             r = SIMPNODE_SimpCreateExp2(opc,SIMPNODE_kid0(k0),k1);
03511             SIMP_DELETE(SIMPNODE_kid1(k0));
03512             SIMP_DELETE(k0);
03513             return (r);
03514          } else if (Enable_extract_compose && IS_POWER_OF_2(c2+1)) {
03515            SHOW_RULE("(j & mask) << c1 -> COMPOSE");
03516            c2 = wn_simp_code::log2(c2+1);
03517            r = SIMPNODE_SimpCreateDeposit(OPC_FROM_OPR(OPR_COMPOSE_BITS,ty),c1,c2,
03518                                           SIMP_INTCONST(ty,0),SIMPNODE_kid0(k0));
03519            SIMP_DELETE(SIMPNODE_kid1(k0));
03520            SIMP_DELETE(k0);
03521            return (r);
03522          }
03523       } else if (firstop == OPR_BAND && (op == OPR_ASHR || op == OPR_LSHR) &&
03524                  SIMP_Is_Constant(SIMPNODE_kid1(k0)) &&
03525                  shift_size == MTYPE_bit_size(OPCODE_rtype(first_opcode))) {
03526          c2 = SIMP_Int_ConstVal(SIMPNODE_kid1(k0));
03527          SHOW_RULE("(j & mask) >> c1");
03528          tmp = SIMPNODE_SimpCreateExp2(opc,SIMPNODE_kid1(k0),SIMPNODE_CopyNode(k1));
03529          r = SIMPNODE_SimpCreateExp2(opc,SIMPNODE_kid0(k0),k1);
03530          r = SIMPNODE_SimpCreateExp2(SIMPNODE_opcode(k0),r,tmp);
03531          SIMP_DELETE(k0);
03532       } else {
03533          rty = get_value_type(k0);
03534          if (rty != ty && ((op == OPR_LSHR)
03535                            || (op == OPR_ASHR &&
03536                                SIMP_IS_TYPE_UNSIGNED(SIMP_TYPE(k0)) &&
03537                                SIMP_TYPE_SIZE(rty) < SIMP_TYPE_SIZE(ty)))) {
03538             if (c1 >= SIMP_TYPE_SIZE(rty)) {
03539                SHOW_RULE("short >> large c1 = 0");
03540                r = SIMP_INTCONST(ty,0);
03541             }
03542          }
03543       }
03544    }
03545    if (r) return (r);
03546 
03547    /* Non-constant second child */
03548    if (SIMPNODE_operator(k1) == OPR_BAND &&
03549        SIMP_Is_Constant(SIMPNODE_kid1(k1)) && ARCH_mask_shift_counts) {
03550       c1 = SIMP_Int_ConstVal(SIMPNODE_kid1(k1));
03551       if  ((c1 & (shift_size-1)) == shift_size-1) {
03552          SHOW_RULE ("j shift (X & mask)");
03553          r = SIMPNODE_SimpCreateExp2(opc,k0,SIMPNODE_kid0(k1));
03554          SIMPNODE_DELETE(SIMPNODE_kid1(k1));
03555          SIMPNODE_DELETE(k1);
03556       }
03557    }
03558    return (r);
03559 }
03560 
03561 
03562 
03563 /*---------------------------------------------
03564 
03565 Helper routine for simplifying expressions like
03566  x+y relop x+z  -> y relop z
03567  x+y relop x    -> y relop 0
03568  -x relop -y    -> y relop x
03569 
03570 ---------------------------------------------*/
03571 
03572 static simpnode cancel_in_relop(OPCODE opc, TYPE_ID ty, simpnode k0, simpnode k1)
03573 {
03574    simpnode r = NULL;
03575    simpnode t;
03576    simpnode dt;
03577    OPERATOR op0,op1,top,mainopr;
03578    char buf[64];  /* for the show message */
03579    OPCODE kidop;
03580    
03581    simpnode   x[4],lhs,rhs,del1,del2,del3;
03582    BOOL     s[4],s_lhs,s_rhs,pointer_seen;
03583    INT32    i,j,jmax;
03584    
03585    op0 = SIMPNODE_operator(k0);
03586    op1 = SIMPNODE_operator(k1);
03587 
03588    /* If we have a negate on both sides, remove it and flip the comparison */
03589    if (op0 == OPR_NEG && op1 == OPR_NEG) {
03590       SHOW_RULE("-x relop -y");
03591       r = SIMPNODE_SimpCreateExp2(OPCODE_commutative_op(opc),SIMPNODE_kid0(k0),SIMPNODE_kid0(k1));
03592       SIMPNODE_DELETE(k0);
03593       SIMPNODE_DELETE(k1);
03594       return (r);
03595    }
03596 
03597    /* Special for a pair of LDA's */
03598    if (op0 == OPR_LDA && op1 == OPR_LDA &&
03599        SIMPNODE_Compare_Symbols(k0,k1) == 0) {
03600       SHOW_RULE("LDA relop LDA");
03601       lhs = SIMP_INTCONST(MTYPE_I8,SIMPNODE_lda_offset(k0));
03602       rhs = SIMP_INTCONST(MTYPE_I8,SIMPNODE_lda_offset(k1));
03603       opc = OPCODE_make_op(OPCODE_operator(opc),MTYPE_I4,MTYPE_I8);
03604       SIMPNODE_DELETE(k0);
03605       SIMPNODE_DELETE(k1);
03606       r = SIMPNODE_SimpCreateExp2(opc,lhs,rhs);
03607    }
03608 
03609    if (!Enable_Cfold_Aggressive) return (r);
03610    if (SIMP_IS_TYPE_FLOATING(ty) &&
03611        (!Enable_Cfold_Reassociate || Force_IEEE_Comparisons
03612         || Roundoff_Level < ROUNDOFF_ANY)) return(r);
03613 
03614    /* might we have nothing to do? */
03615    if (op0 != OPR_ADD && op1 != OPR_ADD && op0 != OPR_SUB && op1 != OPR_SUB) return (r);
03616 
03617 
03618    /* mini canonicalization, put +- on left */
03619    if (op0 != OPR_ADD && op0 != OPR_SUB) {
03620       /* Swap around */
03621       opc = OPCODE_commutative_op(opc);
03622       t = k0; k0 = k1; k1 = t;
03623       top = op0; op0 = op1; op1 = top;
03624    }
03625 
03626    /* mini canonicalization, put + on left */
03627    if (op0 != OPR_ADD && op1 == OPR_ADD) {
03628       /* Swap around */
03629       opc = OPCODE_commutative_op(opc);
03630       t = k0; k0 = k1; k1 = t;
03631       top = op0; op0 = op1; op1 = top;
03632    }
03633 
03634    mainopr = OPCODE_operator(opc);
03635 
03636    /* Pick up the 3 or 4 pieces */
03637    s[0] = 0;
03638    s[1] = (op0 == OPR_SUB);
03639    x[0] = SIMPNODE_kid0(k0);
03640    x[1] = SIMPNODE_kid1(k0);
03641    
03642    if (op1 == OPR_ADD || op1 == OPR_SUB) {
03643       s[2] = 0;
03644       s[3] = (op1 == OPR_SUB);
03645       x[2] = SIMPNODE_kid0(k1);
03646       x[3] = SIMPNODE_kid1(k1);
03647       jmax = 3;
03648    } else if (op1 == OPR_NEG) {
03649       s[2] = 1;
03650       x[2] = SIMPNODE_kid0(k1);
03651       x[3] = NULL;
03652       jmax = 2;
03653    } else {
03654       s[2] = 0;
03655       x[2] = k1;
03656       x[3] = NULL;
03657       jmax = 2;
03658    }
03659 
03660    /* Check for pointer arithmetic in any of the X's */
03661    pointer_seen = FALSE;
03662    if (mainopr != OPR_EQ && mainopr != OPR_NE) {  /* We only want to special case for 
03663                                                      <, <=, > ,>= */
03664       for (i=0; i <= jmax; i++) {
03665          kidop = SIMPNODE_opcode(x[i]);
03666          if (OPCODE_has_1ty(kidop) || OPCODE_has_2ty(kidop)) {
03667             if (TY_kind (SIMPNODE_ty(x[i])) == KIND_POINTER) {
03668                pointer_seen = TRUE;
03669                break;
03670             }
03671          } else if (OPCODE_operator(kidop) == OPR_LDA) {
03672             pointer_seen = TRUE;
03673             break;
03674          }
03675       }
03676    }
03677    
03678    /* Can't do this for unsigned's either */
03679    if (SIMP_IS_TYPE_UNSIGNED(ty) && !pointer_seen && !Simp_Fold_Unsigned_Relops &&
03680        (mainopr != OPR_EQ && mainopr != OPR_NE)) return(r);
03681 
03682    /* Don't do anything if we are trying to make sure that overflow doesn't change the answers */
03683    if ((mainopr != OPR_EQ && mainopr != OPR_NE) &&
03684        SIMP_IS_TYPE_INTEGRAL(ty) && !SIMP_IS_TYPE_UNSIGNED(ty) &&
03685        !Simp_Unsafe_Relops) return (r);
03686 
03687 
03688    /* Do all the pairwise comparisons */
03689    for (i=0; i <= 1; i++) {
03690       for (j=2; j <= jmax; j++) {
03691          if (s[i]==s[j] && (dt = simp_diff_value(x[i],x[j],s[i]))) {
03692             /* We've found a match, cancel and return */
03693             /* get the remaining quantities */
03694             lhs = x[1-i]; s_lhs = s[1-i];
03695             rhs = x[5-j]; s_rhs = s[5-j];
03696             if (!rhs) {
03697                rhs = dt;
03698                if (!s_lhs) {
03699                   rhs = SIMPNODE_SimpCreateExp1(OPC_FROM_OPR(OPR_NEG,ty),rhs);
03700                }
03701                s_rhs = s_lhs; /* We always want to give RHS and LHS the same sign if possible */
03702             } else {
03703                /* We need to fix up the lhs with the offset */
03704                if (s_lhs) {
03705                   dt = SIMPNODE_SimpCreateExp1(OPC_FROM_OPR(OPR_NEG,ty),dt);
03706                }
03707                lhs = SIMPNODE_SimpCreateExp2(OPC_FROM_OPR(OPR_ADD,ty),lhs,dt);
03708             }
03709             
03710             if (pointer_seen) {
03711             /* Special treatment of pointer comparisons. After
03712              *  cancellation, we need to do a SIGNED comparison on the two
03713              *  remaining arguments cases.
03714              */
03715                sprintf(buf,"(pointers) x+y relop x+z %2d %2d\n",i,j);
03716                SHOW_RULE(buf);
03717                /* Convert to signed comparison */
03718                if (ty == MTYPE_U8) {
03719                   opc = OPCODE_make_op(mainopr,OPCODE_rtype(opc),MTYPE_I8);
03720                } else if (ty == MTYPE_U4) {
03721                   opc = OPCODE_make_op(mainopr,OPCODE_rtype(opc),MTYPE_I4);
03722                }
03723                if (s_lhs && s_rhs) {
03724                   r = SIMPNODE_SimpCreateExp2(opc,rhs,lhs);
03725                } else {
03726                   if (s_lhs) {
03727                      lhs = SIMPNODE_SimpCreateExp1(OPC_FROM_OPR(OPR_NEG,ty),lhs);
03728                   }
03729                   if (s_rhs) {
03730                      rhs = SIMPNODE_SimpCreateExp1(OPC_FROM_OPR(OPR_NEG,ty),rhs);
03731                   }
03732                   r = SIMPNODE_SimpCreateExp2(opc,lhs,rhs);
03733                }
03734                SIMP_DELETE_TREE(x[i]);
03735                SIMP_DELETE_TREE(x[j]);
03736                SIMP_DELETE(k0);
03737                if (k1 != x[j]) SIMP_DELETE(k1);
03738                return (r);
03739                
03740             } else {  /* Non-pointer case */
03741                sprintf(buf,"x+y relop x+z %2d %2d\n",i,j);
03742                SHOW_RULE(buf);
03743                
03744                /* Build lhs op rhs with appropriate signs */
03745                /* special case: left and right sides both have negates */
03746                if (s_lhs && s_rhs) {
03747                   r = SIMPNODE_SimpCreateExp2(opc,rhs,lhs);
03748                } else {
03749                   if (s_lhs) {
03750                      lhs = SIMPNODE_SimpCreateExp1(OPC_FROM_OPR(OPR_NEG,ty),lhs);
03751                   }
03752                   if (s_rhs) {
03753                      rhs = SIMPNODE_SimpCreateExp1(OPC_FROM_OPR(OPR_NEG,ty),rhs);
03754                   }
03755                   r = SIMPNODE_SimpCreateExp2(opc,lhs,rhs);
03756                }
03757                SIMP_DELETE_TREE(x[i]);
03758                SIMP_DELETE_TREE(x[j]);
03759                SIMP_DELETE(k0);
03760                if (k1 != x[j]) SIMP_DELETE(k1);
03761                return (r);
03762             }
03763          }
03764       }
03765    }
03766    if (r) return (r);
03767 
03768    /* Now we need to check each side against the pieces of the other side,
03769     We only need to do this if we had add/sub ops on both sides */
03770    if (jmax != 3) return (r); 
03771 
03772    /* compare LHS against pieces of RHS */
03773    lhs = NULL;
03774    rhs = NULL;
03775    
03776    for (i=0; i <= 1; i++) {
03777       if (s[i] == 0 && (dt = simp_diff_value(k1,x[i],TRUE))) {
03778          lhs = x[1-i];
03779          s_lhs = s[1-i];
03780          del1 = x[i];
03781          del2 = k1;
03782          del3 = k0;
03783          break;
03784       } else if (s[i+2] == 0 && (dt = simp_diff_value(k0,x[i+2],FALSE))) {
03785          rhs = x[3-i];
03786          s_rhs = s[3-i];
03787          del1 = x[i+2];
03788          del2 = k0;
03789          del3 = k1;
03790          break;
03791       }
03792    }
03793    if (lhs || rhs) { /* We found something */
03794       if (!rhs) {
03795          rhs = dt;
03796          s_rhs = 0;
03797       }
03798       if (!lhs) {
03799          lhs = dt;
03800          s_lhs = 0;
03801       }
03802             
03803       if (pointer_seen) {
03804          /* Special treatment of pointer comparisons. After
03805           * cancellation, we need to do a SIGNED comparison on the two
03806           * remaining arguments cases.
03807           */
03808          SHOW_RULE("(pointers) x+y relop x");
03809          /* Convert to signed comparison */
03810          if (ty == MTYPE_U8) {
03811             opc = OPCODE_make_op(mainopr,OPCODE_rtype(opc),MTYPE_I8);
03812          } else if (ty == MTYPE_U4) {
03813             opc = OPCODE_make_op(mainopr,OPCODE_rtype(opc),MTYPE_I4);
03814          }
03815          if (s_lhs && s_rhs) {
03816             r = SIMPNODE_SimpCreateExp2(opc,rhs,lhs);
03817          } else {
03818             if (s_lhs) {
03819                lhs = SIMPNODE_SimpCreateExp1(OPC_FROM_OPR(OPR_NEG,ty),lhs);
03820             }
03821             if (s_rhs) {
03822                rhs = SIMPNODE_SimpCreateExp1(OPC_FROM_OPR(OPR_NEG,ty),rhs);
03823             }
03824             r = SIMPNODE_SimpCreateExp2(opc,lhs,rhs);
03825          }
03826          /* Clean up the old trees */
03827          SIMP_DELETE_TREE(del1);
03828          SIMP_DELETE_TREE(del2);
03829          SIMP_DELETE(del3);
03830          return (r);
03831          
03832       } else {  /* Non-pointer case */
03833          SHOW_RULE(" x+y relop x");
03834          /* Build lhs op rhs with appropriate signs */
03835          /* special case: left and right sides both have negates */
03836          if (s_lhs && s_rhs) {
03837             r = SIMPNODE_SimpCreateExp2(opc,rhs,lhs);
03838          } else {
03839             if (s_lhs) {
03840                lhs = SIMPNODE_SimpCreateExp1(OPC_FROM_OPR(OPR_NEG,ty),lhs);
03841             }
03842             if (s_rhs) {
03843                rhs = SIMPNODE_SimpCreateExp1(OPC_FROM_OPR(OPR_NEG,ty),rhs);
03844             }
03845             r = SIMPNODE_SimpCreateExp2(opc,lhs,rhs);
03846          }
03847          /* Clean up the old trees */
03848          SIMP_DELETE_TREE(del1);
03849          SIMP_DELETE_TREE(del2);
03850          SIMP_DELETE(del3);
03851          return (r);
03852       }
03853    }
03854    return (r);
03855 }
03856 
03857 /*------------------------------------------------ 
03858    Simplifications for ==, !=
03859 
03860 (x reloporlogop y)==1   x reloporlogop y 
03861 (x reloporlogop y)!=0   x reloporlogop y
03862 (x relop y)==0          x inverserelop Y                
03863 (x relop y)!=1          x inverserelop Y
03864 (x logop y)==0          !(x logop Y)
03865 (x logop y)!=1          !(x logop Y)
03866 (j & c2) != c1          1 if (c1 & ~c2) is non-zero
03867 (j & c2) == c1          0 if (c1 & ~c2) is non-zero
03868 (j | c2) != c1          1 if (c2 & ~c1) is non-zero
03869 (j | c2) == c1          0 if (c2 & ~c1) is non-zero
03870 (~j & c2) == 0          (j & c2) != 0 if c2 is a power of 2
03871 
03872 (j +- c2) relop c1      j relop (c1 -+ c2)
03873 (c2 - j) relop c1      j relop (c2 - c1)
03874 (j * c2) op c1         j op c1/c2 if c2 divides c1
03875 
03876 
03877  Aggressive:
03878 j==j                    1                       A
03879 j!=j                    0                       A
03880 a==a                    1                       A, IEEE_comparisons is off
03881 a!=a                    0                       A, IEEE_comparisons is off
03882 
03883 x+-y op x+-z          y op z  (and related)   A, IEEE_comparisons is off, Enable_Cfold_Reassociate on 
03884 x+-y op x             y op 0                  A, IEEE_comparisons is off, Enable_Cfold_Reassociate on 
03885 
03886 -------------------------------------------------*/
03887 
03888 static simpnode
03889 simp_eq_neq (OPCODE opc, simpnode k0, simpnode k1, BOOL k0const, BOOL k1const)
03890 {
03891    simpnode r = NULL, expr;
03892    INT64 c1,c2,c3;
03893    TYPE_ID  ty;
03894    BOOL   iseq;
03895    OPCODE firstop,inv_op;
03896     
03897    iseq = (OPCODE_operator(opc) == OPR_EQ);
03898 
03899    /* k0const should always be false. If it isn't we messed up
03900       some canonicalizations */
03901    if (k0const) {
03902       return (r);
03903    }
03904     
03905    firstop = SIMPNODE_opcode(k0);
03906    inv_op = get_inverse_relop(firstop);
03907    ty = OPCODE_rtype(firstop);
03908 
03909    if (k1const && SIMP_IS_TYPE_INTEGRAL(ty)) {
03910       c1 = SIMP_Int_ConstVal(k1); 
03911       if (c1 == 0 || c1 == 1) {
03912          if (((is_logop(firstop) && (ty == OPCODE_rtype(opc))) || inv_op) && 
03913              ((iseq && c1==1) || (!iseq && c1==0))){
03914             /*
03915              * (x reloporlogop y)==1
03916              * (x reloporlogop y)!=0
03917              */
03918             SHOW_RULE("x reloporlogop y ==1,!=0");
03919             r = SIMPNODE_SimpCreateExp2(
03920                 OPCODE_make_op(OPCODE_operator(firstop),
03921                                OPCODE_rtype(opc),
03922                                OPCODE_desc(firstop)),
03923                 SIMPNODE_kid0(k0),SIMPNODE_kid1(k0));
03924             SIMP_DELETE(k0);
03925             SIMP_DELETE(k1);
03926          } else if (is_logop(firstop) &&
03927                     ((iseq && c1==0) || (!iseq && c1==1))) {
03928             /*
03929              * (x logop y)==0
03930              * (x logop y)!=1
03931              */
03932             SHOW_RULE("x logop y ==0,!=1");
03933             r = SIMPNODE_SimpCreateExp1(OPC_FROM_OPR(OPR_LNOT,ty), k0);
03934             SIMP_DELETE(k1);
03935          } else if (inv_op &&
03936                     ((iseq && c1==0) || (!iseq && c1==1))) {
03937             /*
03938              * (x relop y)==0
03939              * (x relop y)!=1
03940              */
03941             if (!SIMP_IS_TYPE_FLOATING(OPCODE_desc(inv_op)) ||
03942                 !Force_IEEE_Comparisons) {
03943                SHOW_RULE("x relop y ==0,!=1");
03944                OPCODE inv_relop = OPCODE_make_op(OPCODE_operator(inv_op),
03945                                                  OPCODE_rtype(opc),
03946                                                  OPCODE_desc(inv_op));
03947                r = SIMPNODE_SimpCreateExp2(inv_relop,
03948                                            SIMPNODE_kid0(k0),
03949                                            SIMPNODE_kid1(k0));
03950                SIMP_DELETE(k1);
03951                SIMP_DELETE(k0);
03952             }
03953          } else if (iseq &&
03954                     (c1 == 0) &&
03955                     (OPCODE_operator(firstop)==OPR_BAND) &&
03956                     (SIMPNODE_operator(SIMPNODE_kid0(k0))==OPR_BNOT) &&
03957                     SIMP_Is_Constant(SIMPNODE_kid1(k0))) {
03958             c2 = SIMP_Int_ConstVal(SIMPNODE_kid1(k0));
03959             expr = SIMPNODE_kid0(SIMPNODE_kid0(k0));
03960             if ((c2 != 0) && IS_POWER_OF_2(c2)) {
03961                SHOW_RULE(" (~j & c2) == 0       (j & c2) != 0 if c2 is a power of 2 ");
03962                /* c2 is a power of 2 not equal to 0 */
03963                r = SIMPNODE_SimpCreateExp2(firstop, expr, SIMPNODE_kid1(k0));
03964                r = SIMPNODE_SimpCreateExp2(get_inverse_relop(opc), /* this will be != */
03965                                            r,k1);
03966                SIMP_DELETE(SIMPNODE_kid0(k0));
03967                SIMP_DELETE(k0);
03968                     
03969             }
03970          }
03971 
03972          /* Only do this simplification if the data structure is WHIRL.
03973           * This is so we don't need to make the optimizer reconstruct a lot
03974           * of stuff about the symbols.
03975           */
03976 
03977          // LDA optimizations
03978          else if (c1 == 0 && OPCODE_operator(firstop)==OPR_LDA) {
03979             ST_IDX base_idx;
03980             INT64 offset;
03981             LDA_FLAGS l;
03982             l = get_lda_info(k0,offset,base_idx);
03983             if ((l & LDA_CANNOT_BE_ZERO) != 0) {
03984                /* Symbol cannot be 0 */
03985                /* &x == 0 or &x != 0 */
03986                if (iseq) {
03987                   SHOW_RULE("&x == 0");
03988                   r = SIMP_INTCONST(OPCODE_rtype(opc), 0);
03989                } else {
03990                   SHOW_RULE("&x != 0");
03991                   r = SIMP_INTCONST(OPCODE_rtype(opc), 1);
03992                }
03993                SIMP_DELETE_TREE(k0);
03994                SIMP_DELETE_TREE(k1);
03995             }
03996          }
03997       }
03998 
03999       /* Exit here for code cleanliness if we did something */
04000       if (r) return (r);
04001 
04002 
04003       if ((!ARCH_has_bit_tests) &&
04004           (c1 == 0) &&
04005           (OPCODE_operator(firstop)==OPR_BAND) && 
04006           SIMP_Is_Constant(SIMPNODE_kid1(k0)) &&
04007           (SIMP_Int_ConstVal(SIMPNODE_kid1(k0))==1)) { 
04008         simpnode k0k0 = SIMPNODE_kid0(k0);
04009         if (((SIMPNODE_operator(k0k0) == OPR_LSHR) ||
04010              (SIMPNODE_operator(k0k0) == OPR_ASHR)) &&
04011             SIMP_Is_Constant(SIMPNODE_kid1(k0k0))) {
04012             ty = SIMPNODE_rtype(k0k0);
04013             c2 = MTYPE_bit_size(ty) - 1 - SIMP_Int_ConstVal(SIMPNODE_kid1(k0k0));
04014             SHOW_RULE("(x>>c1)&1 ==,!= 0");
04015             /* This one is useful for bit field extractions on MIPS */
04016             r = SIMPNODE_SimpCreateExp2(MTYPE_bit_size(ty) == 32 ? OPC_I4SHL : OPC_I8SHL,
04017                                         SIMPNODE_kid0(k0k0),SIMP_INTCONST(MTYPE_I4,c2));
04018             if (MTYPE_is_unsigned(ty)) ty = MTYPE_complement(ty);
04019             OPCODE newopc = OPCODE_make_op(iseq ? OPR_GE : OPR_LT,
04020                                            OPCODE_rtype(opc),
04021                                            ty);
04022             r = SIMPNODE_SimpCreateExp2(newopc,r,SIMP_INTCONST(ty,0));
04023             SIMP_DELETE(SIMPNODE_kid1(k0k0));
04024             SIMP_DELETE(k0k0);
04025             SIMP_DELETE(k1);
04026             SIMP_DELETE(SIMPNODE_kid1(k0));
04027             SIMP_DELETE(k0);
04028          }
04029       } else if ((OPCODE_operator(firstop)==OPR_BIOR ||
04030                    OPCODE_operator(firstop)==OPR_BAND) &&
04031                   SIMP_Is_Constant(SIMPNODE_kid1(k0))) {
04032           c2 = SIMP_Int_ConstVal(SIMPNODE_kid1(k0));
04033          /*
04034           *  (j & c2) == c1     0 if (c1 & ~c2) is non-zero
04035           *  (j | c2) == c1     0 if (c2 & ~c1) is non-zero
04036           *  (j & c2) != c1     1 if (c1 & ~c2) is non-zero
04037           *  (j | c2) != c1     1 if (c2 & ~c1) is non-zero
04038           */
04039          if (((c1 & ~c2)!=0 && OPCODE_operator(firstop)==OPR_BAND) ||
04040              ((c2 & ~c1)!=0 && OPCODE_operator(firstop)==OPR_BIOR)) {
04041             if (iseq) {
04042                c2 = 0;
04043             } else {
04044                c2 = 1;
04045             }
04046             SHOW_RULE("(j & c2) == c1 ->0 et al");
04047             r = SIMP_INTCONST(OPCODE_rtype(opc), c2);
04048             SIMP_DELETE_TREE(k0);
04049             SIMP_DELETE_TREE(k1);
04050          }
04051       } else if ((OPCODE_operator(firstop)==OPR_ADD ||
04052                   OPCODE_operator(firstop)==OPR_SUB) &&
04053                  SIMP_Is_Constant(SIMPNODE_kid1(k0))) {
04054          c2 = SIMP_Int_ConstVal(SIMPNODE_kid1(k0));
04055          /*
04056           *  (j +- c2) op c1    j op (c1 -+ c2)
04057           */
04058          if (OPCODE_operator(firstop)==OPR_ADD) {
04059             c2 = -c2;
04060          }
04061          c3 = c1 + c2;
04062          SHOW_RULE("(j -+ c2) == c1");
04063          r = SIMPNODE_SimpCreateExp2(opc,SIMPNODE_kid0(k0),
04064                                      SIMP_INTCONST(OPCODE_rtype(firstop), c3));
04065          SIMP_DELETE(SIMPNODE_kid1(k0));
04066          SIMP_DELETE(k0);
04067          SIMP_DELETE(k1);
04068       } else if (OPCODE_operator(firstop)==OPR_SUB &&
04069                  SIMP_Is_Constant(SIMPNODE_kid0(k0))) {
04070          /*
04071           *  (c2 - j) op c1    j op (c2 - c1)
04072           */
04073          c2 = SIMP_Int_ConstVal(SIMPNODE_kid0(k0));
04074          c3 = c2 - c1;
04075          SHOW_RULE("(j -+ c2) == c1");
04076          r = SIMPNODE_SimpCreateExp2(opc,SIMPNODE_kid1(k0),
04077                                      SIMP_INTCONST(OPCODE_rtype(firstop), c3));
04078          SIMP_DELETE(SIMPNODE_kid0(k0));
04079          SIMP_DELETE(k0);
04080          SIMP_DELETE(k1);
04081       } else if (OPCODE_operator(firstop)==OPR_MPY &&
04082                  SIMP_Is_Constant(SIMPNODE_kid1(k0))) {
04083          /*
04084           *  (j * c2) op c1    j op (c1 / c2), if c2 divides c1
04085           */
04086          c2 = SIMP_Int_ConstVal(SIMPNODE_kid1(k0));
04087          if (c2 != 0) {
04088             if ((c1/c2)*c2 == c1) { 
04089                SHOW_RULE("(j * c2) == c1 divides");
04090                r = SIMPNODE_SimpCreateExp2(opc,SIMPNODE_kid0(k0),
04091                                            SIMP_INTCONST(OPCODE_rtype(firstop), c1/c2));
04092                SIMP_DELETE(SIMPNODE_kid1(k0));
04093                SIMP_DELETE(k0);
04094                SIMP_DELETE(k1);
04095             } else {
04096                SHOW_RULE("(j * c2) == c1 nodivide");
04097                if (iseq) {
04098                   c2 = 0;
04099                } else {
04100                   c2 = 1;
04101                }
04102                r = SIMP_INTCONST(OPCODE_rtype(opc), c2);
04103                SIMP_DELETE_TREE(k0);
04104                SIMP_DELETE_TREE(k1);
04105             }
04106          }
04107       }
04108    }
04109     
04110     
04111    if (!Enable_Cfold_Aggressive || r) return (r);
04112    
04113    
04114    if (!Force_IEEE_Comparisons || SIMP_IS_TYPE_INTEGRAL(OPCODE_desc(opc))) {
04115       if (SIMPNODE_Simp_Compare_Trees(k0,k1)==0) {
04116          if (iseq) {
04117             c1 = 1;
04118             SHOW_RULE("x==x");
04119          } else {
04120             c1 = 0;
04121             SHOW_RULE("x!=x");
04122          }
04123          r = SIMP_INTCONST(OPCODE_rtype(opc), c1);
04124          SIMP_DELETE_TREE(k0);
04125          SIMP_DELETE_TREE(k1);
04126       }
04127    }
04128    if (r) return (r);
04129 
04130    if (OPCODE_operator(firstop)==OPR_LDA &&
04131        SIMPNODE_operator(k1) == OPR_LDA) {
04132       YESNOMAYBE lda_comp;
04133       lda_comp = LDA_Equal_Address(k0,k1);
04134       if (lda_comp == YES) {
04135          SHOW_RULE("&x == &y (true)");
04136          r = SIMP_INTCONST(OPCODE_rtype(opc), iseq);
04137          SIMP_DELETE_TREE(k0);
04138          SIMP_DELETE_TREE(k1);
04139       } else if (lda_comp == NO) {
04140          SHOW_RULE("&x == &y (false)");
04141          r = SIMP_INTCONST(OPCODE_rtype(opc), !iseq);
04142          SIMP_DELETE_TREE(k0);
04143          SIMP_DELETE_TREE(k1);
04144       }        
04145    }
04146    if (r) return (r);
04147 
04148    r = cancel_in_relop(opc, OPCODE_desc(opc), k0, k1);
04149 
04150    return (r);
04151 }
04152 
04153 /*------------------------------------------------ 
04154    Simplifications for <, > <=, >=
04155 
04156 For integers only:
04157 
04158 x >= MIN VALUE          1
04159 x >  MAX VALUE          0
04160 x <= MAX VALUE          1
04161 x <  MIN VALUE          0
04162 
04163 (x +- c2) op c1         x op (c1 -+ c2)
04164 (c2 - x) op c1          x reversed op (c2 - c1)
04165 x*c1 op c2              x newop c3, c3 is something close to c2/c1
04166 
04167 i <= N + -1      i < N  
04168 i > N + -1       i >= N 
04169 
04170 i < N + 1        i <= N 
04171 i >= N + 1       i > N  
04172 
04173 
04174  Aggressive:
04175 x <= x                  1 (For floating types only if !Force_IEEE_Comparisons)
04176 x >= x                  1  "
04177 x < x                   0  "
04178 x > x                   0  "
04179 
04180 -------------------------------------------------*/
04181 
04182 static simpnode  simp_relop(OPCODE opc,
04183                        simpnode k0, simpnode k1, BOOL k0const, BOOL k1const)
04184 {
04185    simpnode r = NULL;
04186    INT64 c1,c2,c3;
04187    TYPE_ID  ty, rtyp;
04188    BOOL   c1min,c1max;
04189    BOOL   add_fold_ok;
04190    OPERATOR  op;
04191    OPCODE  newopc;
04192    
04193    op = OPCODE_operator(opc);
04194    
04195    /* k0const should always be false. If it isn't we messed up
04196       some canonicalizations */
04197    if (k0const) {
04198       return (r);
04199    }
04200 
04201    ty = OPCODE_desc(opc);
04202    rtyp = OPCODE_rtype(opc);
04203 
04204    /* Need to check for trying to move an unsigned ADD through a signed equality */
04205    add_fold_ok = (!SIMP_IS_TYPE_UNSIGNED(ty) || Simp_Fold_Unsigned_Relops) && 
04206       Simp_Unsafe_Relops;
04207    
04208    if (!SIMP_IS_TYPE_UNSIGNED(ty) &&
04209        (SIMP_IS_TYPE_UNSIGNED(SIMPNODE_rtype(k0)) || 
04210         SIMP_IS_TYPE_UNSIGNED(SIMPNODE_rtype(k1)))) {
04211       add_fold_ok = Simp_Fold_Unsigned_Relops;
04212    }
04213    
04214    /* Only do integral types */
04215    if (k1const && SIMP_IS_TYPE_INTEGRAL(ty)) {
04216       c1 = SIMP_Int_ConstVal(k1);
04217       c1min = FALSE;
04218       c1max = FALSE;
04219       switch (ty) {
04220        case MTYPE_I4:
04221          c1min = (c1 == INT32_MIN);
04222          c1max = (c1 == INT32_MAX);
04223          break;
04224        case MTYPE_I8:
04225          c1min = (c1 == 0x8000000000000000LL);
04226          c1max = (c1 == 0x7fffffffffffffffLL);
04227          break;
04228        case MTYPE_U4:
04229          c1min = (c1 == 0);
04230          c1max = (c1 == UINT32_MAX);
04231          break;
04232        case MTYPE_U8:
04233          c1min = (c1 == 0);
04234          c1max = (c1 == 0xffffffffffffffffLL);
04235          break;
04236       }
04237       if (c1min && op == OPR_LT) {
04238          SHOW_RULE("x < MIN");
04239          r = SIMP_INTCONST(rtyp, 0);
04240       } else if (c1min && op == OPR_GE) {
04241          SHOW_RULE("x >= MIN");
04242          r = SIMP_INTCONST(rtyp, 1);
04243       } else if (c1max && op == OPR_GT) {
04244          SHOW_RULE("x > MAX");
04245          r = SIMP_INTCONST(rtyp, 0);
04246       } else if (c1max && op == OPR_LE) {
04247          SHOW_RULE("x <= MAX");
04248          r = SIMP_INTCONST(rtyp, 1);
04249       }
04250       if (r) {
04251          SIMP_DELETE_TREE(k0);
04252          SIMP_DELETE_TREE(k1);
04253          return (r);
04254       }
04255       
04256       
04257       if ((SIMPNODE_operator(k0) == OPR_ADD) &&
04258           SIMP_Is_Constant(SIMPNODE_kid1(k0)) &&
04259           add_fold_ok) {
04260          c2 = SIMP_Int_ConstVal(SIMPNODE_kid1(k0));
04261          if (is_sub_ok(&c3,c1,c2,ty)) {
04262             SHOW_RULE ("j + c2 relop c1");
04263             r = SIMPNODE_SimpCreateExp2(opc,SIMPNODE_kid0(k0),
04264                                         SIMP_INTCONST(ty,c3));
04265             SIMP_DELETE(k1);
04266             SIMP_DELETE(SIMPNODE_kid1(k0));
04267             SIMP_DELETE(k0);
04268          }
04269       } else if (SIMPNODE_operator(k0) == OPR_SUB && add_fold_ok) {
04270          if (SIMP_Is_Constant(SIMPNODE_kid1(k0))) {
04271             c2 = SIMP_Int_ConstVal(SIMPNODE_kid1(k0));
04272             if (is_add_ok(&c3,c1,c2,ty)) {
04273                SHOW_RULE ("j - c2 relop c1");
04274                r = SIMPNODE_SimpCreateExp2(opc,SIMPNODE_kid0(k0),
04275                                            SIMP_INTCONST(ty,c3));
04276                SIMP_DELETE(k1);
04277                SIMP_DELETE(SIMPNODE_kid1(k0));
04278                SIMP_DELETE(k0);
04279             }
04280          } else if (SIMP_Is_Constant(SIMPNODE_kid0(k0))) {
04281             c2 = SIMP_Int_ConstVal(SIMPNODE_kid0(k0));
04282             if (is_sub_ok(&c3,c2,c1,ty)) {
04283                SHOW_RULE ("c2 - j relop c1");
04284                r = SIMPNODE_SimpCreateExp2(OPCODE_commutative_op(opc),SIMPNODE_kid1(k0),
04285                                            SIMP_INTCONST(ty,c3));
04286                SIMP_DELETE(k1);
04287                SIMP_DELETE(SIMPNODE_kid0(k0));
04288                SIMP_DELETE(k0);
04289             }
04290          }
04291       } else if (SIMPNODE_operator(k0)==OPR_MPY && 
04292                  SIMP_Is_Constant(SIMPNODE_kid1(k0)) &&
04293                  add_fold_ok) {
04294          /*
04295           *  (j * c2) relop c1    j newrelop (c1 / c2), if c2 divides c1
04296           */
04297          c2 = SIMP_Int_ConstVal(SIMPNODE_kid1(k0));
04298          if (c2!=0) {
04299             BOOL divides=FALSE;
04300             BOOL sign_c3;
04301             c3 = c1/c2;
04302             sign_c3 = (c1 ^ c2) < 0;
04303             if (c1 == c3*c2) divides = TRUE;
04304             newopc = (c2 > 0) ? opc : OPCODE_commutative_op(opc);
04305             if (divides) {
04306                SHOW_RULE("(j * c2) == c1 (divides)");
04307                r = SIMPNODE_SimpCreateExp2(newopc,SIMPNODE_kid0(k0),
04308                                            SIMP_INTCONST(ty, c3));
04309                SIMP_DELETE(SIMPNODE_kid1(k0));
04310                SIMP_DELETE(k0);
04311                SIMP_DELETE(k1);
04312             } else {
04313                /* tricky case, it doesn't divide evenly */
04314                if ((op == OPR_LT && c1 > 0) ||
04315                    (op == OPR_GT && c1 < 0) ||
04316                    (op == OPR_LE && c1 < 0) ||
04317                    (op == OPR_GE && c1 > 0)) {
04318                   /* we need to move |c3| one greater */
04319                   if (sign_c3) {
04320                      c3 -= 1;
04321                   } else {
04322                      c3 += 1;
04323                   }
04324                }  
04325                SHOW_RULE("(j * c2) == c1 (no divides)");
04326                r = SIMPNODE_SimpCreateExp2(newopc,SIMPNODE_kid0(k0),
04327                                            SIMP_INTCONST(ty, c3));
04328                SIMP_DELETE(SIMPNODE_kid1(k0));
04329                SIMP_DELETE(k0);
04330                SIMP_DELETE(k1);
04331             }
04332          }  
04333       }
04334    }
04335 
04336    if (r) return (r);
04337    
04338    /* 
04339       i <= N + -1        i < N  
04340       i > N + -1         i >= N 
04341       
04342       i < N + 1          i <= N 
04343       i >= N + 1         i > N  
04344 
04345    */
04346 
04347    if (SIMP_IS_TYPE_INTEGRAL(ty) && add_fold_ok &&
04348        SIMPNODE_operator(k1) == OPR_ADD &&
04349        SIMP_Is_Constant(SIMPNODE_kid1(k1))) {
04350       c1 = SIMP_Int_ConstVal(SIMPNODE_kid1(k1));
04351       if (c1==1 && op == OPR_LT) {
04352          SHOW_RULE("i < j+1");
04353          r = SIMPNODE_SimpCreateExp2(OPCODE_make_op(OPR_LE,rtyp,ty),k0,SIMPNODE_kid0(k1));
04354       }
04355       if (c1==1 && op == OPR_GE) {
04356          SHOW_RULE("i >= j+1");
04357          r = SIMPNODE_SimpCreateExp2(OPCODE_make_op(OPR_GT,rtyp,ty),k0,SIMPNODE_kid0(k1));
04358       }
04359       if (c1==-1 && op == OPR_GT) {
04360          SHOW_RULE("i > j-1");
04361          r = SIMPNODE_SimpCreateExp2(OPCODE_make_op(OPR_GE,rtyp,ty),k0,SIMPNODE_kid0(k1));
04362       }
04363       if (c1==-1 && op == OPR_LE) {
04364          SHOW_RULE("i <= j-1");
04365          r = SIMPNODE_SimpCreateExp2(OPCODE_make_op(OPR_LT,rtyp,ty),k0,SIMPNODE_kid0(k1));
04366       }
04367       if (r) {
04368          SIMP_DELETE(SIMPNODE_kid1(k1));
04369          SIMP_DELETE(k1);
04370          return (r);
04371       }
04372    }
04373    /* 
04374       N-1 >= i      N > i       
04375       N-1 < i       N <= i
04376       
04377       N+1 > i       N >= i
04378       N+1 <= i      N < i
04379    */
04380 
04381    if (SIMP_IS_TYPE_INTEGRAL(ty) && add_fold_ok &&
04382        SIMPNODE_operator(k0) == OPR_ADD &&
04383        Simp_Unsafe_Relops &&
04384        SIMP_Is_Constant(SIMPNODE_kid1(k0))) {
04385       c1 = SIMP_Int_ConstVal(SIMPNODE_kid1(k0));
04386       if (c1==-1 && op == OPR_LT) {
04387          SHOW_RULE("j-1 < i");
04388          r = SIMPNODE_SimpCreateExp2(OPCODE_make_op(OPR_LE,rtyp,ty),SIMPNODE_kid0(k0),k1);
04389       }
04390       if (c1==-1 && op == OPR_GE) {
04391          SHOW_RULE("j-1 >= i");
04392          r = SIMPNODE_SimpCreateExp2(OPCODE_make_op(OPR_GT,rtyp,ty),SIMPNODE_kid0(k0),k1);
04393       }
04394       if (c1==1 && op == OPR_GT) {
04395          SHOW_RULE("j+1 > i");
04396          r = SIMPNODE_SimpCreateExp2(OPCODE_make_op(OPR_GE,rtyp,ty),SIMPNODE_kid0(k0),k1);
04397       }
04398       if (c1==1 && op == OPR_LE) {
04399          SHOW_RULE("j+1 <= i");
04400          r = SIMPNODE_SimpCreateExp2(OPCODE_make_op(OPR_LT,rtyp,ty),SIMPNODE_kid0(k0),k1);
04401       }
04402       if (r) {
04403          SIMP_DELETE(SIMPNODE_kid1(k0));
04404          SIMP_DELETE(k0);
04405          return (r);
04406       }
04407    }
04408    
04409    /* Aggressive optimizations */
04410    
04411    if (!Enable_Cfold_Aggressive || r) return (r);
04412 
04413    if (!Force_IEEE_Comparisons || SIMP_IS_TYPE_INTEGRAL(ty)) {
04414       if (SIMPNODE_Simp_Compare_Trees(k0,k1)==0) {
04415          if (op == OPR_LE || op == OPR_GE) {
04416             c1 = 1;
04417             SHOW_RULE("x<=x, x>=x");
04418          } else {
04419             c1 = 0;
04420             SHOW_RULE("x<x, x>x");
04421          }
04422          r = SIMP_INTCONST(rtyp, c1);
04423          SIMP_DELETE_TREE(k0);
04424          SIMP_DELETE_TREE(k1);
04425       }
04426    }
04427 
04428    if (r) return (r);
04429    r = cancel_in_relop(opc, ty, k0, k1);
04430    
04431    return (r);
04432 }
04433 /*================================================================
04434 ================================================================
04435 ================================================================
04436 
04437 End of simplifications
04438 
04439 ================================================================
04440 ================================================================
04441 ================================================================*/
04442 
04443 /*
04444  * This array is a dispatch table to a simplifier function for each
04445  * operator. If an entry is NULL, there is no simplifier for that operator.
04446  * This table is automatically generated by opcode_gen.
04447  */
04448 
04449 #include "wn_simp_ftable.h"
04450 
04451 
04452 /*---------------------------------
04453 Do the transformation 
04454 
04455 SELECT(x, c0, c1) op c2 -> SELECT(x,c0 op c2, c1 op c2)
04456 
04457 -----------------------------------*/
04458 
04459 static simpnode Fold2_Into_Select(OPCODE opc, simpnode k0, simpnode k1)
04460 {
04461    simpnode r = NULL;
04462    simpnode sk1,sk2,kt;
04463    
04464    if (SIMPNODE_operator(k0)==OPR_SELECT) {
04465       sk1 = SIMPNODE_kid1(k0);
04466       sk2 = SIMPNODE_kid(k0,2);
04467       if (SIMP_Is_Constant(sk1) &&
04468           SIMP_Is_Constant(sk2)) {
04469          kt = SIMPNODE_CopyNode(k1);
04470          r = SIMPNODE_SimpCreateExp3(OPC_FROM_OPR(OPR_SELECT,OPCODE_rtype(opc)),
04471                                      SIMPNODE_kid0(k0),
04472                                      SIMPNODE_SimpCreateExp2(opc,sk1,k1),
04473                                      SIMPNODE_SimpCreateExp2(opc,sk2,kt));
04474          SHOW_RULE("SELECT(x,c1,c2) op c0");
04475       }
04476    } else if (SIMPNODE_operator(k1)==OPR_SELECT) {
04477       sk1 = SIMPNODE_kid1(k1);
04478       sk2 = SIMPNODE_kid(k1,2);
04479       if (SIMP_Is_Constant(sk1) &&
04480           SIMP_Is_Constant(sk2)) {
04481          kt = SIMPNODE_CopyNode(k0);
04482          r = SIMPNODE_SimpCreateExp3(OPC_FROM_OPR(OPR_SELECT,OPCODE_rtype(opc)),
04483                                      SIMPNODE_kid0(k1),
04484                                      SIMPNODE_SimpCreateExp2(opc,k0,sk1),
04485                                      SIMPNODE_SimpCreateExp2(opc,kt,sk2));
04486          SHOW_RULE("co op SELECT(x,c1,c2)");
04487       }
04488    }
04489    return (r);
04490 }
04491 
04492 
04493 
04494 static simpnode  SIMPNODE_ConstantFold1(OPCODE opc, simpnode  k0)
04495 {
04496    simpnode  r = NULL;
04497    TCON c0,c1;
04498    BOOL folded;
04499 
04500    if (SIMP_Is_Flt_Constant(k0)) {
04501       c0 = SIMP_Flt_ConstVal(k0);
04502    } else {
04503       c0 = Host_To_Targ(SIMPNODE_rtype(k0),SIMP_Int_ConstVal(k0)); 
04504    }
04505 
04506 #ifndef WN_SIMP_WORKING_ON_WHIRL
04507    // The optimizer doesn't really try very hard to keep the type distinctions
04508    // clear, so we need to make sure we don't remove necessary converts
04509    if (OPCODE_operator(opc) == OPR_CVTL ||
04510        OPCODE_operator(opc) == OPR_PARM ||
04511        (Split_64_Bit_Int_Ops &&
04512         OPCODE_operator(opc) == OPR_CVT && 
04513         MTYPE_bit_size(OPCODE_rtype(opc)) == 64 &&
04514         MTYPE_bit_size(OPCODE_desc(opc)) == 32)) {
04515       /* Not possible to folds this here */
04516      return r;
04517    } else {
04518       c1 = Host_To_Targ(MTYPE_I8,0);     
04519    }
04520 #else
04521    // For WHIRL, we need to get a least a dummy TCON to pass to the folder
04522    c1 = Host_To_Targ(MTYPE_I8,0);     
04523 #endif
04524 
04525    
04526    c0 = Targ_WhirlOp(opc,c0,c1,&folded);
04527    if (folded) {
04528       SHOW_RULE("constant fold 1");
04529       if (SIMP_IS_TYPE_INTEGRAL(TCON_ty(c0))) {
04530          r = SIMP_INTCONST(TCON_ty(c0),Targ_To_Host(c0));
04531       } else {
04532          r = SIMPNODE_CreateFloatconstFromTcon(c0);
04533       }
04534       SIMP_DELETE(k0);
04535    }
04536    return (r);
04537 }
04538 
04539 static simpnode  SIMPNODE_ConstantFold2(OPCODE opc, simpnode  k0, simpnode  k1)
04540 {
04541    simpnode  r = NULL;
04542    TCON c0,c1;
04543    BOOL folded;
04544 
04545    if (SIMP_Is_Flt_Constant(k0)) {
04546       c0 = SIMP_Flt_ConstVal(k0);
04547    } else {
04548       c0 = Host_To_Targ(SIMPNODE_rtype(k0),SIMP_Int_ConstVal(k0)); 
04549    }
04550    if (SIMP_Is_Flt_Constant(k1)) {
04551       c1 = SIMP_Flt_ConstVal(k1);
04552    } else {
04553       c1 = Host_To_Targ(SIMPNODE_rtype(k1),SIMP_Int_ConstVal(k1)); 
04554    }
04555 
04556    c0 = Targ_WhirlOp(opc,c0,c1,&folded);
04557    if (folded) {
04558       SHOW_RULE("constant fold 2");
04559       if (SIMP_IS_TYPE_INTEGRAL(TCON_ty(c0))) {
04560          r = SIMP_INTCONST(TCON_ty(c0),Targ_To_Host(c0));
04561       } else {
04562          r = SIMPNODE_CreateFloatconstFromTcon(c0);
04563       }
04564       SIMP_DELETE(k0);
04565       SIMP_DELETE(k1);
04566    }
04567    return (r);
04568 }
04569 
04570 
04571 
04572 static simpnode SIMPNODE_SimplifyExp2_h(OPCODE opc, simpnode k0, simpnode k1) 
04573 {
04574    BOOL  k0const, k1const;
04575    OPERATOR  op;
04576    OPCODE    canon_opc;
04577    simpnode result=NULL;
04578    
04579    simpnode  (*simp_func)(OPCODE opc, simpnode k0, simpnode k1, 
04580                           BOOL k0const, BOOL k1const);
04581    
04582    if (!SIMPNODE_enable || !OPCODE_is_expression(opc)) return (result);
04583    if (!SIMPNODE_simp_initialized) SIMPNODE_Simplify_Initialize();
04584    
04585    op = OPCODE_operator(opc);
04586    simp_func = simplify_function_table[op];
04587    k0const = SIMP_Is_Constant(k0);
04588    k1const = SIMP_Is_Constant(k1);
04589    
04590    if (k0const && k1const) {
04591       result = SIMPNODE_ConstantFold2(opc, k0, k1);
04592       return (result);
04593    }
04594 
04595    /* Don't swap around MINMAX, DIVREM or the coming XMPY */
04596    /* This fixes PV 442288 and 443473 */
04597    if (op != OPR_MINMAX && op != OPR_DIVREM) {
04598       if (k0const || k1const) {
04599          result = Fold2_Into_Select(opc, k0, k1);
04600          if (result) return (result);
04601       }
04602    }
04603 
04604    if (Simp_Canonicalize) {
04605       /* Simply canonicalization for constants. *******************************
04606          c1 op1 x               x op2 c2             if op1 is one of the following:
04607          op1    op2
04608          --     ---
04609          +,*    +,*
04610          &,|,^  &,|,^
04611          &&,||  &&,||   
04612          MAX,MIN        MAX,MIN
04613          <      >
04614          <=     >=
04615          ==     ==
04616          !=     !=
04617          >=     <=
04618          >      <
04619          *******************************************************************/
04620       if (k0const &&
04621           (canon_opc = OPCODE_commutative_op(opc)) != 0) {
04622          /* Switch things around and rebuild the node */
04623          SHOW_RULE("commute constant operand");
04624          result = SIMPNODE_SimpCreateExp2(canon_opc, k1, k0);
04625          return (result);
04626       }
04627 
04628       /* Canonicalization for non-constants
04629          ----------------------------------
04630          y op1 x                        x op2 y   with op1 and op2 as above
04631          There will be some "shape-like"
04632          order (perhaps the formal number?)
04633          The operation will be commuted if 
04634          y > x in the shape order.
04635          */
04636       if (!k0const && !k1const &&
04637           (canon_opc = OPCODE_commutative_op(opc)) &&
04638           Enable_Cfold_Aggressive) {
04639          if (SIMPNODE_Simp_Compare_Trees(k0,k1) == 1) {
04640             SHOW_RULE("commute operand");
04641             result = SIMPNODE_SimpCreateExp2(canon_opc, k1, k0);
04642             return(result);
04643          }
04644       }
04645 
04646       /********************************** 
04647         simple reassociations:  
04648         ---------------------
04649         (j op c1) op c2         j op (c1 op c2)         op is +,*,&,|,^,MAX,MIN
04650         (a op c1) op c2         a op (c1 op c2)         R:2 op is +,*
04651         (a op c1) op c2         a op (c1 op c2)         op is MAX, MIN
04652         (j op c1) op k          (j op k) op c1          op is +,*,&,|,^,MAX,MIN
04653         (a op c1) op b          (a op b) op c1          R:2 op is +,*
04654         (a op c1) op b          (a op b) op c1          op is MAX, MIN
04655         (j op c1) op (k op c2)  (j op k) op (c1 op c2)  op is +,*,&,|,^,MAX,MIN
04656         (a op c1) op (b op c2)  (a op b) op (c1 op c2)  R:2 op is +,*
04657         (a op c1) op (b op c2)  (a op b) op (c1 op c2)  op is MAX, MIN
04658         
04659         k op (j op c1)          (k op j) op c1          op is +,*,&,|,^,MAX,MIN
04660         b op (a op c1)          (b op a) op c1          R:2 op is +,*
04661         b op (a op c1)          (b op a) op c1          op is MAX, MIN
04662         
04663         **********************************/
04664    
04665       if (is_ok_to_reassociate(opc)) {
04666          if (k1const && (SIMPNODE_opcode(k0) == opc) &&
04667              SIMP_Is_Constant(SIMPNODE_kid1(k0))) {
04668             SHOW_RULE("reassociate 1");
04669             result = SIMPNODE_SimpCreateExp2(opc, SIMPNODE_kid0(k0),
04670                                              SIMPNODE_SimpCreateExp2(opc, SIMPNODE_kid1(k0), k1));
04671             SIMP_DELETE(k0);
04672             return (result);
04673          }
04674       
04675          if (!k1const &&
04676              SIMPNODE_opcode(k0) == opc &&
04677              SIMP_Is_Constant(SIMPNODE_kid1(k0))) {
04678            TY_IDX tas_idx = 0;
04679            simpnode t0;
04680            SHOW_RULE("reassociate 2a");
04681            
04682            // for expr x[a+ct][b] the optimizer
04683            // moves the ct to the rightmost leaf
04684            // need to create a TAS for the inner add node
04685            if(SIMPNODE_operator(k0) == OPR_LDA && 
04686               Type_Is_Shared_Ptr(ST_type(SIMPNODE_st((k0))))) {
04687               tas_idx = ST_type(SIMPNODE_st(k0));
04688            } else  if(SIMPNODE_operator(k1) == OPR_LDA && 
04689                       Type_Is_Shared_Ptr(ST_type(SIMPNODE_st(k1))) ) {
04690              tas_idx = ST_type(SIMPNODE_st(k1));
04691            }
04692            
04693            k1 = SIMPNODE_SimpCreateExp2(opc, SIMPNODE_kid0(k0), k1); 
04694            if (tas_idx) {
04695              OPCODE opc = OPCODE_make_op(OPR_TAS, Pointer_Mtype, MTYPE_V);
04696              t0 = SIMPNODE_SimpCreateExp1(opc, k1);
04697              WN_set_ty((WN*)t0, tas_idx);
04698              k1  = t0;
04699              SHOW_RULE("tas after reassociate2a");
04700            }
04701            result = SIMPNODE_SimpCreateExp2(opc ,k1, SIMPNODE_kid1(k0));
04702            SIMP_DELETE(k0);     
04703             return (result);
04704          }
04705       
04706          if (!k1const &&
04707              SIMPNODE_opcode(k1) == opc &&
04708              SIMP_Is_Constant(SIMPNODE_kid1(k1))) {
04709             SHOW_RULE("reassociate 2b");
04710             result = SIMPNODE_SimpCreateExp2(opc,
04711                                              SIMPNODE_SimpCreateExp2(opc, SIMPNODE_kid0(k1), k0),
04712                                              SIMPNODE_kid1(k1));
04713             SIMP_DELETE(k1);
04714             return (result);
04715          }
04716       
04717          if (SIMPNODE_opcode(k0) == opc &&
04718              SIMPNODE_opcode(k1) == opc &&
04719              SIMP_Is_Constant(SIMPNODE_kid1(k0)) &&
04720              SIMP_Is_Constant(SIMPNODE_kid1(k1))) {
04721          
04722             SHOW_RULE("reassociate 3");
04723             result = SIMPNODE_SimpCreateExp2(opc, SIMPNODE_kid0(k0),SIMPNODE_kid0(k1));
04724             result = SIMPNODE_SimpCreateExp2(opc, result,
04725                                              SIMPNODE_SimpCreateExp2(opc,SIMPNODE_kid1(k0),SIMPNODE_kid1(k1)));
04726             SIMP_DELETE(k0);
04727             SIMP_DELETE(k1);
04728             return (result);
04729          }
04730       }
04731    }  /* Simp_Canonicalize */
04732    if (simp_func) {
04733       result = simp_func(opc, k0, k1, k0const, k1const);
04734    } else {
04735       result = NULL;
04736    }
04737    
04738    return (result);
04739 }
04740 
04741 /* This just calls the above routine. It's done this way to simplify my debugging */
04742 simpnode SIMPNODE_SimplifyExp2(OPCODE opc, simpnode k0, simpnode k1) 
04743 {
04744    simpnode  result;
04745    result = SIMPNODE_SimplifyExp2_h(opc, k0,k1);
04746    SHOW_TREE(opc,k0,k1,result);
04747    return (result);
04748 }
04749    
04750 
04751 simpnode SIMPNODE_SimplifyExp1(OPCODE opc, simpnode k0) 
04752 {
04753    OPERATOR  op;
04754    simpnode result=NULL;
04755    simpnode k1,k2;
04756    
04757    simpnode  (*simp_func)(OPCODE opc, simpnode k0, simpnode k1, 
04758                      BOOL k0const, BOOL k1const);
04759 
04760    if (!SIMPNODE_enable || !OPCODE_is_expression(opc)) return (result);
04761    if (!SIMPNODE_simp_initialized) SIMPNODE_Simplify_Initialize();
04762 
04763    op = OPCODE_operator(opc);
04764 
04765 /* For debugging only */
04766 #undef DEBUG_IGNORE_PARENS
04767 #ifdef DEBUG_IGNORE_PARENS
04768    if (op == OPR_PAREN) return k0;
04769 #endif
04770 
04771 
04772    /* Check for and do the simplification 
04773     * OP (SELECT(X,c1,c2)) ->
04774     * SELECT(X,OP(c1),OP(C2))
04775     */
04776    if (SIMPNODE_operator(k0) == OPR_SELECT && op != OPR_PARM) {
04777       k1 = SIMPNODE_kid1(k0);
04778       k2 = SIMPNODE_kid(k0,2);
04779       /* Check for and do the simplification 
04780        * OP (SELECT(X,c1,c2)) ->
04781        * SELECT(X,OP(c1),OP(C2))
04782        */
04783       if (SIMP_Is_Constant(k1) && SIMP_Is_Constant(k2)) {
04784          result = SIMPNODE_SimpCreateExp3(OPC_FROM_OPR(OPR_SELECT,OPCODE_rtype(opc)),
04785                                           SIMPNODE_kid0(k0),
04786                                           SIMPNODE_SimpCreateExp1(opc,k1),
04787                                           SIMPNODE_SimpCreateExp1(opc,k2));
04788          SHOW_RULE("OP(SELECT(x,c1,c2))");
04789       }
04790    } else {
04791       simp_func = simplify_function_table[op];
04792       if (SIMP_Is_Constant(k0)) {
04793          result = SIMPNODE_ConstantFold1(opc, k0);
04794       } else if (simp_func) {
04795          result = simp_func(opc, k0, NULL, FALSE, FALSE);
04796       } else {
04797          result = NULL;
04798       }
04799    }
04800 
04801    SHOW_TREE(opc,k0,NULL,result);
04802    return (result);
04803 }
04804 
04805 
04806 /*------------------------------------------------ 
04807    Simplifications for CVTL
04808 
04809    CVTL (SELECT(X,c1,c2))           -> SELECT(X,CVTL(C1),CVTL(C2))
04810    CVTL n1(CVTL n2(k0)), n2 <= n1   -> cvtl n2(k0)
04811    CVTL n1(CVTL n2(k0)), n2 > n1    -> cvtl n1(k0)
04812    CVTL n (X & c1)                  -> cvtl n (x) if (1<<n)-1 & c1 = (1<<n)-1
04813    
04814    cvtl n (cvtl n (x) op y)         -> cvtl n (x op y), op is ADD,SUB,MPY,BIOR,BAND,BXOR,SHL
04815    cvtl n (op cvtl n (x) )          -> cvtl n (op x), op is NEG, BNOT
04816    cvtl n (op cvtl n (x) )          -> op cvtl n (x)), op is ABS
04817                                        
04818    
04819 
04820 -------------------------------------------------*/
04821 
04822 
04823 simpnode simp_cvtl(OPCODE opc, INT16 cvtl_bits, simpnode k0)
04824 {
04825    simpnode r=NULL,k1,k2;
04826    TYPE_ID source_ty,dest_ty;
04827    INT16   s_size,d_size,k0_bits;
04828    INT64  cval,mask;
04829    OPERATOR opr0;
04830    
04831    source_ty = SIMPNODE_rtype(k0);
04832    dest_ty = OPCODE_rtype(opc);
04833 
04834    /* Constant fold it */
04835    if (SIMP_Is_Constant(k0)) {
04836       BOOL folded = FALSE;
04837       TCON c0,c1;
04838 #ifndef WN_SIMP_WORKING_ON_WHIRL
04839       if (Split_64_Bit_Int_Ops && 
04840           MTYPE_bit_size(dest_ty) == 64 &&
04841           MTYPE_bit_size(source_ty) == 32) {
04842         // do not fold because cannot change result type to I8/U8 in wopt
04843       }
04844       else 
04845 #endif
04846       {
04847         c0 = Host_To_Targ(source_ty,SIMP_Int_ConstVal(k0));
04848         c1 = Host_To_Targ(MTYPE_I8,cvtl_bits);
04849         c0 = Targ_WhirlOp(opc,c0,c1,&folded);
04850       }
04851       if (folded) {
04852          SHOW_RULE("constant fold cvtl");
04853          r = SIMP_INTCONST(dest_ty,Targ_To_Host(c0));
04854          SIMP_DELETE(k0);
04855          return (r);
04856       }
04857    } else if (SIMPNODE_operator(k0) == OPR_SELECT) {
04858       k1 = SIMPNODE_kid1(k0);
04859       k2 = SIMPNODE_kid(k0,2);
04860       /* Check for and do the simplification 
04861        * CVTL (SELECT(X,c1,c2)) ->
04862        * SELECT(X,CVTL(c1),CVTL(C2))
04863        */
04864       if (SIMP_Is_Constant(k1) || SIMP_Is_Constant(k2) ||
04865           SIMPNODE_opcode(k1) == opc || SIMPNODE_opcode(k2) == opc) {
04866         simpnode t_k1 = SIMPNODE_SimplifyCvtl(opc,cvtl_bits,k1);
04867         simpnode t_k2 = SIMPNODE_SimplifyCvtl(opc,cvtl_bits,k2);
04868         r = SIMPNODE_SimpCreateExp3(OPC_FROM_OPR(OPR_SELECT,OPCODE_rtype(opc)),
04869                                     SIMPNODE_kid0(k0),
04870                                     (t_k1) ? t_k1 : SIMPNODE_SimpCreateCvtl(opc,cvtl_bits,k1),
04871                                     (t_k2) ? t_k2 : SIMPNODE_SimpCreateCvtl(opc,cvtl_bits,k2));
04872 
04873          SHOW_RULE("CVTL(SELECT(x,c1,c2))");
04874       }
04875    } else if (SIMPNODE_opcode(k0) == opc) {
04876       /* CVTL (CVTL) */
04877       k0_bits = SIMPNODE_cvtl_bits(k0);
04878       if (k0_bits <= cvtl_bits) {
04879          SHOW_RULE("CVTL(n1,CVTL(n2,k0)), n2 <= n1");
04880          r = k0;
04881       } else {
04882          SHOW_RULE("CVTL(n1,CVTL(n2,k0)), n2 > n1");
04883          r = SIMPNODE_SimpCreateCvtl(opc,cvtl_bits,SIMPNODE_kid0(k0));
04884       }
04885    } else if (SIMPNODE_operator(k0) == OPR_BAND &&
04886               SIMP_Is_Constant(SIMPNODE_kid1(k0))) {
04887       cval = SIMP_Int_ConstVal(SIMPNODE_kid1(k0));
04888       mask = (1ll << cvtl_bits) - 1ll;
04889       if ((mask & cval) == mask) {
04890          SHOW_RULE("cvtl(x&c1) -> cvtl(x)");
04891          r = SIMPNODE_SimpCreateCvtl(opc,cvtl_bits,SIMPNODE_kid0(k0));
04892          SIMP_DELETE(SIMPNODE_kid1(k0));
04893          SIMP_DELETE(k0);
04894       }
04895    } else {
04896       
04897       s_size = SIMP_TYPE_SIZE(source_ty);
04898       d_size = SIMP_TYPE_SIZE(dest_ty);
04899       
04900       if (s_size == d_size && s_size == cvtl_bits) {
04901          SHOW_RULE("CVTL(n, k0) -> k0");
04902          r = k0;
04903       }
04904    }
04905 
04906    if (r) return (r);
04907 
04908    /* A few more CVTL simplifcations (from PV 364316):
04909       ALso, if we see CVTL(BINOP(CVTL(X),Y)), I believe we can turn this into
04910       CVTL(BINOP(X,Y)) for BINOPs BAND, BIOR, BXOR, ADD, SUB, MPY and SHL, because
04911       these operations always push information toward higher bits. We can also do
04912       CVTL(BNOT(CVTL(X))). DIV, MOD, LSHR and ASHR can't be done this way, because
04913       they bring in information from the higher bits. 
04914       */
04915    
04916    opr0 = SIMPNODE_operator(k0);
04917    switch (opr0) {
04918     case OPR_NEG:
04919     case OPR_BNOT:
04920     case OPR_LNOT:
04921       k1 = SIMPNODE_kid0(k0);
04922       if (SIMPNODE_opcode(k1) == opc &&
04923           SIMPNODE_cvtl_bits(k1) >= cvtl_bits) {
04924          SHOW_RULE("CVTL n (op CVTL n (X))");
04925          r = SIMPNODE_SimpCreateCvtl(opc,cvtl_bits,
04926                                      SIMPNODE_SimpCreateExp1(SIMPNODE_opcode(k0),
04927                                                              SIMPNODE_kid0(k1)));
04928          SIMP_DELETE(k1);
04929          SIMP_DELETE(k0);
04930       } else if (opr0 == OPR_LNOT) {
04931          /* Since this returns 0 or 1, we don't need to CVTL it */
04932          r = k0;
04933       }
04934       break;
04935 
04936 #if 0 // this rule is wrong because of the number 0x8000 in 16 bits;
04937       // ABS(I4CVTL16(0x8000)) == 0x8000, and I4CVTL(0x8000) == 0xffff8000
04938       // i.e. the negation of MININT is itself 
04939     case OPR_ABS:
04940        k1 = SIMPNODE_kid0(k0);
04941        if (SIMPNODE_opcode(k1) == opc &&
04942            SIMPNODE_cvtl_bits(k1) == cvtl_bits) {
04943           SHOW_RULE("CVTL n (ABS CVTL n (X))");
04944           r = k0;
04945        }
04946        break;
04947 #endif
04948 
04949     case OPR_LT:
04950     case OPR_LE:
04951     case OPR_GT:
04952     case OPR_GE:
04953     case OPR_EQ:
04954     case OPR_NE:
04955     case OPR_LIOR:
04956     case OPR_LAND:
04957       /* Since these return 0 or 1, we don't need to CVTL them at all */
04958       r = k0;
04959       break;
04960 
04961     case OPR_ADD:
04962     case OPR_SUB:
04963     case OPR_MPY:
04964     case OPR_BIOR:
04965     case OPR_BXOR:
04966     case OPR_BAND:
04967     case OPR_SHL:
04968       k1 = SIMPNODE_kid0(k0);
04969       k2 = SIMPNODE_kid1(k0);
04970       if (SIMPNODE_opcode(k1) == opc &&
04971           SIMPNODE_cvtl_bits(k1) >= cvtl_bits && 
04972           SIMPNODE_opcode(k2) == opc &&
04973           SIMPNODE_cvtl_bits(k2) >= cvtl_bits) {
04974          SHOW_RULE("CVTL n (CVTL n (X) op CVTL(y))");
04975          r = SIMPNODE_SimpCreateCvtl(opc,cvtl_bits,
04976                                      SIMPNODE_SimpCreateExp2(SIMPNODE_opcode(k0),
04977                                                              SIMPNODE_kid0(k1),
04978                                                              SIMPNODE_kid0(k2)));
04979          SIMP_DELETE(k2);
04980          SIMP_DELETE(k1);
04981          SIMP_DELETE(k0);
04982       } else if (SIMPNODE_opcode(k1) == opc &&
04983                  SIMPNODE_cvtl_bits(k1) >= cvtl_bits) {
04984          SHOW_RULE("CVTL n (CVTL n (X) op y)");
04985          r = SIMPNODE_SimpCreateCvtl(opc,cvtl_bits,
04986                                      SIMPNODE_SimpCreateExp2(SIMPNODE_opcode(k0),
04987                                                              SIMPNODE_kid0(k1),
04988                                                              k2));
04989          SIMP_DELETE(k1);
04990          SIMP_DELETE(k0);
04991       } else if (SIMPNODE_opcode(k2) == opc &&
04992                  SIMPNODE_cvtl_bits(k2) >= cvtl_bits && opr0 != OPR_SHL) {
04993          SHOW_RULE("CVTL n (X op CVTL n (y))");
04994          r = SIMPNODE_SimpCreateCvtl(opc,cvtl_bits,
04995                                      SIMPNODE_SimpCreateExp2(SIMPNODE_opcode(k0),
04996                                                              k1,
04997                                                              SIMPNODE_kid0(k2)));
04998          SIMP_DELETE(k2);
04999          SIMP_DELETE(k0);
05000       }
05001       break;
05002     default:
05003       break;
05004    }
05005    return (r);
05006 }      
05007 
05008 simpnode SIMPNODE_SimplifyCvtl(OPCODE opc, INT16 cvtl_bits, simpnode k0) 
05009 {
05010    simpnode result = NULL;
05011    if (!SIMPNODE_enable) return (result);
05012    if (!SIMPNODE_simp_initialized) SIMPNODE_Simplify_Initialize();
05013    
05014    result = simp_cvtl(opc,cvtl_bits,k0);
05015 
05016    if (result) {
05017       SHOW_TREE(opc,k0,(simpnode) cvtl_bits, result);
05018    }
05019    return (result);
05020 }
05021 
05022 
05023 /*------------------------------------------------ 
05024    Simplifications for SELECT
05025 
05026    FALSE ? x : y        y
05027    TRUE  ? x : y        x
05028    x ? y : y            y
05029    boolexpr ? 1 : 0     boolexpr
05030    x ? 1 : 0            NE(x,0)
05031    x ? 0 : 1            NOT(x)
05032 
05033 -------------------------------------------------*/
05034 
05035 
05036 simpnode SIMPNODE_SimplifyExp3(OPCODE opc, simpnode k0, simpnode k1, 
05037                                simpnode k2) 
05038 {
05039    simpnode r = NULL;
05040    OPCODE   k0op;
05041    
05042    if (!SIMPNODE_enable) return (r);
05043    if (!SIMPNODE_simp_initialized) SIMPNODE_Simplify_Initialize();
05044 
05045    /* Currently, this only simplifies SELECT */
05046    if (OPCODE_operator(opc) != OPR_SELECT && OPCODE_operator(opc) != OPR_CSELECT) return (r);
05047    
05048    k0op = SIMPNODE_opcode(k0);
05049    if (SIMP_Is_Int_Constant(k0)) {
05050       if (SIMP_Int_ConstVal(k0) == 0) {
05051          SHOW_RULE("SELECT(FALSE,x,y)");
05052          r = k2;
05053          SIMP_DELETE_TREE(k1);
05054       } else {
05055          SHOW_RULE("SELECT(TRUE,x,y)");
05056          r = k1;
05057          SIMP_DELETE_TREE(k2);
05058       }
05059       SIMP_DELETE_TREE(k0);
05060    } else if (SIMP_Is_Int_Constant(k1) &&
05061               SIMP_Is_Int_Constant(k2) &&
05062               SIMPNODE_operator(k0) != OPR_CAND &&
05063               SIMPNODE_operator(k0) != OPR_CIOR) {
05064       if (SIMP_Int_ConstVal(k1) == 1 && 
05065           SIMP_Int_ConstVal(k2) == 0) {
05066          if (get_inverse_relop(k0op) != OPCODE_UNKNOWN ||
05067              OPCODE_rtype(k0op) == MTYPE_B) {
05068             SHOW_RULE("SELECT(boolexpr,1,0)");
05069             r = k0;
05070             SIMP_DELETE_TREE(k1);
05071             SIMP_DELETE_TREE(k2);
05072          } else {
05073             TYPE_ID k0_rtype = OPCODE_rtype(k0op);
05074             SHOW_RULE("SELECT(expr,1,0)");
05075             r = SIMPNODE_SimpCreateExp2(OPCODE_make_op(OPR_NE, k0_rtype, k0_rtype),
05076                                         k0, SIMP_INTCONST(k0_rtype, 0));
05077             SIMP_DELETE_TREE(k1);
05078             SIMP_DELETE_TREE(k2);
05079          }
05080       } else if (SIMP_Int_ConstVal(k1) == 0 && 
05081                  SIMP_Int_ConstVal(k2) == 1) {
05082          SHOW_RULE("SELECT(expr,0,1)");
05083          r = SIMPNODE_SimpCreateExp1(OPC_FROM_OPR(OPR_LNOT,OPCODE_rtype(k0op)),k0);
05084          SIMP_DELETE_TREE(k1);
05085          SIMP_DELETE_TREE(k2);
05086       }
05087       if (r) {
05088         const TYPE_ID opc_rtype = OPCODE_rtype(opc);
05089         if (OPCODE_rtype(k0op) == MTYPE_B && opc_rtype != MTYPE_B)
05090           r = SIMPNODE_SimpCreateExp1(
05091                         OPCODE_make_op(OPR_CVT, opc_rtype, MTYPE_B), r);
05092         return (r);
05093       }
05094    }
05095    if (r == NULL && Enable_Cfold_Aggressive) {
05096       if (SIMPNODE_Simp_Compare_Trees(k1,k2)==0) {
05097          SHOW_RULE("SELECT(x,y,y)");
05098          r = k1;
05099          SIMP_DELETE_TREE(k0);
05100          SIMP_DELETE_TREE(k2);
05101       }
05102    }
05103 
05104    return (r);
05105 }
05106 
05107 
05108 /*----------------------------------------------------------
05109   Simplifications for intrinsics
05110 
05111   Currently, only constant folding is attempted
05112 
05113 ------------------------------------------------------------*/
05114 #define MAX_INTRINSIC_ARGS 6
05115 simpnode SIMPNODE_SimplifyIntrinsic(OPCODE opc, UINT32 intrinsic, INT32 n, simpnode k[])
05116 {
05117    simpnode r = NULL;
05118    TCON c[MAX_INTRINSIC_ARGS],c0;
05119    BOOL allconst;
05120    BOOL folded;
05121    INT i;
05122    INT64  ival;
05123    TYPE_ID  ty;
05124    simpnode kid;
05125    
05126    if (!SIMPNODE_enable) return (r);
05127    if (!SIMPNODE_simp_initialized) SIMPNODE_Simplify_Initialize();
05128 
05129    if (OPCODE_operator(opc) != OPR_INTRINSIC_OP) return(r);
05130 
05131    /* It's an intrinsic */
05132    if (n > MAX_INTRINSIC_ARGS) return (r);
05133    allconst = TRUE;
05134    for (i=0; (i < n) && allconst; i++) {
05135       kid = k[i];
05136       if (SIMPNODE_operator(kid) == OPR_PARM) {
05137          kid = SIMPNODE_kid0(kid);
05138       }
05139       if (SIMP_Is_Constant(kid)) {
05140          if (SIMP_Is_Flt_Constant(kid)) {
05141             c[i] = SIMP_Flt_ConstVal(kid);
05142          } else {
05143             c[i] = Host_To_Targ(SIMPNODE_rtype(kid),SIMP_Int_ConstVal(kid)); 
05144          }
05145       } else {
05146          allconst = FALSE;
05147       }
05148    }
05149    if (allconst) {
05150       SHOW_RULE("intrinsic fold");
05151       c0 = Targ_IntrinsicOp(intrinsic,c,&folded);
05152       if (folded) {
05153          if (SIMP_IS_TYPE_INTEGRAL(TCON_ty(c0))) {
05154             ival = Targ_To_Host(c0);
05155             ty = TCON_ty(c0);
05156             /* May need to promote type to I4/U4 */
05157             if (ty == MTYPE_I1 || ty == MTYPE_I2) {
05158                ty = MTYPE_I4;
05159             } else if (ty == MTYPE_U1 || ty == MTYPE_U2) {
05160                ty = MTYPE_U4;
05161             }
05162             r = SIMP_INTCONST(ty,ival);
05163          } else {
05164             r = SIMPNODE_CreateFloatconstFromTcon(c0);
05165          }
05166 
05167          if (n >= 2) {
05168            SHOW_TREE(opc,k[0],k[1],r);
05169          } else {
05170            SHOW_TREE(opc,k[0],NULL,r);
05171          }
05172 
05173          for (i=0; i<n; i++) {
05174             SIMP_DELETE(k[i]);
05175          }
05176       }
05177    }
05178    return (r);
05179 }
05180 
05181 
05182 
05183 #ifdef WN_SIMP_WORKING_ON_WHIRL
05184 /*----------------------------------------------------------
05185   Simplifications for ILOADS
05186 
05187   Currently, only constant folding is attempted
05188 
05189 ------------------------------------------------------------*/
05190 
05191 simpnode SIMPNODE_SimplifyIload(OPCODE opc, WN_OFFSET offset, 
05192                                 TY_IDX ty, UINT field_id, TY_IDX load_addr_ty,
05193                                 simpnode addr) 
05194 {
05195    simpnode r = NULL;
05196    INT64 lda_offset,new_offset;
05197    
05198 
05199    if (!SIMPNODE_enable || !WN_Simp_Fold_ILOAD) return (r);
05200    if (!SIMPNODE_simp_initialized) SIMPNODE_Simplify_Initialize();
05201 
05202    /* Look for ILOAD(LDA) */
05203    if (SIMPNODE_operator(addr) == OPR_LDA
05204 #ifndef TARG_MIPS // if LDA is function pointer, can fold only for MIPS ABI
05205        && ST_class(SIMPNODE_st_idx(addr)) != CLASS_FUNC
05206 #endif
05207        ) {
05208       lda_offset = SIMPNODE_lda_offset(addr);
05209       if (is_add_ok(&new_offset,offset,lda_offset,MTYPE_I4)) {
05210          SHOW_RULE("ILOAD(LDA)->LDID");
05211          r = WN_CreateLdid(OPCODE_operator(opc) == OPR_ILOAD ? OPR_LDID : OPR_LDBITS,
05212                            OPCODE_rtype(opc),
05213                            OPCODE_desc(opc),
05214                            new_offset,
05215                            SIMPNODE_st_idx(addr),
05216                            ty,
05217                            field_id);
05218          SIMP_DELETE(addr);
05219       }
05220    }
05221    return (r);
05222 }
05223 
05224 simpnode SIMPNODE_SimplifyIstore(OPCODE opc, WN_OFFSET offset, 
05225                                  TY_IDX ty, UINT field_id, simpnode value,
05226                                  simpnode addr)  
05227 {
05228    simpnode r = NULL;
05229    INT64 lda_offset,new_offset;
05230    TY_IDX pointed;
05231 
05232 
05233    if (!SIMPNODE_enable || !WN_Simp_Fold_ILOAD) return (r);
05234    if (!SIMPNODE_simp_initialized) SIMPNODE_Simplify_Initialize();
05235 
05236    /* Look for ISTORE(LDA) */
05237    if (SIMPNODE_operator(addr) == OPR_LDA) {
05238       lda_offset = SIMPNODE_lda_offset(addr);
05239       if (is_add_ok(&new_offset,offset,lda_offset,MTYPE_I4)) {
05240          SHOW_RULE("ISTORE(LDA)->STID");
05241          pointed = TY_pointed(ty);
05242          DevAssert(pointed, ("TY_pointed of ISTORE type is NULL"));
05243          r = WN_CreateStid(OPCODE_operator(opc) == OPR_ISTORE ? OPR_STID : OPR_STBITS,
05244                            OPCODE_rtype(opc),
05245                            OPCODE_desc(opc),
05246                            new_offset,
05247                            SIMPNODE_st_idx(addr),
05248                            pointed,
05249                            value,
05250                            field_id);
05251          SIMP_DELETE(addr);
05252       }
05253    }
05254    return (r);
05255 }
05256 
05257 // fzhao
05258 
05259 simpnode SIMPNODE_SimplifyPstore(OPCODE opc, WN_OFFSET offset,
05260                                  TY_IDX ty, UINT field_id, simpnode value,
05261                                  simpnode addr)
05262 {
05263    simpnode r = NULL;
05264    INT64 lda_offset,new_offset;
05265    TY_IDX pointed;
05266 
05267 
05268    if (!SIMPNODE_enable || !WN_Simp_Fold_ILOAD) return (r);
05269    if (!SIMPNODE_simp_initialized) SIMPNODE_Simplify_Initialize();
05270 
05271    /* Look for PSTORE(LDA) */
05272    if (SIMPNODE_operator(addr) == OPR_LDA) {
05273       lda_offset = SIMPNODE_lda_offset(addr);
05274       if (is_add_ok(&new_offset,offset,lda_offset,MTYPE_I4)) {
05275          SHOW_RULE("PSTORE(LDA)->PSTID");
05276          pointed = TY_pointed(ty);
05277          DevAssert(pointed, ("TY_pointed of PSTORE type is NULL"));
05278   r = WN_CreatePStid(OPCODE_operator(opc) == OPR_PSTORE ? OPR_PSTID : OPR_STBITS,
05279                            OPCODE_rtype(opc),
05280                            OPCODE_desc(opc),
05281                            new_offset,
05282                            SIMPNODE_st_idx(addr),
05283                            pointed,
05284                            value,
05285                            field_id);
05286          SIMP_DELETE(addr);
05287       }
05288    }
05289    return (r);
05290 }
05291 #endif
05292 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines