Open64 (mfef90, whirl2f, and IR tools)
TAG: version-openad; SVN changeset: 916
|
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