00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060 #ifdef USE_PCH
00061 #include "opt_pch.h"
00062 #endif // USE_PCH
00063 #pragma hdrstop
00064
00065
00066 #ifdef _KEEP_RCS_ID
00067 #define opt_combine_CXX "opt_combine.cxx"
00068 static char *rcs_id = opt_combine_CXX"$Revision: 1.8 $";
00069 #endif
00070
00071 #include <sys/types.h>
00072 #include "defs.h"
00073 #include "config.h"
00074 #include "config_opt.h"
00075 #include "mempool.h"
00076 #include "tracing.h"
00077 #include "opt_base.h"
00078
00079 #include "wn.h"
00080 #include "wutil.h"
00081 #include "opt_config.h"
00082 #include "opt_defs.h"
00083
00084 #include "opt_combine.h"
00085 #include "betarget.h"
00086
00087
00088
00089
00090
00091
00092 static BOOL
00093 Combine_div_operator( WN *old_wn, WN **new_wn, OPCODE old_wn_opc )
00094 {
00095 Is_True( OPCODE_operator(old_wn_opc) == OPR_DIV,
00096 ("Combine_div_operator: bad op: %s", OPCODE_name(old_wn_opc)) );
00097
00098 const MTYPE rtype = OPCODE_rtype(old_wn_opc);
00099 const MTYPE desc = OPCODE_desc(old_wn_opc);
00100
00101 #ifdef TARG_X8664 // Bug 1960
00102 if (old_wn_opc == OPC_V16F8DIV || old_wn_opc == OPC_V16C4DIV)
00103 return FALSE;
00104
00105 #endif
00106 if ( MTYPE_is_float(rtype) || MTYPE_is_complex(rtype) ) {
00107
00108
00109
00110
00111
00112
00113
00114 if ( Div_Split_Allowed ) {
00115 const OPCODE recip_opc = OPCODE_make_op(OPR_RECIP,rtype,desc);
00116 WN *recip = WN_CreateExp1(recip_opc, WN_kid(old_wn,1));
00117 const OPCODE mpy_opc = OPCODE_make_op(OPR_MPY,rtype,desc);
00118 WN *mpy = WN_CreateExp2(mpy_opc, WN_kid0(old_wn), recip);
00119 *new_wn = mpy;
00120 return TRUE;
00121 }
00122 }
00123
00124 else if ( WOPT_Enable_DIVREM && MTYPE_is_integral(rtype) &&
00125 ! (WN_operator_is(WN_kid1(old_wn), OPR_INTCONST) &&
00126 Can_Do_Fast_Divide(MTYPE_I4, WN_const_val(WN_kid1(old_wn))))) {
00127
00128
00129
00130
00131 const OPCODE divrem_opc = OPCODE_make_op(OPR_DIVREM,rtype,desc);
00132 WN *divrem = WN_CreateExp2(divrem_opc, WN_kid0(old_wn),WN_kid1(old_wn));
00133 const OPCODE divpart_opc = OPCODE_make_op(OPR_DIVPART,rtype,desc);
00134 WN *divpart = WN_CreateExp1(divpart_opc, divrem);
00135 *new_wn = divpart;
00136 return TRUE;
00137 }
00138
00139
00140 return FALSE;
00141 }
00142
00143
00144
00145
00146
00147 static BOOL
00148 Combine_intrinsic_operator( WN *old_wn, WN **new_wn, OPCODE old_wn_opc )
00149 {
00150 Is_True( OPCODE_operator(old_wn_opc) == OPR_INTRINSIC_OP,
00151 ("Combine_intrinsic_operator: bad op: %s", OPCODE_name(old_wn_opc)) );
00152
00153 const MTYPE rtype = OPCODE_rtype(old_wn_opc);
00154 const MTYPE desc = OPCODE_desc(old_wn_opc);
00155 const INTRINSIC intr = (INTRINSIC)WN_intrinsic(old_wn);
00156 OPCODE new_intr_opc;
00157 INTRINSIC new_intr;
00158 OPCODE new_complex;
00159
00160 switch ( intr ) {
00161
00162
00163
00164
00165 case INTRN_F4SIN:
00166 new_intr_opc = OPC_C4INTRINSIC_OP;
00167 new_intr = INTRN_F4CIS; new_complex = OPC_F4IMAGPART;
00168 goto handle_sin;
00169 case INTRN_F8SIN:
00170 new_intr_opc = OPC_C8INTRINSIC_OP;
00171 new_intr = INTRN_F8CIS; new_complex = OPC_F8IMAGPART;
00172 goto handle_sin;
00173 case INTRN_FQSIN:
00174 new_intr_opc = OPC_CQINTRINSIC_OP;
00175 new_intr = INTRN_FQCIS; new_complex = OPC_FQIMAGPART;
00176 {
00177 handle_sin:
00178 if (CIS_Allowed) {
00179 WN *intr_wn = WN_Create_Intrinsic( new_intr_opc, new_intr, 1,
00180 &WN_kid0(old_wn) );
00181 WN *imag = WN_CreateExp1( new_complex, intr_wn );
00182 *new_wn = imag;
00183 return TRUE;
00184 } else
00185 return FALSE;
00186 }
00187
00188
00189
00190
00191 case INTRN_F4COS:
00192 new_intr_opc = OPC_C4INTRINSIC_OP;
00193 new_intr = INTRN_F4CIS; new_complex = OPC_F4REALPART;
00194 goto handle_cos;
00195 case INTRN_F8COS:
00196 new_intr_opc = OPC_C8INTRINSIC_OP;
00197 new_intr = INTRN_F8CIS; new_complex = OPC_F8REALPART;
00198 goto handle_cos;
00199 case INTRN_FQCOS:
00200 new_intr_opc = OPC_CQINTRINSIC_OP;
00201 new_intr = INTRN_FQCIS; new_complex = OPC_FQREALPART;
00202 {
00203 handle_cos:
00204 if (CIS_Allowed) {
00205 WN *intr_wn = WN_Create_Intrinsic( new_intr_opc, new_intr, 1,
00206 &WN_kid0(old_wn) );
00207 WN *real = WN_CreateExp1( new_complex, intr_wn );
00208 *new_wn = real;
00209 return TRUE;
00210 } else
00211 return FALSE;
00212 }
00213
00214 }
00215
00216
00217 return FALSE;
00218 }
00219
00220
00221
00222
00223
00224
00225
00226
00227 static BOOL
00228 Combine_minmax_operator( WN *old_wn, WN **new_wn, OPCODE old_wn_opc )
00229 {
00230 OPCODE minmax_part;
00231
00232 if ( ! WOPT_Enable_MINMAX )
00233 return FALSE;
00234
00235 const MTYPE rtype = OPCODE_rtype(old_wn_opc);
00236 const MTYPE desc = OPCODE_desc(old_wn_opc);
00237
00238
00239 if ( rtype == MTYPE_FQ )
00240 return FALSE;
00241
00242 switch ( OPCODE_operator(old_wn_opc) ) {
00243 case OPR_MIN:
00244 minmax_part = OPCODE_make_op(OPR_MINPART,rtype,desc);
00245 break;
00246 case OPR_MAX:
00247 minmax_part = OPCODE_make_op(OPR_MAXPART,rtype,desc);
00248 break;
00249 default:
00250 FmtAssert( FALSE,
00251 ("Combine_minmax_operator: bad operator") );
00252 return FALSE;
00253 }
00254
00255 const OPCODE minmax_opc = OPCODE_make_op(OPR_MINMAX,rtype,desc);
00256 WN *minmax = WN_CreateExp2(minmax_opc, WN_kid0(old_wn),WN_kid1(old_wn));
00257 WN *part = WN_CreateExp1(minmax_part, minmax);
00258 *new_wn = part;
00259 return TRUE;
00260 }
00261
00262
00263
00264
00265
00266 static BOOL
00267 Combine_rem_operator( WN *old_wn, WN **new_wn, OPCODE old_wn_opc )
00268 {
00269 Is_True( OPCODE_operator(old_wn_opc) == OPR_REM,
00270 ("Combine_rem_operator: bad op: %s", OPCODE_name(old_wn_opc)) );
00271
00272 const MTYPE rtype = OPCODE_rtype(old_wn_opc);
00273 const MTYPE desc = OPCODE_desc(old_wn_opc);
00274
00275 #if defined (TARG_SL)
00276 if ( WOPT_Enable_DIVREM && MTYPE_is_integral(rtype) &&
00277 ! (WN_operator_is(WN_kid1(old_wn), OPR_INTCONST) &&
00278 Can_Do_Fast_Remainder(MTYPE_I4, WN_const_val(WN_kid1(old_wn))))) {
00279 #else
00280 if ( WOPT_Enable_DIVREM && MTYPE_is_integral(rtype) ) {
00281 #endif
00282
00283
00284
00285 const OPCODE divrem_opc = OPCODE_make_op(OPR_DIVREM,rtype,desc);
00286 WN *divrem = WN_CreateExp2(divrem_opc, WN_kid0(old_wn),WN_kid1(old_wn));
00287 const OPCODE rempart_opc = OPCODE_make_op(OPR_REMPART,rtype,desc);
00288 WN *rempart = WN_CreateExp1(rempart_opc, divrem);
00289 *new_wn = rempart;
00290 return TRUE;
00291 }
00292
00293
00294 return FALSE;
00295 }
00296
00297
00298
00299
00300
00301
00302
00303
00304 extern BOOL
00305 Combine_Operations( WN *old_wn, WN **new_wn )
00306 {
00307 const OPCODE old_wn_opc = WN_opcode(old_wn);
00308 const OPERATOR old_wn_opr = OPCODE_operator(old_wn_opc);
00309
00310 switch ( old_wn_opr ) {
00311
00312 case OPR_DIV:
00313 return Combine_div_operator( old_wn, new_wn, old_wn_opc );
00314
00315 case OPR_INTRINSIC_OP:
00316 return Combine_intrinsic_operator( old_wn, new_wn, old_wn_opc );
00317
00318 case OPR_MAX:
00319 case OPR_MIN:
00320 return Combine_minmax_operator( old_wn, new_wn, old_wn_opc );
00321
00322 case OPR_REM:
00323 return Combine_rem_operator( old_wn, new_wn, old_wn_opc );
00324
00325 }
00326
00327 return FALSE;
00328 }
00329
00330
00331
00332
00333
00334 static BOOL
00335 Uncombine_mpy_operator( WN *old_wn, WN **new_wn, OPCODE old_wn_opc )
00336 {
00337 Is_True( OPCODE_operator(old_wn_opc) == OPR_MPY,
00338 ("Uncombine_mpy_operator: bad op: %s", OPCODE_name(old_wn_opc)) );
00339
00340 WN *kid1 = WN_kid1(old_wn);
00341 const OPCODE kid1_opc = WN_opcode(kid1);
00342 const OPERATOR kid1_opr = OPCODE_operator(kid1_opc);
00343
00344 #ifdef KEY
00345 if (Recip_Allowed)
00346 return FALSE;
00347 #endif
00348
00349 if ( kid1_opr == OPR_RECIP ) {
00350
00351
00352
00353 const OPCODE div_opc = OPCODE_make_op(OPR_DIV,
00354 OPCODE_rtype(kid1_opc),OPCODE_desc(kid1_opc) );
00355 WN *div = WN_CreateExp2(div_opc, WN_kid0(old_wn), WN_kid0(kid1));
00356 *new_wn = div;
00357 return TRUE;
00358 }
00359
00360 WN *kid0 = WN_kid0(old_wn);
00361 const OPCODE kid0_opc = WN_opcode(kid0);
00362 const OPERATOR kid0_opr = OPCODE_operator(kid0_opc);
00363
00364 if ( kid0_opr == OPR_RECIP ) {
00365
00366
00367
00368 const OPCODE div_opc = OPCODE_make_op(OPR_DIV,
00369 OPCODE_rtype(kid0_opc),OPCODE_desc(kid0_opc) );
00370 WN *div = WN_CreateExp2(div_opc, WN_kid1(old_wn), WN_kid0(kid0));
00371 *new_wn = div;
00372 return TRUE;
00373 }
00374
00375
00376 return FALSE;
00377 }
00378
00379
00380
00381
00382
00383 static BOOL
00384 Uncombine_divrempart_operator(WN *old_wn,WN **new_wn,OPCODE old_wn_opc)
00385 {
00386 const OPERATOR old_wn_opr = OPCODE_operator(old_wn_opc);
00387
00388 Is_True( old_wn_opr == OPR_DIVPART || old_wn_opr == OPR_REMPART,
00389 ("Uncombine_divrempart_operator: bad op: %s", OPCODE_name(old_wn_opc)) );
00390
00391 WN *kid0 = WN_kid0(old_wn);
00392 const OPCODE kid0_opc = WN_opcode(kid0);
00393 const OPERATOR kid0_opr = OPCODE_operator(kid0_opc);
00394
00395 if ( kid0_opr == OPR_DIVREM ) {
00396
00397
00398
00399 const OPCODE divrem_opc = old_wn_opr == OPR_DIVPART ?
00400 OPCODE_make_op(OPR_DIV,
00401 OPCODE_rtype(kid0_opc),OPCODE_desc(kid0_opc) ):
00402 OPCODE_make_op(OPR_REM,
00403 OPCODE_rtype(kid0_opc),OPCODE_desc(kid0_opc) );
00404 WN *divrem = WN_CreateExp2(divrem_opc, WN_kid0(kid0),WN_kid1(kid0));
00405 *new_wn = divrem;
00406 return TRUE;
00407 }
00408
00409
00410 return FALSE;
00411 }
00412
00413
00414
00415
00416
00417 static BOOL
00418 Uncombine_imagrealpart_operator(WN *old_wn,WN **new_wn,OPCODE old_wn_opc)
00419 {
00420 const OPERATOR old_wn_opr = OPCODE_operator(old_wn_opc);
00421
00422 Is_True( old_wn_opr == OPR_IMAGPART || old_wn_opr == OPR_REALPART,
00423 ("Uncombine_imagrealpart_operator: bad op: %s", OPCODE_name(old_wn_opc)) );
00424
00425 WN *kid0 = WN_kid0(old_wn);
00426 const OPCODE kid0_opc = WN_opcode(kid0);
00427 const OPERATOR kid0_opr = OPCODE_operator(kid0_opc);
00428
00429 if ( kid0_opr == OPR_INTRINSIC_OP ) {
00430 INTRINSIC new_intr;
00431 OPCODE new_intr_opc;
00432 switch ( (INTRINSIC)WN_intrinsic(kid0) ) {
00433 case INTRN_F4CIS:
00434 new_intr = old_wn_opr == OPR_IMAGPART ? INTRN_F4SIN : INTRN_F4COS;
00435 new_intr_opc = OPC_F4INTRINSIC_OP;
00436 goto handle_sincos;
00437
00438 case INTRN_F8CIS:
00439 new_intr = old_wn_opr == OPR_IMAGPART ? INTRN_F8SIN : INTRN_F8COS;
00440 new_intr_opc = OPC_F8INTRINSIC_OP;
00441 goto handle_sincos;
00442
00443 case INTRN_FQCIS:
00444 new_intr = old_wn_opr == OPR_IMAGPART ? INTRN_FQSIN : INTRN_FQCOS;
00445 new_intr_opc = OPC_FQINTRINSIC_OP;
00446
00447 {
00448 handle_sincos:
00449 WN *intr_wn = WN_Create_Intrinsic( new_intr_opc, new_intr, 1,
00450 &WN_kid0(kid0) );
00451 *new_wn = intr_wn;
00452 return TRUE;
00453 }
00454
00455 }
00456 }
00457
00458
00459 return FALSE;
00460 }
00461
00462
00463
00464
00465
00466
00467
00468
00469 static BOOL
00470 Uncombine_minmaxpart_operator(WN *old_wn,WN **new_wn,OPCODE old_wn_opc)
00471 {
00472 const OPERATOR old_wn_opr = OPCODE_operator(old_wn_opc);
00473
00474 Is_True( old_wn_opr == OPR_MINPART || old_wn_opr == OPR_MAXPART,
00475 ("Uncombine_minmaxpart_operator: bad op: %s", OPCODE_name(old_wn_opc)) );
00476
00477 WN *kid0 = WN_kid0(old_wn);
00478 const OPCODE kid0_opc = WN_opcode(kid0);
00479 const OPERATOR kid0_opr = OPCODE_operator(kid0_opc);
00480
00481 if ( kid0_opr == OPR_MINMAX ) {
00482 const OPCODE min_or_max_opc = old_wn_opr == OPR_MINPART ?
00483 OPCODE_make_op(OPR_MIN, OPCODE_rtype(kid0_opc),OPCODE_desc(kid0_opc) ) :
00484 OPCODE_make_op(OPR_MAX, OPCODE_rtype(kid0_opc),OPCODE_desc(kid0_opc) );
00485
00486 WN *min_or_max = WN_CreateExp2(min_or_max_opc, WN_kid0(kid0),WN_kid1(kid0));
00487 *new_wn = min_or_max;
00488 return TRUE;
00489 }
00490
00491
00492 return FALSE;
00493 }
00494
00495
00496
00497
00498
00499
00500
00501 extern BOOL
00502 Uncombine_Operations( WN *old_wn, WN **new_wn )
00503 {
00504 const OPCODE old_wn_opc = WN_opcode(old_wn);
00505 const OPERATOR old_wn_opr = OPCODE_operator(old_wn_opc);
00506
00507 switch ( old_wn_opr ) {
00508
00509 case OPR_MPY:
00510 return Uncombine_mpy_operator( old_wn, new_wn, old_wn_opc );
00511
00512 case OPR_DIVPART:
00513 case OPR_REMPART:
00514 return Uncombine_divrempart_operator( old_wn, new_wn, old_wn_opc);
00515
00516 case OPR_IMAGPART:
00517 case OPR_REALPART:
00518 return Uncombine_imagrealpart_operator(old_wn,new_wn,old_wn_opc);
00519
00520 case OPR_MAXPART:
00521 case OPR_MINPART:
00522 return Uncombine_minmaxpart_operator(old_wn,new_wn,old_wn_opc);
00523
00524 }
00525
00526 return FALSE;
00527 }
00528