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 #ifdef USE_PCH
00046 #include "be_com_pch.h"
00047 #endif
00048 #pragma hdrstop
00049 #include <math.h>
00050 #if defined(BUILD_OS_DARWIN)
00051 #include <limits.h>
00052 #else
00053 #include <values.h>
00054 #endif
00055 #include <alloca.h>
00056
00057 #include "defs.h"
00058 #include "config.h"
00059 #include "config_debug.h"
00060 #include "config_opt.h"
00061 #include "config_targ_opt.h"
00062 #include "errors.h"
00063 #include "erglob.h"
00064 #include "erbe.h"
00065 #include "tracing.h"
00066 #include "stab.h"
00067 #include "data_layout.h"
00068 #include "wn.h"
00069 #include "wn_util.h"
00070 #include "const.h"
00071 #include "targ_const.h"
00072 #include "targ_sim.h"
00073 #include "fb_whirl.h"
00074 #include "be_symtab.h"
00075 #include "intrn_info.h"
00076
00077
00078 #if (__GNUC__ == 2)
00079
00080
00081
00082
00083 static inline double trunc(double d)
00084 {
00085 if (d < 0.0) {
00086 return 1.0 + floor(d);
00087 }
00088 else {
00089 return floor(d);
00090 }
00091 }
00092 #endif
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102 typedef enum
00103 {
00104 EM_TRAPUV,
00105 EM_RTS_CHECKSTACK,
00106
00107 EM_LL_MUL,
00108 EM_LL_DIV,
00109 EM_ULL_DIV,
00110 EM_LL_MOD,
00111 EM_LL_REM,
00112 EM_ULL_REM,
00113 EM_LL_LSHIFT,
00114 EM_LL_RSHIFT,
00115 EM_ULL_RSHIFT,
00116 EM_LL_M3_DSLLV,
00117 EM_LL_M3_DSRAV,
00118 EM_LL_M3_DSRLV,
00119 EM_LL_TO_F,
00120 EM_ULL_TO_F,
00121 EM_LL_TO_D,
00122 EM_ULL_TO_D,
00123 EM_F_TO_LL,
00124 EM_F_TO_ULL,
00125 EM_F_ROUND_LL_F,
00126 EM_F_TRUNC_LL_F,
00127 EM_D_TO_LL,
00128 EM_D_TO_ULL,
00129 EM_D_ROUND_LL_D,
00130 EM_D_TRUNC_LL_D,
00131 EM_LL_BIT_EXTRACT ,
00132 EM_LL_BIT_INSERT ,
00133
00134 EM_Q_ABS,
00135 EM_Q_SQRT,
00136 EM_Q_ADD,
00137 EM_Q_SUB,
00138 EM_Q_MPY,
00139 EM_Q_DIV,
00140 EM_Q_MAX1,
00141 EM_Q_MIN1,
00142 EM_Q_EQ,
00143 EM_Q_NE,
00144 EM_Q_GE,
00145 EM_Q_GT,
00146 EM_Q_LE,
00147 EM_Q_LT,
00148 EM_SNGL_Q,
00149 EM_DBLE_Q,
00150 EM_KI_QINT,
00151 EM_JI_QINT,
00152 EM_Q_EXT,
00153 EM_Q_EXTD,
00154 EM_Q_FLOTK,
00155 EM_Q_FLOTKU,
00156 EM_Q_FLOTJ,
00157 EM_Q_FLOTJU,
00158 EM_KIQNNT,
00159 EM_JIQNNT,
00160
00161 EM_C4_SQRT,
00162 EM_C8_SQRT,
00163 EM_CQ_SQRT,
00164 EM_C4_RSQRT,
00165 EM_C8_RSQRT,
00166 EM_CQ_RSQRT,
00167
00168 EM_C4_ABS,
00169 EM_C8_ABS,
00170 EM_CQ_ABS,
00171 EM_KI_QCEIL,
00172 EM_JI_QCEIL,
00173 EM_KI_QFLOOR,
00174 EM_JI_QFLOOR,
00175 EM_LAST
00176 } EMULATION;
00177
00178
00179
00180
00181
00182
00183 typedef enum
00184 {
00185 COERCE_none,
00186 COERCE_by_reference,
00187 COERCE_by_value,
00188 COERCE_struct_by_value,
00189 COERCE_struct_by_reference,
00190 COERCE_split_complex
00191 } COERCE, *COERCEp;
00192
00193 typedef struct EM_ROUTINES
00194 {
00195 EMULATION id;
00196 const char *functionName;
00197 INT32 functionAttributes;
00198 COERCE runtimeArg0coercion;
00199 } EM_ROUTINES, *EM_ROUTINESp;
00200
00201 #define EM_id(x) em_routines[x].id
00202 #define EM_rt_name(x) em_routines[x].functionName
00203 #define EM_attributes(x) em_routines[x].functionAttributes
00204 #define EM_coerce0(x) em_routines[x].runtimeArg0coercion
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224 #define NSE PU_NO_SIDE_EFFECTS
00225 #define PURE_NSE (PU_IS_PURE | NSE)
00226 #define INVALID NULL
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252 #define NONE 0
00253 const EM_ROUTINES em_routines[]=
00254 {
00255 EM_TRAPUV, "__trapuv", PURE_NSE, COERCE_none,
00256 EM_RTS_CHECKSTACK,"_RtlCheckStack",PURE_NSE, COERCE_none,
00257 EM_LL_MUL, "__ll_mul", PURE_NSE, COERCE_none,
00258 EM_LL_DIV, "__ll_div", PURE_NSE, COERCE_none,
00259 EM_ULL_DIV, "__ull_div", PURE_NSE, COERCE_none,
00260 EM_LL_MOD, "__ll_mod", PURE_NSE, COERCE_none,
00261 EM_LL_REM, "__ll_rem", PURE_NSE, COERCE_none,
00262 EM_ULL_REM, "__ull_rem", PURE_NSE, COERCE_none,
00263 EM_LL_LSHIFT, "__ll_lshift", PURE_NSE, COERCE_none,
00264 EM_LL_RSHIFT, "__ll_rshift", PURE_NSE, COERCE_none,
00265 EM_ULL_RSHIFT, "__ull_rshift", PURE_NSE, COERCE_none,
00266 EM_LL_M3_DSLLV, "__dsllv", PURE_NSE, COERCE_none,
00267 EM_LL_M3_DSRAV, "__dsrav", PURE_NSE, COERCE_none,
00268 EM_LL_M3_DSRLV, "__dsrlv", PURE_NSE, COERCE_none,
00269 EM_LL_TO_F, "__ll_to_f", PURE_NSE, COERCE_none,
00270 EM_ULL_TO_F, "__ull_to_f", PURE_NSE, COERCE_none,
00271 EM_LL_TO_D, "__ll_to_d", PURE_NSE, COERCE_none,
00272 EM_ULL_TO_D, "__ull_to_d", PURE_NSE, COERCE_none,
00273 EM_F_TO_LL, "__f_to_ll", PURE_NSE, COERCE_none,
00274 EM_F_TO_ULL, "__f_to_ull", PURE_NSE, COERCE_none,
00275 EM_F_ROUND_LL_F, "__f_round_ll_f",PURE_NSE, COERCE_none,
00276 EM_F_TRUNC_LL_F, "__f_trunc_ll_f",PURE_NSE, COERCE_none,
00277 EM_D_TO_LL, "__d_to_ll", PURE_NSE, COERCE_none,
00278 EM_D_TO_ULL, "__d_to_ull", PURE_NSE, COERCE_none,
00279 EM_D_ROUND_LL_D, "__d_round_ll_d",PURE_NSE, COERCE_none,
00280 EM_D_TRUNC_LL_D, "__d_trunc_ll_d",PURE_NSE, COERCE_none,
00281 EM_LL_BIT_EXTRACT,"__ll_bit_extract",PURE_NSE,COERCE_none,
00282 EM_LL_BIT_INSERT, "__ll_bit_insert",PURE_NSE, COERCE_none,
00283 EM_Q_ABS, "__qabs", PURE_NSE, COERCE_none,
00284 EM_Q_SQRT, "__qsqrt", PURE_NSE, COERCE_none,
00285 EM_Q_ADD, "__q_add", PURE_NSE, COERCE_none,
00286 EM_Q_SUB, "__q_sub", PURE_NSE, COERCE_none,
00287 EM_Q_MPY, "__q_mul", PURE_NSE, COERCE_none,
00288 EM_Q_DIV, "__q_div", PURE_NSE, COERCE_none,
00289 EM_Q_MAX1, "__q_max1", PURE_NSE, COERCE_none,
00290 EM_Q_MIN1, "__q_min1", PURE_NSE, COERCE_none,
00291 EM_Q_EQ, "__q_eq", PURE_NSE, COERCE_none,
00292 EM_Q_NE, "__q_ne", PURE_NSE, COERCE_none,
00293 EM_Q_GE, "__q_ge", PURE_NSE, COERCE_none,
00294 EM_Q_GT, "__q_gt", PURE_NSE, COERCE_none,
00295 EM_Q_LE, "__q_le", PURE_NSE, COERCE_none,
00296 EM_Q_LT, "__q_lt", PURE_NSE, COERCE_none,
00297 EM_SNGL_Q, "__sngl_q", PURE_NSE, COERCE_none,
00298 EM_DBLE_Q, "__dble_q", PURE_NSE, COERCE_none,
00299 EM_KI_QINT, "__ki_qint", PURE_NSE, COERCE_none,
00300 EM_JI_QINT, "__ji_qint", PURE_NSE, COERCE_none,
00301 EM_Q_EXT, "__q_ext", PURE_NSE, COERCE_none,
00302 EM_Q_EXTD, "__q_extd", PURE_NSE, COERCE_none,
00303 EM_Q_FLOTK, "__q_flotk", PURE_NSE, COERCE_none,
00304 EM_Q_FLOTKU, "__q_flotku", PURE_NSE, COERCE_none,
00305 EM_Q_FLOTJ, "__q_flotj", PURE_NSE, COERCE_none,
00306 EM_Q_FLOTJU, "__q_flotju", PURE_NSE, COERCE_none,
00307 EM_KIQNNT, "__kiqnnt", PURE_NSE, COERCE_none,
00308 EM_JIQNNT, "__jiqnnt", PURE_NSE, COERCE_none,
00309 EM_C4_SQRT, "__csqrt", PURE_NSE, COERCE_split_complex,
00310 EM_C8_SQRT, "__zsqrt", PURE_NSE, COERCE_split_complex,
00311 EM_CQ_SQRT, "__cqsqrt", PURE_NSE, COERCE_split_complex,
00312 EM_C4_RSQRT, INVALID, NONE, COERCE_none,
00313 EM_C8_RSQRT, INVALID, NONE, COERCE_none,
00314 EM_CQ_RSQRT, INVALID, NONE, COERCE_none,
00315 EM_C4_ABS, INVALID, NONE, COERCE_none,
00316 EM_C8_ABS, INVALID, NONE, COERCE_none,
00317 EM_CQ_ABS, INVALID, NONE, COERCE_none,
00318
00319 EM_KI_QCEIL, "_CEILING_16_8", PURE_NSE, COERCE_none,
00320 EM_JI_QCEIL, "_CEILING_16_4", PURE_NSE, COERCE_none,
00321 EM_KI_QFLOOR, "_FLOOR_16_8", PURE_NSE, COERCE_none,
00322 EM_JI_QFLOOR, "_FLOOR_16_4", PURE_NSE, COERCE_none,
00323 };
00324
00325 typedef struct
00326 {
00327 INTRINSIC id;
00328 COERCE runtimeArg0;
00329 COERCE runtimeArg1;
00330 } INTRINSIC_RUNTIME_FORMALS;
00331
00332 #define INTR_id(x) intrinsic_runtime_formals[(x)].id
00333 #define INTR_coerce0(x) intrinsic_runtime_formals[(x)].runtimeArg0
00334 #define INTR_coerce1(x) intrinsic_runtime_formals[(x)].runtimeArg1
00335
00336
00337
00338
00339
00340
00341 INTRINSIC_RUNTIME_FORMALS intrinsic_runtime_formals[]=
00342 {
00343 INTRN_C4I4EXPEXPR, COERCE_split_complex, COERCE_none,
00344 INTRN_C4I8EXPEXPR, COERCE_split_complex, COERCE_none,
00345 INTRN_C8I4EXPEXPR, COERCE_split_complex, COERCE_none,
00346 INTRN_C8I8EXPEXPR, COERCE_split_complex, COERCE_none,
00347 INTRN_CQI4EXPEXPR, COERCE_split_complex, COERCE_none,
00348 INTRN_CQI8EXPEXPR, COERCE_split_complex, COERCE_none,
00349
00350 INTRN_C4EXPEXPR, COERCE_split_complex, COERCE_split_complex,
00351 INTRN_C8EXPEXPR, COERCE_split_complex, COERCE_split_complex,
00352 INTRN_CQEXPEXPR, COERCE_split_complex, COERCE_split_complex,
00353 INTRN_F4C4ABS, COERCE_split_complex, COERCE_none,
00354 INTRN_F8C8ABS, COERCE_split_complex, COERCE_none,
00355 INTRN_FQCQABS, COERCE_split_complex, COERCE_none,
00356 INTRN_C4EXP, COERCE_split_complex, COERCE_none,
00357 INTRN_C8EXP, COERCE_split_complex, COERCE_none,
00358 INTRN_CQEXP, COERCE_split_complex, COERCE_none,
00359 INTRN_C4LOG, COERCE_split_complex, COERCE_none,
00360 INTRN_C8LOG, COERCE_split_complex, COERCE_none,
00361 INTRN_CQLOG, COERCE_split_complex, COERCE_none,
00362 INTRN_C4COS, COERCE_split_complex, COERCE_none,
00363 INTRN_C8COS, COERCE_split_complex, COERCE_none,
00364 INTRN_CQCOS, COERCE_split_complex, COERCE_none,
00365 INTRN_C4SIN, COERCE_split_complex, COERCE_none,
00366 INTRN_C8SIN, COERCE_split_complex, COERCE_none,
00367 INTRN_CQSIN, COERCE_split_complex, COERCE_none
00368 };
00369
00370 INT32 intrinsic_runtime_formals_size = sizeof(intrinsic_runtime_formals) /
00371 sizeof( INTRINSIC_RUNTIME_FORMALS);
00372
00373 typedef struct
00374 {
00375 INTRINSIC id;
00376 TYPE_ID parameterType0;
00377 TYPE_ID parameterType1;
00378 TYPE_ID parameterType2;
00379 } INTRINSIC_PARAMETER_TYPE;
00380
00381 #define INTR_parm_id(x) intrinsic_parameter_type[(x)].id
00382 #define INTR_parmtype0(x) intrinsic_parameter_type[(x)].parameterType0
00383 #define INTR_parmtype1(x) intrinsic_parameter_type[(x)].parameterType1
00384 #define INTR_parmtype2(x) intrinsic_parameter_type[(x)].parameterType2
00385
00386 INTRINSIC_PARAMETER_TYPE intrinsic_parameter_type[]=
00387 {
00388 INTRN_I1DIM, MTYPE_I1, MTYPE_I1, MTYPE_V,
00389 INTRN_I2DIM, MTYPE_I2, MTYPE_I2, MTYPE_V,
00390 INTRN_I4DIM, MTYPE_I4, MTYPE_I4, MTYPE_V,
00391 INTRN_I8DIM, MTYPE_I8, MTYPE_I8, MTYPE_V,
00392 INTRN_F4DIM, MTYPE_F4, MTYPE_F4, MTYPE_V,
00393 INTRN_F8DIM, MTYPE_F8, MTYPE_F8, MTYPE_V,
00394 INTRN_FQDIM, MTYPE_FQ, MTYPE_FQ, MTYPE_V,
00395
00396 INTRN_F4MOD, MTYPE_F4, MTYPE_F4, MTYPE_V,
00397 INTRN_F8MOD, MTYPE_F8, MTYPE_F8, MTYPE_V,
00398 INTRN_FQMOD, MTYPE_FQ, MTYPE_FQ, MTYPE_V,
00399
00400 INTRN_F8F4PROD, MTYPE_F4, MTYPE_F4, MTYPE_V,
00401 INTRN_FQF8PROD, MTYPE_F8, MTYPE_F8, MTYPE_V,
00402
00403 INTRN_I1SIGN, MTYPE_I1, MTYPE_I1, MTYPE_V,
00404 INTRN_I2SIGN, MTYPE_I2, MTYPE_I2, MTYPE_V,
00405 INTRN_I4SIGN, MTYPE_I4, MTYPE_I4, MTYPE_V,
00406 INTRN_I8SIGN, MTYPE_I8, MTYPE_I8, MTYPE_V,
00407 INTRN_F4SIGN, MTYPE_F4, MTYPE_F4, MTYPE_V,
00408 INTRN_F8SIGN, MTYPE_F8, MTYPE_F8, MTYPE_V,
00409 INTRN_FQSIGN, MTYPE_FQ, MTYPE_FQ, MTYPE_V,
00410
00411 INTRN_F4AINT, MTYPE_F4, MTYPE_V, MTYPE_V,
00412 INTRN_F8AINT, MTYPE_F8, MTYPE_V, MTYPE_V,
00413 INTRN_FQAINT, MTYPE_FQ, MTYPE_V, MTYPE_V,
00414
00415 INTRN_I2F4NINT, MTYPE_F4, MTYPE_V, MTYPE_V,
00416 INTRN_I4F4NINT, MTYPE_F4, MTYPE_V, MTYPE_V,
00417 INTRN_I8F4NINT, MTYPE_F4, MTYPE_V, MTYPE_V,
00418 INTRN_I2F8IDNINT, MTYPE_F8, MTYPE_V, MTYPE_V,
00419 INTRN_I4F8IDNINT, MTYPE_F8, MTYPE_V, MTYPE_V,
00420 INTRN_I8F8IDNINT, MTYPE_F8, MTYPE_V, MTYPE_V,
00421 INTRN_I2FQIQNINT, MTYPE_FQ, MTYPE_V, MTYPE_V,
00422 INTRN_I4FQIQNINT, MTYPE_FQ, MTYPE_V, MTYPE_V,
00423 INTRN_I8FQIQNINT, MTYPE_FQ, MTYPE_V, MTYPE_V,
00424
00425 INTRN_F4ANINT, MTYPE_F4, MTYPE_V, MTYPE_V,
00426 INTRN_F8ANINT, MTYPE_F8, MTYPE_V, MTYPE_V,
00427 INTRN_FQANINT, MTYPE_FQ, MTYPE_V, MTYPE_V,
00428
00429 INTRN_F4LOG10, MTYPE_F4, MTYPE_V, MTYPE_V,
00430 INTRN_F8LOG10, MTYPE_F8, MTYPE_V, MTYPE_V,
00431 INTRN_FQLOG10, MTYPE_FQ, MTYPE_V, MTYPE_V,
00432
00433 INTRN_I1BTEST, MTYPE_I1, MTYPE_I1, MTYPE_V,
00434 INTRN_I2BTEST, MTYPE_I2, MTYPE_I2, MTYPE_V,
00435 INTRN_I4BTEST, MTYPE_I4, MTYPE_I4, MTYPE_V,
00436 INTRN_I8BTEST, MTYPE_I8, MTYPE_I8, MTYPE_V,
00437
00438 INTRN_I1BSET, MTYPE_I1, MTYPE_I1, MTYPE_V,
00439 INTRN_I2BSET, MTYPE_I2, MTYPE_I2, MTYPE_V,
00440 INTRN_I4BSET, MTYPE_I4, MTYPE_I4, MTYPE_V,
00441 INTRN_I8BSET, MTYPE_I8, MTYPE_I8, MTYPE_V,
00442
00443 INTRN_I1BCLR, MTYPE_I1, MTYPE_I1, MTYPE_V,
00444 INTRN_I2BCLR, MTYPE_I2, MTYPE_I2, MTYPE_V,
00445 INTRN_I4BCLR, MTYPE_I4, MTYPE_I4, MTYPE_V,
00446 INTRN_I8BCLR, MTYPE_I8, MTYPE_I8, MTYPE_V,
00447
00448 INTRN_I1BITS, MTYPE_I1, MTYPE_I1, MTYPE_I1,
00449 INTRN_I2BITS, MTYPE_I2, MTYPE_I2, MTYPE_I2,
00450 INTRN_I4BITS, MTYPE_I4, MTYPE_I4, MTYPE_I4,
00451 INTRN_I8BITS, MTYPE_I8, MTYPE_I8, MTYPE_I8,
00452
00453 INTRN_I1SHL, MTYPE_I1, MTYPE_I1, MTYPE_V,
00454 INTRN_I2SHL, MTYPE_I2, MTYPE_I2, MTYPE_V,
00455
00456 INTRN_I1SHR, MTYPE_I1, MTYPE_I1, MTYPE_V,
00457 INTRN_I2SHR, MTYPE_I2, MTYPE_I2, MTYPE_V,
00458
00459 INTRN_I1SHFT, MTYPE_I1, MTYPE_I1, MTYPE_V,
00460 INTRN_I2SHFT, MTYPE_I2, MTYPE_I2, MTYPE_V,
00461 INTRN_I4SHFT, MTYPE_I4, MTYPE_I4, MTYPE_V,
00462 INTRN_I8SHFT, MTYPE_I8, MTYPE_I8, MTYPE_V,
00463
00464 INTRN_I1SHFTC, MTYPE_I1, MTYPE_I1, MTYPE_I1,
00465 INTRN_I2SHFTC, MTYPE_I2, MTYPE_I2, MTYPE_I2,
00466 INTRN_I4SHFTC, MTYPE_I4, MTYPE_I4, MTYPE_I4,
00467 INTRN_I8SHFTC, MTYPE_I8, MTYPE_I8, MTYPE_I8,
00468
00469 INTRN_I1MVBITS, MTYPE_I1, MTYPE_I1, MTYPE_I1,
00470 INTRN_I2MVBITS, MTYPE_I2, MTYPE_I2, MTYPE_I2,
00471 INTRN_I4MVBITS, MTYPE_I4, MTYPE_I4, MTYPE_I4,
00472 INTRN_I8MVBITS, MTYPE_I8, MTYPE_I8, MTYPE_I8,
00473
00474 };
00475 INT32 intrinsic_parameter_type_size = sizeof(intrinsic_parameter_type) /
00476 sizeof( INTRINSIC_PARAMETER_TYPE);
00477
00478
00479 #define WN_has_ty(x) (OPCODE_has_1ty(WN_opcode(x)) || OPCODE_has_2ty(WN_opcode(x)))
00480
00481 #define WN_is_pointer(x) (WN_has_ty(x) && (TY_kind(WN_ty(x)) == KIND_POINTER))
00482
00483 #define Is_Integer_Constant(x) (WN_operator(x) == OPR_INTCONST)
00484
00485 #define Is_Constant(x) (WN_operator(x) == OPR_CONST)
00486
00487 #define OPCODE_is_intrinsic(op) \
00488 ((OPCODE_operator((op)) == OPR_INTRINSIC_CALL) || \
00489 (OPCODE_operator((op)) == OPR_INTRINSIC_OP))
00490
00491 #define ABS(x) (((x)<0) ? -(x) : (x))
00492
00493
00494
00495
00496
00497 extern const char * INTR_intrinsic_name(WN *tree);
00498
00499 extern WN * make_pointer_to_node(WN *block, WN *tree);
00500
00501
00502
00503
00504
00505 extern PREG_NUM AssignExpr(WN *block, WN *tree, TYPE_ID type);
00506
00507 extern TY_IDX compute_alignment_type(WN *tree, TY_IDX, INT64 offset);
00508
00509 extern INT32 compute_copy_alignment(TY_IDX, TY_IDX, INT32 offset);
00510
00511 extern BOOL lower_is_aliased(WN *wn1, WN *wn2, INT64 size);
00512
00513 extern TYPE_ID compute_copy_quantum(INT32 );
00514
00515 extern WN *WN_I1const(TYPE_ID type, INT64 con);
00516 extern void WN_annotate_call_flags(WN *call, ST *sym);
00517
00518 extern BOOL CG_bcopy_cannot_overlap;
00519 extern BOOL CG_memcpy_cannot_overlap;
00520 extern BOOL CG_memmove_cannot_overlap;
00521
00522 extern INT32 CG_memmove_inst_count;
00523
00524
00525
00526
00527
00528
00529 static EMULATION WN_emulation(WN *tree);
00530
00531 static WN *em_exp_int(WN *block, WN *x, WN *pow, TYPE_ID type);
00532 static WN *em_exp_float(WN *block, WN *x, WN *pow, TYPE_ID type);
00533 static WN *em_mod_float(WN *block, WN *x, WN *y);
00534
00535 static WN *em_complex_exp(WN *block, WN *x);
00536 static WN *em_complex_cos(WN *block, WN *x);
00537
00538 static COERCE INTR_coerce_runtime(WN *tree, INT32 arg);
00539 static TYPE_ID INTR_parameter_type(WN *tree, INT32 arg);
00540 static TY_IDX aux_compute_alignment(WN *tree);
00541
00542
00543
00544
00545
00546
00547
00548 static INT32 em_exp_int_max = 256;
00549
00550 #define MAX_INTRINSIC_ARGS 20
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563 TYPE_ID INTR_return_mtype(INTRINSIC id)
00564 {
00565 INTRN_RETKIND rtype = INTRN_return_kind(id);
00566
00567 switch(rtype)
00568 {
00569 case IRETURN_I1: return MTYPE_I1;
00570 case IRETURN_I2: return MTYPE_I2;
00571 case IRETURN_I4: return MTYPE_I4;
00572 case IRETURN_I8: return MTYPE_I8;
00573 case IRETURN_U1: return MTYPE_U1;
00574 case IRETURN_U2: return MTYPE_U2;
00575 case IRETURN_U4: return MTYPE_U4;
00576 case IRETURN_U8: return MTYPE_U8;
00577 case IRETURN_F4: return MTYPE_F4;
00578 case IRETURN_F8: return MTYPE_F8;
00579 case IRETURN_FQ: return MTYPE_FQ;
00580 case IRETURN_C4: return MTYPE_C4;
00581 case IRETURN_C8: return MTYPE_C8;
00582 case IRETURN_CQ: return MTYPE_CQ;
00583 case IRETURN_V: return MTYPE_V;
00584 case IRETURN_PV:
00585 case IRETURN_PU1:
00586 case IRETURN_DA1:
00587 case IRETURN_SZT:
00588 case IRETURN_PC :
00589 case IRETURN_UNKNOWN:
00590 return MTYPE_UNKNOWN;
00591 }
00592 return MTYPE_UNKNOWN;
00593 }
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608 static EMULATION WN_emulation(WN *tree)
00609 {
00610 OPCODE op = WN_opcode(tree);
00611 TYPE_ID type = OPCODE_rtype(op);
00612
00613 switch (WN_operator(tree)) {
00614 case OPR_SQRT:
00615 switch(type) {
00616 case MTYPE_C4: return EM_C4_SQRT;
00617 case MTYPE_C8: return EM_C8_SQRT;
00618 case MTYPE_CQ: return EM_CQ_SQRT;
00619 case MTYPE_FQ: return EM_Q_SQRT;
00620 }
00621 break;
00622
00623 case OPR_RSQRT:
00624 switch(type) {
00625 case MTYPE_C4: return EM_C4_RSQRT;
00626 case MTYPE_C8: return EM_C8_RSQRT;
00627 case MTYPE_CQ: return EM_CQ_RSQRT;
00628 }
00629 break;
00630
00631 case OPR_CVT:
00632 {
00633 TYPE_ID desc = WN_desc(tree);
00634 if (desc == MTYPE_FQ)
00635 {
00636 switch(type) {
00637 case MTYPE_I4: return EM_JI_QINT;
00638 case MTYPE_I8: return EM_KI_QINT;
00639 case MTYPE_F4: return EM_SNGL_Q;
00640 case MTYPE_F8: return EM_DBLE_Q;
00641 }
00642 break;
00643 }
00644 else if (type == MTYPE_FQ)
00645 {
00646 switch(desc) {
00647 case MTYPE_U4: return EM_Q_FLOTJU;
00648 case MTYPE_I4: return EM_Q_FLOTJ;
00649 case MTYPE_U8: return EM_Q_FLOTKU;
00650 case MTYPE_I8: return EM_Q_FLOTK;
00651 case MTYPE_F8: return EM_Q_EXTD;
00652 case MTYPE_F4: return EM_Q_EXT;
00653 }
00654 }
00655 }
00656 break;
00657
00658 case OPR_RND:
00659 {
00660 TYPE_ID desc = WN_desc(tree);
00661 if (desc == MTYPE_FQ)
00662 {
00663 switch(type)
00664 {
00665 case MTYPE_I4: return EM_JIQNNT;
00666 case MTYPE_I8: return EM_KIQNNT;
00667 }
00668 break;
00669 }
00670 }
00671 break;
00672
00673 default:
00674 if (type == MTYPE_FQ)
00675 {
00676 switch(WN_operator(tree)) {
00677 case OPR_ISTORE:
00678 case OPR_ISTOREX:
00679 case OPR_STID:
00680 case OPR_ILOAD:
00681 case OPR_ILOADX:
00682 case OPR_SELECT:
00683 case OPR_LDID:
00684 case OPR_CONST:
00685 case OPR_NEG:
00686 break;
00687
00688 case OPR_ABS: return EM_Q_ABS;
00689 case OPR_ADD: return EM_Q_ADD;
00690 case OPR_SUB: return EM_Q_SUB;
00691 case OPR_MPY: return EM_Q_MPY;
00692 case OPR_DIV: return EM_Q_DIV;
00693 case OPR_MAX: return EM_Q_MAX1;
00694 case OPR_MIN: return EM_Q_MIN1;
00695
00696 case OPR_RECIP:
00697 case OPR_RSQRT:
00698 case OPR_MADD:
00699 case OPR_MSUB:
00700 case OPR_NMADD:
00701 case OPR_NMSUB:
00702 case OPR_RND:
00703 case OPR_TRUNC:
00704 case OPR_CVT:
00705 case OPR_SQRT:
00706 Is_True(FALSE, ("WN_emulation() %s should be already processed", OPCODE_name(WN_opcode(tree))));
00707 break;
00708
00709 case OPR_CEIL:
00710 case OPR_FLOOR:
00711 case OPR_MOD:
00712 case OPR_REM:
00713 case OPR_CVTL:
00714 case OPR_CALL:
00715 case OPR_INTRINSIC_CALL:
00716 Is_True(FALSE, ("WN_emulation() %s invalid context for op", OPCODE_name(WN_opcode(tree))));
00717 }
00718 }
00719 else if (WN_desc(tree)== MTYPE_FQ)
00720 {
00721 switch(WN_operator(tree)) {
00722 case OPR_EQ: return EM_Q_EQ;
00723 case OPR_NE: return EM_Q_NE;
00724 case OPR_GT: return EM_Q_GT;
00725 case OPR_GE: return EM_Q_GE;
00726 case OPR_LT: return EM_Q_LT;
00727 case OPR_LE: return EM_Q_LE;
00728
00729 case OPR_TRUNC:
00730 switch(type)
00731 {
00732 case MTYPE_I4: return EM_JI_QINT;
00733 case MTYPE_I8: return EM_KI_QINT;
00734 }
00735 break;
00736 case OPR_CEIL:
00737 switch(type)
00738 {
00739 case MTYPE_I4: return EM_JI_QCEIL;
00740 case MTYPE_I8: return EM_KI_QCEIL;
00741 }
00742 break;
00743 case OPR_FLOOR:
00744 switch(type)
00745 {
00746 case MTYPE_I4: return EM_JI_QFLOOR;
00747 case MTYPE_I8: return EM_KI_QFLOOR;
00748 }
00749 break;
00750 }
00751 }
00752 break;
00753 }
00754 FmtAssert(FALSE, ("WN_emulation() %s not recognized", OPCODE_name(WN_opcode(tree))));
00755 return EM_LAST;
00756 }
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771 static WN *checkForZero(WN *block, TYPE_ID type, PREG_NUM xN, WN *if_else, WN *value)
00772 {
00773 TYPE_ID rtype = WN_rtype(value);
00774 WN *if_then;
00775 PREG_NUM retN;
00776
00777 if_then = WN_CreateBlock();
00778
00779 retN = AssignExpr(if_then, WN_Zerocon(rtype), rtype);
00780
00781 {
00782 WN *st;
00783
00784 st = WN_StidIntoPreg(rtype, retN, MTYPE_To_PREG(rtype), value);
00785 WN_INSERT_BlockLast(if_else, st);
00786 }
00787
00788 {
00789 WN *cond, *IF;
00790
00791 Is_True(MTYPE_is_float(type), ("unexpected type"));
00792
00793 cond = WN_EQ(type,
00794 WN_LdidPreg(type, xN),
00795 WN_Zerocon(type));
00796
00797 IF = WN_CreateIf(cond, if_then, if_else);
00798 WN_INSERT_BlockLast(block, IF);
00799 }
00800 return WN_LdidPreg(rtype, retN);
00801 }
00802
00803
00804
00805
00806
00807
00808
00809
00810
00811
00812 static WN *WN_arg(WN *tree, INT32 arg)
00813 {
00814 WN *child= WN_kid(tree, arg);
00815
00816 if (WN_operator_is(child, OPR_PARM))
00817 {
00818 return WN_kid0(child);
00819 }
00820
00821 return child;
00822 }
00823
00824
00825
00826
00827 static WN *em_clen(WN *block, WN *len)
00828 {
00829 return len;
00830 }
00831
00832
00833
00834
00835
00836
00837
00838 static WN *aux_nearest(TYPE_ID rtype, PREG_NUM xN)
00839 {
00840 WN *rel, *select;
00841
00842 rel = WN_GE(rtype, WN_LdidPreg(rtype, xN), WN_Zerocon(rtype));
00843
00844 select = WN_Select(rtype,
00845 rel,
00846 WN_Floatconst(rtype, .5),
00847 WN_Floatconst(rtype, -.5));
00848
00849 return WN_Add(rtype, WN_LdidPreg(rtype, xN), select);
00850 }
00851
00852
00853
00854
00855 static WN *aux_CvtRnd(TYPE_ID rtype, WN *x)
00856 {
00857 WN *rnd;
00858 TYPE_ID intToFloat = (Slow_CVTDL) ? MTYPE_I4 : MTYPE_I8;
00859
00860
00861 if (WN_rtype(x) != MTYPE_F4) {
00862 intToFloat = MTYPE_I8;
00863 }
00864 rnd = WN_Rnd(rtype, intToFloat, x);
00865
00866 return WN_Cvt(intToFloat, rtype, rnd);
00867 }
00868
00869 static WN *aux_CvtTrunc(TYPE_ID rtype, WN *x)
00870 {
00871 WN *trunc;
00872 TYPE_ID intToFloat = (Slow_CVTDL) ? MTYPE_I4 : MTYPE_I8;
00873
00874
00875
00876
00877
00878 if (WN_rtype(x) != MTYPE_F4) {
00879 intToFloat = MTYPE_I8;
00880 }
00881 trunc = WN_Trunc(rtype, intToFloat, x);
00882
00883 return WN_Cvt(intToFloat, rtype, trunc);
00884 }
00885
00886
00887
00888
00889 static WN *aux_CreateMstore(WN_OFFSET offset, TY_IDX type, WN *value, WN *addr,
00890 WN *size)
00891 {
00892 if (Is_Integer_Constant(size) && WN_const_val(size) <= 0)
00893 {
00894
00895
00896
00897
00898
00899 return WN_CreateBlock();
00900 }
00901
00902 UINT64 ty_size = TY_size(TY_pointed(type));
00903 if (ty_size != 0 && WN_const_val (size) % ty_size != 0) {
00904
00905
00906
00907 static TY_IDX void_star = TY_IDX_ZERO;
00908 if (void_star == TY_IDX_ZERO)
00909 void_star = Make_Pointer_Type (MTYPE_To_TY (MTYPE_V));
00910 Set_TY_IDX_index (type, TY_IDX_index (void_star));
00911 }
00912 return WN_CreateMstore(offset, type, value, addr, size);
00913 }
00914
00915
00916
00917
00918
00919
00920
00921
00922
00923
00924
00925
00926
00927
00928
00929
00930 #define TWO_EXP_23 8388608.0
00931 #define TWO_EXP_52 4503599627370496.0
00932
00933
00934
00935
00936
00937
00938
00939
00940
00941
00942
00943
00944
00945
00946
00947
00948
00949 static WN *em_nearest_int(WN *block, TYPE_ID rtype, WN *x)
00950 {
00951 TYPE_ID type = WN_rtype(x);
00952
00953 if (Fast_NINT_Allowed)
00954 {
00955 return WN_Rnd(type, rtype, x);
00956 }
00957 else if ((type == MTYPE_F4) || (type == MTYPE_F8))
00958 {
00959 WN *add;
00960 PREG_NUM xN;
00961
00962 xN = AssignExpr(block, x, type);
00963
00964 add = aux_nearest(type, xN);
00965
00966 if (Fast_trunc_Allowed)
00967 {
00968 return WN_Trunc(type, rtype, add);
00969 }
00970 else
00971 {
00972 WN *rel, *select;
00973 double con= (type==MTYPE_F4) ? TWO_EXP_23 : TWO_EXP_52;
00974
00975 rel = WN_GE(type,
00976 WN_Abs(type, WN_LdidPreg(type, xN)),
00977 WN_Floatconst(type, con));
00978
00979 select = WN_Select(type, rel, WN_LdidPreg(type, xN), add);
00980
00981 return WN_Trunc(type, rtype, select);
00982 }
00983 }
00984 else
00985 {
00986 return NULL;
00987 }
00988 }
00989
00990
00991
00992
00993
00994
00995
00996
00997
00998
00999 static WN *em_nearest_aint(WN *block, TYPE_ID rtype, WN *x)
01000 {
01001 if (Fast_NINT_Allowed)
01002 {
01003 return aux_CvtRnd(rtype, x);
01004 }
01005 else if ((rtype == MTYPE_F4) || (rtype == MTYPE_F8))
01006 {
01007 PREG_NUM xN;
01008 WN *add, *cvt;
01009
01010 xN = AssignExpr(block, x, rtype);
01011
01012 add = aux_nearest(rtype, xN);
01013
01014
01015
01016
01017 cvt = aux_CvtTrunc(rtype, add);
01018
01019 if (Fast_trunc_Allowed)
01020 {
01021 return cvt;
01022 }
01023 else
01024 {
01025 WN *rel;
01026 double con= (rtype==MTYPE_F4) ? TWO_EXP_23 : TWO_EXP_52;
01027
01028 rel = WN_GE(rtype,
01029 WN_Abs(rtype, WN_LdidPreg(rtype, xN)),
01030 WN_Floatconst(rtype, con));
01031
01032 return WN_Select(rtype, rel, WN_LdidPreg(rtype, xN), cvt);
01033 }
01034 }
01035 return NULL;
01036 }
01037
01038
01039
01040
01041
01042
01043
01044
01045
01046
01047 static WN *em_aint(WN *block, TYPE_ID rtype, WN *x)
01048 {
01049 if (Fast_trunc_Allowed)
01050 {
01051 return aux_CvtTrunc(rtype, x);
01052 }
01053 else if ((rtype == MTYPE_F4) || (rtype == MTYPE_F8))
01054 {
01055 PREG_NUM xN;
01056 WN *rel, *cvt;
01057 double con= (rtype==MTYPE_F4) ? TWO_EXP_23 : TWO_EXP_52;
01058
01059 xN = AssignExpr(block, x, rtype);
01060
01061 rel = WN_GE(rtype,
01062 WN_Abs(rtype, WN_LdidPreg(rtype, xN)),
01063 WN_Floatconst(rtype, con));
01064
01065 cvt = aux_CvtTrunc(rtype, WN_LdidPreg(rtype, xN));
01066
01067 return WN_Select(rtype, rel, WN_LdidPreg(rtype, xN), cvt);
01068 }
01069 else
01070 {
01071 return NULL;
01072 }
01073 }
01074
01075
01076
01077
01078
01079
01080
01081
01082
01083
01084 static WN *em_sign(WN *block, WN *x, WN *y)
01085 {
01086 PREG_NUM absN;
01087 TYPE_ID type = WN_rtype(x);
01088 WN *abs, *select;
01089
01090 #ifdef KEY // bug 9660
01091 if (MTYPE_is_integral(type) && ! MTYPE_signed(type))
01092 type = Mtype_TransferSign(MTYPE_I4, type);
01093 #endif
01094 #ifdef KEY // bug 12052
01095 if (MTYPE_is_integral(type) &&
01096 MTYPE_byte_size(type) < MTYPE_byte_size(WN_rtype(y)))
01097 type = Mtype_TransferSize(WN_rtype(y), type);
01098 #endif
01099 abs = WN_Abs(type, x);
01100 absN = AssignExpr(block, abs, type);
01101
01102
01103 select = WN_Select(type,
01104 WN_GE(type, y, WN_Zerocon(type)),
01105 WN_LdidPreg(type, absN),
01106 WN_Neg(type, WN_LdidPreg(type, absN)));
01107 return select;
01108 }
01109
01110
01111
01112
01113
01114
01115 static WN *em_prod(WN *block, TYPE_ID rtype, WN *x, WN *y)
01116 {
01117 TYPE_ID type = WN_rtype(x);
01118 WN *mpy;
01119
01120 mpy = WN_Mpy(rtype,
01121 WN_Cvt(type, rtype, x),
01122 WN_Cvt(type, rtype, y));
01123 return mpy;
01124 }
01125
01126
01127
01128
01129
01130
01131 static WN *em_dim(WN *block, WN *x, WN *y)
01132 {
01133 PREG_NUM xN, yN;
01134 TYPE_ID type = WN_rtype(x);
01135 WN *rel, *sub, *select;
01136
01137 xN = AssignExpr(block, x, type);
01138 yN = AssignExpr(block, y, type);
01139
01140 rel = WN_GT(type,
01141 WN_LdidPreg(type, xN),
01142 WN_LdidPreg(type, yN));
01143
01144 sub = WN_Sub(type,
01145 WN_LdidPreg(type, xN),
01146 WN_LdidPreg(type, yN));
01147
01148 select = WN_Select(type,
01149 rel,
01150 sub,
01151 WN_Zerocon(type));
01152 return select;
01153 }
01154
01155
01156
01157
01158
01159
01160 static WN *em_mod_float(WN *block, WN *x, WN *y)
01161 {
01162 PREG_NUM xN, yN;
01163 TYPE_ID type = WN_rtype(x);
01164 WN *div, *cvt, *mpy, *sub;
01165
01166 if ((type == MTYPE_F4) || (type == MTYPE_F8)) {
01167 xN = AssignExpr(block, x, type);
01168 yN = AssignExpr(block, y, type);
01169 div = WN_Div(type,
01170 WN_LdidPreg(type, xN),
01171 WN_LdidPreg(type, yN));
01172 cvt = em_aint(block, type, div);
01173 mpy = WN_Mpy(type,
01174 WN_LdidPreg(type, yN),
01175 cvt);
01176 sub = WN_Sub(type,
01177 WN_LdidPreg(type, xN),
01178 mpy);
01179 return sub;
01180 } else {
01181 return NULL;
01182 }
01183 }
01184
01185
01186
01187
01188
01189
01190
01191
01192
01193
01194
01195
01196
01197
01198
01199
01200 #define BIT_IS_ON(x,i) ((x) & (1<<(i)))
01201
01202 static WN *build_mult_tree(WN *block, TYPE_ID type, PREG_NUM xN, INT32 pow)
01203 {
01204 PREG_NUM powers[16];
01205 INT32 i, n = 0;
01206 PREG_NUM xNm1;
01207 WN *tree = NULL;
01208
01209 Is_True((pow>0), ("expected pow>0"));
01210
01211 powers[n++] = xN;
01212 xNm1 = xN;
01213
01214 for(i= 1; ((1<<i) <= pow); i++)
01215 {
01216 WN *mpy;
01217
01218 mpy = WN_Mpy(type, WN_LdidPreg(type, xNm1), WN_LdidPreg(type, xNm1));
01219
01220 xNm1 = AssignExpr(block, mpy, type);
01221
01222 powers[n++] = xNm1;
01223 }
01224
01225 for(i= 0; ((1<<i) <= pow); i++)
01226 {
01227 if (BIT_IS_ON(pow, i))
01228 {
01229 PREG_NUM powerN = powers[i];
01230
01231 if (tree)
01232 {
01233 tree = WN_Mpy(type, tree, WN_LdidPreg(type, powerN));
01234 }
01235 else
01236 {
01237 tree = WN_LdidPreg(type, powerN);
01238 }
01239 }
01240 }
01241 return tree;
01242 }
01243
01244 static WN *em_exp_float(WN *block, WN *x, WN *pow, TYPE_ID type)
01245 {
01246 if (Is_Constant(pow))
01247 {
01248 TCON con = Const_Val(pow);
01249 BOOL sqrt, rsqrt;
01250 #ifdef KEY
01251 BOOL sqrt_25, rsqrt_25, sqrt_75, rsqrt_75;
01252 BOOL cbrt_33, cbrt_66;
01253 #endif
01254 WN *tree, *x_copy;
01255 double n;
01256
01257
01258
01259
01260
01261 if (MTYPE_is_complex(type))
01262 {
01263 TCON Ipow;
01264
01265 Ipow = Extract_Complex_Imag(con);
01266
01267 if (Targ_To_Host_Float(Ipow) == 0.0)
01268 {
01269 con = Extract_Complex_Real(con);
01270 }
01271 else
01272 {
01273 return NULL;
01274 }
01275 }
01276 n = Targ_To_Host_Float(con);
01277 sqrt = rsqrt = FALSE;
01278 #ifdef KEY
01279 cbrt_33 = cbrt_66 = FALSE;
01280 sqrt_25 = rsqrt_25 = sqrt_75 = rsqrt_75 = FALSE;
01281 #endif
01282
01283 if (trunc(n) == n)
01284 {
01285 ;
01286 }
01287 else if ((trunc(ABS(n))+.5) == ABS(n))
01288 {
01289
01290
01291
01292
01293 if (n<0)
01294 rsqrt = TRUE;
01295 else
01296 sqrt = TRUE;
01297 x_copy = WN_COPY_Tree(x);
01298 }
01299 #ifdef KEY
01300 else if ((trunc(ABS(n))+.25) == ABS(n))
01301 {
01302
01303
01304
01305
01306 if (n<0)
01307 rsqrt_25 = TRUE;
01308 else
01309 sqrt_25 = TRUE;
01310 x_copy = WN_COPY_Tree(x);
01311 }
01312 else if ((trunc(ABS(n))+.75) == ABS(n))
01313 {
01314
01315
01316
01317
01318 if (n<0)
01319 rsqrt_75 = TRUE;
01320 else
01321 sqrt_75 = TRUE;
01322
01323 x_copy = WN_COPY_Tree(x);
01324 }
01325 #if !defined (TARG_MIPS) && !defined (TARG_IA64)
01326 else if (ABS((trunc(n)+1.0/3) - n) < .0000001 &&
01327 ! (Is_Target_64bit() && !Is_Target_Anyx86() && OPT_Fast_Math))
01328 {
01329 cbrt_33 = TRUE;
01330 x_copy = WN_COPY_Tree(x);
01331 }
01332 else if (ABS((trunc(n)+2.0/3) - n) < .0000001 &&
01333 ! (Is_Target_64bit() && !Is_Target_Anyx86() && OPT_Fast_Math))
01334 {
01335 cbrt_66 = TRUE;
01336 x_copy = WN_COPY_Tree(x);
01337 }
01338 #endif
01339 #endif
01340 else
01341 {
01342 return NULL;
01343 }
01344
01345 {
01346 WN *ipow = WN_Intconst(MTYPE_I4, (INT64) trunc(n));
01347
01348 tree = em_exp_int(block, x, ipow, type);
01349 }
01350
01351 if (sqrt || rsqrt)
01352 {
01353 #ifdef KEY
01354
01355
01356
01357 if (!PU_f77_lang (Get_Current_PU()) &&
01358 !PU_f90_lang (Get_Current_PU()) &&
01359 LANG_Math_Errno &&
01360 MTYPE_is_float (WN_rtype (x_copy)) &&
01361 (!Is_Constant (x_copy) ||
01362 Targ_To_Host_Float (Const_Val (x_copy)) < 0))
01363 return NULL;
01364 #endif // KEY
01365 #ifdef TARG_X8664
01366
01367 if (rsqrt && (type == MTYPE_F8 || type == MTYPE_V16F8))
01368 return NULL;
01369 #endif
01370 if (tree)
01371 {
01372
01373
01374
01375
01376 PREG_NUM xN, treeN;
01377 WN *fractional;
01378
01379 xN = AssignExpr(block, x_copy, type);
01380 treeN = AssignExpr(block, tree, type);
01381
01382 fractional = (sqrt) ? WN_Sqrt(type, WN_LdidPreg(type, xN)) :
01383 WN_Rsqrt(type, WN_LdidPreg(type, xN));
01384
01385 tree = WN_Mpy(type,
01386 WN_LdidPreg(type, treeN),
01387 fractional);
01388 }
01389 }
01390 #ifdef KEY // bug 6932
01391
01392 if (sqrt_25 || rsqrt_25)
01393 {
01394 if (!PU_f77_lang (Get_Current_PU()) &&
01395 !PU_f90_lang (Get_Current_PU()) &&
01396 LANG_Math_Errno &&
01397 MTYPE_is_float (WN_rtype (x_copy)) &&
01398 (!Is_Constant (x_copy) ||
01399 Targ_To_Host_Float (Const_Val (x_copy)) < 0))
01400 return NULL;
01401 #ifdef TARG_X8664
01402
01403 if (rsqrt_25 && (type == MTYPE_F8 || type == MTYPE_V16F8))
01404 return NULL;
01405 #endif
01406 if (tree)
01407 {
01408
01409
01410
01411
01412 PREG_NUM xN, treeN;
01413 WN *fractional;
01414
01415 xN = AssignExpr(block, x_copy, type);
01416 treeN = AssignExpr(block, tree, type);
01417
01418 if (sqrt_25)
01419 fractional = WN_Sqrt(type, WN_Sqrt(type, WN_LdidPreg(type, xN)));
01420 else
01421 fractional = WN_Sqrt(type, WN_Rsqrt(type, WN_LdidPreg(type, xN)));
01422
01423 tree = WN_Mpy(type,
01424 WN_LdidPreg(type, treeN),
01425 fractional);
01426 }
01427 }
01428
01429 if (sqrt_75 || rsqrt_75)
01430 {
01431 if (!PU_f77_lang (Get_Current_PU()) &&
01432 !PU_f90_lang (Get_Current_PU()) &&
01433 LANG_Math_Errno &&
01434 MTYPE_is_float (WN_rtype (x_copy)) &&
01435 (!Is_Constant (x_copy) ||
01436 Targ_To_Host_Float (Const_Val (x_copy)) < 0))
01437 return NULL;
01438 #ifdef TARG_X8664
01439
01440 if (rsqrt_75 && (type == MTYPE_F8 || type == MTYPE_V16F8))
01441 return NULL;
01442 #endif
01443
01444 if (tree)
01445 {
01446
01447
01448
01449
01450 PREG_NUM xN, treeN;
01451 WN *fractional;
01452
01453 xN = AssignExpr(block, x_copy, type);
01454 treeN = AssignExpr(block, tree, type);
01455
01456 if (sqrt_75)
01457 fractional = WN_Mpy(type,
01458 WN_Sqrt(type, WN_LdidPreg(type, xN)),
01459 WN_Sqrt(type,
01460 WN_Sqrt(type, WN_LdidPreg(type, xN))));
01461 else
01462 fractional = WN_Mpy(type,
01463 WN_Rsqrt(type, WN_LdidPreg(type, xN)),
01464 WN_Rsqrt(type,
01465 WN_Sqrt(type, WN_LdidPreg(type, xN))));
01466
01467 tree = WN_Mpy(type,
01468 WN_LdidPreg(type, treeN),
01469 fractional);
01470 }
01471 }
01472
01473 #if !defined(TARG_SL)
01474 if (cbrt_33 || cbrt_66)
01475 {
01476 if (type != MTYPE_F4 && type != MTYPE_F8)
01477 return NULL;
01478 if (tree)
01479 {
01480
01481
01482
01483
01484 PREG_NUM xN = AssignExpr(block, x_copy, type);
01485 WN *kid = WN_CreateParm(type, WN_LdidPreg(type, xN), Be_Type_Tbl(type),
01486 WN_PARM_BY_VALUE | WN_PARM_READ_ONLY);
01487 WN* fraction = WN_Create_Intrinsic(
01488 OPCODE_make_op(OPR_INTRINSIC_OP, type, MTYPE_V),
01489 type == MTYPE_F4 ? INTRN_F4CBRT : INTRN_F8CBRT,
01490 1, &kid);
01491 if (cbrt_66) {
01492 PREG_NUM x13 = AssignExpr(block, fraction, type);
01493 fraction = WN_Mpy(type, WN_LdidPreg(type, x13),
01494 WN_LdidPreg(type, x13));
01495 }
01496 tree = WN_Mpy(type, tree, fraction);
01497 }
01498 }
01499 #endif // !TARG_SL
01500 #endif // KEY bug 6932
01501 return tree;
01502 }
01503
01504 return NULL;
01505 }
01506
01507 static WN *em_exp_int(WN *block, WN *x, WN *pow, TYPE_ID type)
01508 {
01509 if (Is_Integer_Constant(pow))
01510 {
01511 INT32 n = WN_const_val(pow);
01512 INT32 absN = ABS(n);
01513 WN *exp= NULL;
01514
01515 if (em_exp_int_max < absN)
01516 return NULL;
01517
01518 switch(n) {
01519 case 1:
01520 exp = x;
01521 break;
01522 case -1:
01523 exp = WN_Inverse(type, x);
01524 break;
01525 case 0:
01526 if (MTYPE_type_class(type) & MTYPE_CLASS_INTEGER)
01527 exp = WN_Intconst(type, 1);
01528 else
01529 exp = WN_Floatconst(type, 1.0);
01530 break;
01531 case 2:
01532 {
01533 PREG_NUM xN;
01534
01535 xN = AssignExpr(block, x, type);
01536
01537 exp = WN_Mpy(type,
01538 WN_LdidPreg(type, xN),
01539 WN_LdidPreg(type, xN));
01540 break;
01541 }
01542 default:
01543 {
01544 PREG_NUM xN;
01545
01546 if (Fast_Exp_Allowed)
01547 {
01548 xN = AssignExpr(block, x, type);
01549
01550 exp = build_mult_tree(block, type, xN, absN);
01551
01552 WN_Delete(pow);
01553 if (n < 0)
01554 exp = WN_Inverse(type, exp);
01555 }
01556 }
01557 }
01558 return exp;
01559 }
01560 else if (Is_Integer_Constant(x))
01561 {
01562
01563
01564
01565 INT32 val = WN_const_val(x);
01566
01567 switch(val)
01568 {
01569 case -2:
01570 {
01571
01572
01573
01574 PREG_NUM powN, shlN;
01575 WN *shl, *band, *cond, *select, *ge;
01576
01577 powN = AssignExpr(block, pow, type);
01578
01579 shl = WN_Shl(type,
01580 WN_Intconst(type, 1),
01581 WN_LdidPreg(type, powN));
01582
01583 shlN = AssignExpr(block, shl, type);
01584
01585 band = WN_Band(type,
01586 WN_LdidPreg(type, powN),
01587 WN_Intconst(type, 1));
01588
01589 cond = WN_EQ(type, band, WN_Zerocon(type));
01590
01591 select = WN_Select(type,
01592 cond,
01593 WN_LdidPreg(type, shlN),
01594 WN_Neg(type, WN_LdidPreg(type, shlN)));
01595
01596 ge = WN_GE(type,
01597 WN_LdidPreg(type, powN),
01598 WN_Zerocon(type));
01599
01600 return WN_Select(type,
01601 ge,
01602 select,
01603 WN_Zerocon(type));
01604 }
01605 case -1:
01606 {
01607
01608
01609
01610 WN *band;
01611
01612 band = WN_Band(type, pow, WN_Intconst(type, 1));
01613
01614 return WN_Select(type,
01615 WN_EQ(type, band, WN_Zerocon(type)),
01616 WN_Intconst(type, 1),
01617 WN_Intconst(type, -1));
01618 }
01619 case 0:
01620
01621
01622
01623
01624 return WN_EQ(type, pow, WN_Zerocon(type));
01625
01626 case 1:
01627
01628
01629
01630 return WN_Intconst(type, 1);
01631
01632 case 2:
01633 {
01634
01635
01636
01637
01638 WN *ge;
01639 PREG_NUM powN;
01640
01641 powN = AssignExpr(block, pow, type);
01642
01643 ge = WN_GE(type,
01644 WN_LdidPreg(type, powN),
01645 WN_Zerocon(type));
01646
01647 return WN_Shl(type,
01648 ge,
01649 WN_LdidPreg(type, powN));
01650
01651 }
01652 }
01653 }
01654
01655 return NULL;
01656 }
01657
01658
01659
01660
01661
01662
01663
01664
01665
01666
01667 static WN *em_quad_neg(WN *block, WN *tree)
01668 {
01669 TYPE_ID newType;
01670 TYPE_ID type = WN_rtype(tree);
01671 PREG_NUM qN, qNlo;
01672
01673
01674
01675
01676 qN = AssignExpr(block, WN_kid0(tree), type);
01677
01678 if (MTYPE_is_complex(type))
01679 {
01680 newType = MTYPE_C8;
01681 qNlo = qN+2;
01682 }
01683 else
01684 {
01685 newType = MTYPE_F8;
01686 qNlo = qN+1;
01687 }
01688
01689 {
01690 WN *wn, *st;
01691 ST *npreg = MTYPE_To_PREG(newType);
01692
01693 #ifdef TARG_MIPS
01694 wn = WN_LdidPreg(newType, qN);
01695 #else
01696 wn = WN_Neg(newType, WN_LdidPreg(newType, qN));
01697 #endif
01698 st = WN_StidIntoPreg(newType, qN, npreg, wn);
01699 WN_INSERT_BlockLast(block, st);
01700
01701 wn = WN_Neg(newType, WN_LdidPreg(newType, qNlo));
01702 st = WN_StidIntoPreg(newType, qNlo, npreg, wn);
01703 WN_INSERT_BlockLast(block, st);
01704 }
01705 WN_Delete(tree);
01706
01707 return WN_LdidPreg(type, qN);
01708 }
01709
01710
01711 static WN *em_quad_abs(WN *block, WN *tree)
01712 {
01713 TYPE_ID newType;
01714 TYPE_ID type = WN_rtype(tree);
01715 PREG_NUM qN, qNlo;
01716
01717
01718
01719
01720 qN = AssignExpr(block, WN_kid0(tree), type);
01721
01722 Is_True(! MTYPE_is_complex(type), ("em_quad_abs emulates FQ not CQ"));
01723 newType = MTYPE_F8;
01724 qNlo = qN+1;
01725
01726 {
01727 WN *wn, *st;
01728 ST *npreg = MTYPE_To_PREG(newType);
01729
01730 #ifdef TARG_MIPS
01731 wn = WN_LdidPreg(newType, qN);
01732 #else
01733 wn = WN_Abs(newType, WN_LdidPreg(newType, qN));
01734 #endif
01735 st = WN_StidIntoPreg(newType, qN, npreg, wn);
01736 WN_INSERT_BlockLast(block, st);
01737
01738 wn = WN_Abs(newType, WN_LdidPreg(newType, qNlo));
01739 st = WN_StidIntoPreg(newType, qNlo, npreg, wn);
01740 WN_INSERT_BlockLast(block, st);
01741 }
01742 WN_Delete(tree);
01743
01744 return WN_LdidPreg(type, qN);
01745 }
01746
01747
01748
01749
01750
01751
01752
01753
01754
01755
01756
01757
01758
01759 static WN *em_split_select(WN *block, WN *tree)
01760 {
01761 TYPE_ID rtype = WN_rtype(tree);
01762 PREG_NUM qN;
01763 WN *if_then, *if_else;
01764
01765
01766 if_then = WN_CreateBlock();
01767 if_else = WN_CreateBlock();
01768 {
01769 WN *exp1 = WN_kid1(tree);
01770
01771 qN = AssignExpr(if_then, exp1, rtype);
01772 }
01773 {
01774 WN *wn;
01775 WN *exp2 = WN_kid2(tree);
01776 ST *preg = MTYPE_To_PREG(rtype);
01777
01778 wn = WN_StidIntoPreg(rtype, qN, preg, exp2);
01779 WN_INSERT_BlockLast(if_else, wn);
01780 }
01781 {
01782 WN *IF;
01783 WN *cond = WN_kid0(tree);
01784
01785 IF = WN_CreateIf(cond, if_then, if_else);
01786 WN_INSERT_BlockLast(block, IF);
01787 }
01788 WN_Delete(tree);
01789
01790 return WN_LdidPreg(rtype, qN);
01791 }
01792
01793
01794
01795
01796
01797
01798
01799
01800
01801
01802
01803
01804
01805
01806
01807
01808
01809
01810
01811
01812
01813
01814
01815
01816
01817
01818
01819
01820
01821
01822
01823
01824
01825
01826
01827
01828
01829
01830
01831
01832
01833
01834
01835
01836
01837
01838 static WN *em_divfloor(WN *block, TYPE_ID type, WN *x, WN *y)
01839 {
01840 PREG_NUM xN, yN;
01841 WN *numer, *div;
01842
01843 Is_True((MTYPE_is_integral(WN_rtype(x)) &&
01844 MTYPE_is_integral(WN_rtype(y))),
01845 ("em_divfloor() arguments should be type integral"));
01846
01847 xN = AssignExpr(block, x, type);
01848 yN = AssignExpr(block, y, type);
01849
01850 {
01851
01852
01853
01854
01855 TYPE_ID ytype = WN_rtype(y);
01856 WN *sra, *add, *one, *bxor, *mask, *sub, *band;
01857 #ifdef TARG_X8664
01858
01859
01860 if (MTYPE_is_unsigned(ytype) &&
01861 MTYPE_byte_size(ytype) < MTYPE_byte_size(type))
01862 ytype = type;
01863 #endif
01864
01865 sra = WN_Ashr(type,
01866 WN_LdidPreg(type, yN),
01867 WN_Intconst(type, MTYPE_size_reg(ytype)-1));
01868
01869 add = WN_Add(type,
01870 sra,
01871 WN_COPY_Tree(sra));
01872
01873 one = WN_Add(ytype,
01874 add,
01875 WN_Intconst(ytype, 1));
01876
01877
01878
01879
01880 bxor = WN_Bxor(ytype,
01881 WN_LdidPreg(type, xN),
01882 WN_LdidPreg(type, yN));
01883
01884 mask = WN_Ashr(type,
01885 bxor,
01886 WN_Intconst(type, MTYPE_size_reg(type)-1));
01887
01888
01889
01890
01891
01892 sub = WN_Sub(type, one, WN_LdidPreg(type, yN));
01893
01894 band = WN_Band(type, sub, mask);
01895
01896 numer = WN_Add(type, band, WN_LdidPreg(type, xN));
01897 }
01898
01899 div = WN_Div(type, numer, WN_LdidPreg(type, yN));
01900
01901 return div;
01902 }
01903
01904
01905
01906
01907
01908
01909
01910
01911
01912
01913
01914
01915
01916
01917
01918
01919
01920 static WN *em_divceil(WN *block, TYPE_ID type, WN *x, WN*y)
01921 {
01922
01923 WN *divfloor;
01924
01925 divfloor = em_divfloor(block, type, WN_Neg( WN_rtype(x), x), y);
01926
01927 return WN_Neg(type, divfloor);
01928 }
01929
01930
01931
01932
01933
01934
01935
01936
01937
01938
01939
01940
01941
01942
01943
01944 static WN *em_alloca(WN *block, WN *tree)
01945 {
01946 WN *size = WN_arg(tree, 0);
01947 TYPE_ID stype = WN_rtype(size);
01948 TYPE_ID type = WN_rtype(tree);
01949 BOOL stack_decrement = (Stack_Direction() == DECREMENT);
01950
01951 {
01952 WN *add, *adj, *inc, *st;
01953 INT64 stack_alignment;
01954 ST *preg = MTYPE_To_PREG(Pointer_type);
01955
01956 stack_alignment = Stack_Alignment();
01957
01958 add = WN_Add(stype,
01959 size,
01960 WN_Intconst(stype, stack_alignment-1));
01961
01962 adj = WN_Band(stype,
01963 add,
01964 WN_Intconst(stype, -stack_alignment));
01965
01966 inc = WN_Binary(stack_decrement ? OPR_SUB : OPR_ADD,
01967 type,
01968 WN_LdidPreg(Pointer_type, Stack_Pointer_Preg_Offset),
01969 adj);
01970
01971 st = WN_StidIntoPreg(Pointer_type, Stack_Pointer_Preg_Offset, preg, inc);
01972
01973 WN_INSERT_BlockLast(block, st);
01974 }
01975 {
01976
01977
01978
01979 WN *ptr;
01980
01981 Is_True(!Get_Trace(TP_DATALAYOUT, 2),("arg build area not correct"));
01982 ptr = WN_Binary(stack_decrement ? OPR_ADD : OPR_SUB,
01983 type,
01984 WN_LdidPreg(Pointer_type, Stack_Pointer_Preg_Offset),
01985 WN_Intconst(type, Current_PU_Actual_Size));
01986
01987 if ( DEBUG_Trap_Uv )
01988 {
01989 WN *con, *mstore;
01990
01991 con = WN_UVConst(stype);
01992
01993 mstore= aux_CreateMstore(0,
01994 Make_Pointer_Type(MTYPE_To_TY(stype), TRUE),
01995 con,
01996 WN_COPY_Tree(ptr),
01997 WN_COPY_Tree(size));
01998
01999 WN_INSERT_BlockLast(block, mstore);
02000 }
02001
02002 return ptr;
02003 }
02004 }
02005
02006
02007
02008
02009
02010
02011
02012
02013 static WN *em_readstackpointer(TYPE_ID rtype)
02014 {
02015 return WN_LdidPreg(rtype, Stack_Pointer_Preg_Offset);
02016 }
02017
02018 #ifdef KEY
02019
02020
02021
02022
02023
02024
02025
02026 static WN *em_readframepointer(TYPE_ID rtype)
02027 {
02028 return WN_LdidPreg(rtype, Frame_Pointer_Preg_Offset);
02029 }
02030 #endif
02031
02032
02033
02034
02035
02036
02037
02038
02039
02040 static WN *em_setstackpointer(WN *block, TYPE_ID rtype, WN *value)
02041 {
02042 WN *stid;
02043
02044 stid = WN_StidIntoPreg(rtype,
02045 Stack_Pointer_Preg_Offset,
02046 MTYPE_To_PREG(rtype),
02047 value);
02048
02049 WN_INSERT_BlockLast(block, stid);
02050
02051 return WN_LdidPreg(rtype, Stack_Pointer_Preg_Offset);
02052 }
02053
02054 static WN *createParm(WN *x, BOOL byvalue)
02055 {
02056 TYPE_ID type = WN_rtype(x);
02057 TY_IDX ty;
02058
02059 if (WN_operator_is(x, OPR_PARM))
02060 {
02061 return x;
02062 }
02063
02064 ty = MTYPE_To_TY(type);
02065
02066 return WN_CreateParm(type, x, ty,
02067 (byvalue ? WN_PARM_BY_VALUE : WN_PARM_BY_REFERENCE));
02068 }
02069
02070 static WN *Intrinsic(TYPE_ID type, INTRINSIC id, INT32 n, WN *x, WN *y)
02071 {
02072 OPCODE op= OPCODE_make_op (OPR_INTRINSIC_OP, type, MTYPE_V);
02073 WN *wn, *kids[20];
02074 BOOL byvalue = INTRN_by_value(id);
02075
02076 Is_True((n<=20), ("too many arguments for Intrinsic()"));
02077
02078 if (x)
02079 x = createParm(x,byvalue);
02080 if (y)
02081 y = createParm(y,byvalue);
02082
02083 kids[0]= x;
02084 kids[1]= y;
02085
02086 wn = WN_Create_Intrinsic(op, id, n, kids);
02087
02088 return wn;
02089 }
02090
02091
02092
02093
02094
02095
02096
02097 static WN *em_complex_exp(WN *block, WN *x)
02098 {
02099 TYPE_ID type = WN_rtype(x);
02100 TYPE_ID rtype = Mtype_complex_to_real(type);
02101 PREG_NUM zN, expN;
02102 WN *cosine,*sine;
02103 WN *exp;
02104 WN *realpart, *imagpart ;
02105 INTRINSIC expID;
02106 INTRINSIC cosID,sinID;
02107
02108 switch(rtype) {
02109 case MTYPE_F4: expID = INTRN_F4EXP; cosID = INTRN_F4COS; sinID = INTRN_F4SIN; break;
02110 case MTYPE_F8: expID = INTRN_F8EXP; cosID = INTRN_F8COS; sinID = INTRN_F8SIN; break;
02111 case MTYPE_FQ: expID = INTRN_FQEXP; cosID = INTRN_FQCOS; sinID = INTRN_FQSIN; break;
02112 }
02113
02114 zN = AssignExpr(block, x, type);
02115 exp= Intrinsic(rtype,
02116 expID,
02117 1,
02118 WN_Realpart(rtype,WN_LdidPreg(type, zN)), NULL);
02119
02120 expN = AssignExpr(block, exp, rtype);
02121
02122 cosine = Intrinsic(rtype,
02123 cosID,
02124 1,
02125 WN_Imagpart(rtype,WN_LdidPreg(type, zN)), NULL);
02126
02127 sine = Intrinsic(rtype,
02128 sinID,
02129 1,
02130 WN_Imagpart(rtype,WN_LdidPreg(type, zN)), NULL);
02131
02132
02133
02134
02135
02136
02137 realpart = WN_Mpy(rtype,
02138 WN_LdidPreg(rtype, expN),
02139 cosine);
02140
02141 imagpart = WN_Mpy(rtype,
02142 WN_LdidPreg(rtype, expN),
02143 sine);
02144
02145 return WN_Complex(type, realpart, imagpart);
02146 }
02147
02148
02149
02150
02151
02152
02153
02154
02155
02156 static WN *em_complex_cos(WN *block, WN *x)
02157 {
02158 TYPE_ID type = WN_rtype(x);
02159 TYPE_ID rtype = Mtype_complex_to_real(type);
02160 PREG_NUM zN;
02161 WN *realpart, *imagpart ;
02162
02163 zN = AssignExpr(block, x, type);
02164
02165 {
02166 INTRINSIC cosID;
02167 INTRINSIC coshID;
02168 WN *cos, *cosh;
02169
02170 switch(rtype)
02171 {
02172 case MTYPE_F4:
02173 cosID = INTRN_F4COS;
02174 coshID = INTRN_F4COSH;
02175 break;
02176 case MTYPE_F8:
02177 cosID = INTRN_F8COS;
02178 coshID = INTRN_F8COSH;
02179 break;
02180 case MTYPE_FQ:
02181 cosID = INTRN_FQCOS;
02182 coshID = INTRN_FQCOSH;
02183 break;
02184 }
02185 cos= Intrinsic(rtype,
02186 cosID,
02187 1,
02188 WN_Realpart(rtype,WN_LdidPreg(type, zN)), NULL);
02189 cosh= Intrinsic(rtype,
02190 coshID,
02191 1,
02192 WN_Imagpart(rtype,WN_LdidPreg(type, zN)), NULL);
02193
02194
02195
02196
02197 realpart = WN_Mpy(rtype, cos, cosh);
02198 }
02199 {
02200 INTRINSIC sinID, sinhID;
02201 WN *sin, *sinh;
02202
02203 switch(rtype)
02204 {
02205 case MTYPE_F4:
02206 sinID = INTRN_F4SIN;
02207 sinhID = INTRN_F4SINH;
02208 break;
02209 case MTYPE_F8:
02210 sinID = INTRN_F8SIN;
02211 sinhID = INTRN_F8SINH;
02212 break;
02213 case MTYPE_FQ:
02214 sinID = INTRN_FQSIN;
02215 sinhID = INTRN_FQSINH;
02216 break;
02217 }
02218
02219 sin= Intrinsic(rtype,
02220 sinID,
02221 1,
02222 WN_Realpart(rtype,WN_LdidPreg(type, zN)), NULL);
02223 sinh= Intrinsic(rtype,
02224 sinhID,
02225 1,
02226 WN_Imagpart(rtype,WN_LdidPreg(type, zN)), NULL);
02227
02228
02229
02230 imagpart = WN_Neg(rtype, WN_Mpy(rtype, sin, sinh));
02231 }
02232 return WN_Complex(type, realpart, imagpart);
02233 }
02234
02235
02236
02237
02238
02239
02240
02241
02242
02243 static WN *em_complex_sin(WN *block, WN *x)
02244 {
02245 TYPE_ID type = WN_rtype(x);
02246 TYPE_ID rtype = Mtype_complex_to_real(type);
02247 PREG_NUM zN;
02248 WN *realpart, *imagpart ;
02249
02250 zN = AssignExpr(block, x, type);
02251
02252 {
02253 INTRINSIC sinID, coshID;
02254 WN *sin, *cosh;
02255
02256 switch(rtype)
02257 {
02258 case MTYPE_F4:
02259 sinID = INTRN_F4SIN;
02260 coshID = INTRN_F4COSH;
02261 break;
02262 case MTYPE_F8:
02263 sinID = INTRN_F8SIN;
02264 coshID = INTRN_F8COSH;
02265 break;
02266 case MTYPE_FQ:
02267 sinID = INTRN_FQSIN;
02268 coshID = INTRN_FQCOSH;
02269 break;
02270 }
02271 sin= Intrinsic(rtype,
02272 sinID,
02273 1,
02274 WN_Realpart(rtype,WN_LdidPreg(type, zN)), NULL);
02275
02276 cosh= Intrinsic(rtype,
02277 coshID,
02278 1,
02279 WN_Imagpart(rtype,WN_LdidPreg(type, zN)), NULL);
02280
02281
02282
02283
02284 realpart = WN_Mpy(rtype, sin, cosh);
02285 }
02286 {
02287 INTRINSIC cosID, sinhID;
02288 WN *cos, *sinh;
02289
02290 switch(rtype)
02291 {
02292 case MTYPE_F4:
02293 cosID = INTRN_F4COS;
02294 sinhID = INTRN_F4SINH;
02295 break;
02296 case MTYPE_F8:
02297 cosID = INTRN_F8COS;
02298 sinhID = INTRN_F8SINH;
02299 break;
02300 case MTYPE_FQ:
02301 cosID = INTRN_FQCOS;
02302 sinhID = INTRN_FQSINH;
02303 break;
02304 }
02305
02306 cos= Intrinsic(rtype,
02307 cosID,
02308 1,
02309 WN_Realpart(rtype,WN_LdidPreg(type, zN)), NULL);
02310 sinh= Intrinsic(rtype,
02311 sinhID,
02312 1,
02313 WN_Imagpart(rtype,WN_LdidPreg(type, zN)), NULL);
02314
02315
02316
02317 imagpart = WN_Mpy(rtype, cos, sinh);
02318 }
02319 return WN_Complex(type, realpart, imagpart);
02320 }
02321
02322
02323
02324
02325
02326
02327
02328
02329
02330
02331
02332
02333
02334
02335
02336 static WN *em_preg_hypot(WN *block, TYPE_ID type, PREG_NUM xN, PREG_NUM yN)
02337 {
02338 if (Fast_Complex_Allowed)
02339 {
02340
02341
02342
02343
02344 WN *x2, *y2, *add, *hypot;
02345
02346 x2 = WN_Mpy(type,
02347 WN_LdidPreg(type, xN),
02348 WN_LdidPreg(type, xN));
02349
02350 y2 = WN_Mpy(type,
02351 WN_LdidPreg(type, yN),
02352 WN_LdidPreg(type, yN));
02353
02354 add = WN_Add(type, x2, y2);
02355
02356 hypot = WN_Sqrt(type, add);
02357
02358 return hypot;
02359 }
02360 else
02361 {
02362
02363
02364
02365
02366
02367
02368
02369
02370
02371
02372
02373
02374
02375 PREG_NUM axN, ayN, zN, divN;
02376
02377 WN *cond, *w, *z, *div, *mpy, *add, *sqrt, *hypot, *az;
02378
02379 axN = AssignExpr(block,
02380 WN_Abs(type, WN_LdidPreg(type, xN)),
02381 type);
02382
02383 ayN = AssignExpr(block,
02384 WN_Abs(type, WN_LdidPreg(type, yN)),
02385 type);
02386
02387
02388
02389
02390
02391
02392
02393 cond = WN_GT(type,
02394 WN_LdidPreg(type, axN),
02395 WN_LdidPreg(type, ayN)),
02396
02397 w = WN_Select(type,
02398 cond,
02399 WN_LdidPreg(type, yN),
02400 WN_LdidPreg(type, xN));
02401
02402 cond = WN_GT(type,
02403 WN_LdidPreg(type, axN),
02404 WN_LdidPreg(type, ayN));
02405
02406 z = WN_Select(type,
02407 cond,
02408 WN_LdidPreg(type, xN),
02409 WN_LdidPreg(type, yN));
02410
02411 zN = AssignExpr(block, z, type);
02412
02413 div = WN_Div(type,
02414 w,
02415 WN_LdidPreg(type, zN));
02416
02417 divN = AssignExpr(block, div, type);
02418
02419
02420
02421
02422 mpy = WN_Mpy(type,
02423 WN_LdidPreg(type, divN),
02424 WN_LdidPreg(type, divN));
02425
02426 add = WN_Add(type,
02427 WN_Floatconst(type, 1.0),
02428 mpy);
02429
02430 sqrt = WN_Sqrt(type, add);
02431
02432 az = WN_Abs(type, WN_LdidPreg(type, zN));
02433
02434 hypot = WN_Mpy(type, sqrt, az);
02435
02436 return hypot;
02437 }
02438 }
02439
02440
02441
02442
02443
02444 static WN *em_hypot(WN *block, WN *x, WN *y)
02445 {
02446 TYPE_ID type = WN_rtype(x);
02447 PREG_NUM xN, yN;
02448
02449 Is_True((type == WN_rtype(y)), ("em_hypot(): type mismatch"));
02450
02451 xN = AssignExpr(block, x, type);
02452 yN = AssignExpr(block, y, type);
02453
02454 return em_preg_hypot(block, type, xN, yN);
02455 }
02456
02457
02458
02459
02460
02461
02462
02463
02464
02465 static WN *em_complex_log(WN *block, WN *x)
02466 {
02467 PREG_NUM zN;
02468 WN *hypot, *realpart, *imagpart ;
02469 TYPE_ID type = WN_rtype(x);
02470 TYPE_ID rtype = Mtype_complex_to_real(type);
02471
02472 zN = AssignExpr(block, x, type);
02473
02474
02475
02476
02477 hypot = em_hypot(block,
02478 WN_Realpart(rtype,WN_LdidPreg(type,zN)),
02479 WN_Imagpart(rtype,WN_LdidPreg(type,zN)));
02480
02481
02482 {
02483 INTRINSIC logID;
02484
02485 switch(rtype)
02486 {
02487 case MTYPE_F4: logID = INTRN_F4LOG; break;
02488 case MTYPE_F8: logID = INTRN_F8LOG; break;
02489 case MTYPE_FQ: logID = INTRN_FQLOG; break;
02490 }
02491
02492 realpart= Intrinsic(rtype, logID, 1, hypot, NULL);
02493 }
02494 {
02495 INTRINSIC atan2ID;
02496
02497 switch(rtype)
02498 {
02499 case MTYPE_F4: atan2ID = INTRN_F4ATAN2; break;
02500 case MTYPE_F8: atan2ID = INTRN_F8ATAN2; break;
02501 case MTYPE_FQ: atan2ID = INTRN_FQATAN2; break;
02502 }
02503 imagpart= Intrinsic(rtype, atan2ID, 2,
02504 WN_Imagpart(rtype,WN_LdidPreg(type, zN)),
02505 WN_Realpart(rtype,WN_LdidPreg(type, zN)));
02506
02507 }
02508 return WN_Complex(type, realpart, imagpart);
02509 }
02510
02511
02512
02513
02514
02515
02516
02517
02518 static WN *em_complex_abs(WN *block, WN *z)
02519 {
02520 PREG_NUM zN;
02521 WN *hypot;
02522 TYPE_ID type = WN_rtype(z);
02523 TYPE_ID rtype = Mtype_complex_to_real(type);
02524
02525 zN = AssignExpr(block, z, type);
02526
02527 if (Fast_Complex_Allowed==FALSE)
02528 {
02529
02530
02531
02532
02533 WN *if_else;
02534
02535 if_else = WN_CreateBlock();
02536
02537 hypot = em_hypot(if_else,
02538 WN_Realpart(rtype,WN_LdidPreg(type,zN)),
02539 WN_Imagpart(rtype,WN_LdidPreg(type,zN)));
02540
02541 hypot = checkForZero(block, type, zN, if_else, hypot);
02542 }
02543 else
02544 {
02545 hypot = em_hypot(block,
02546 WN_Realpart(rtype,WN_LdidPreg(type,zN)),
02547 WN_Imagpart(rtype,WN_LdidPreg(type,zN)));
02548 }
02549
02550 return hypot;
02551 }
02552
02553
02554
02555
02556
02557
02558
02559
02560
02561
02562
02563
02564
02565
02566
02567
02568
02569
02570
02571
02572
02573
02574
02575
02576
02577
02578 static WN *em_complex_sqrt_preg(WN *block, TYPE_ID type, PREG_NUM zN_in)
02579 {
02580 PREG_NUM ziN, zN, absN, t1N, t2N, t3N;
02581 TYPE_ID rtype = Mtype_complex_to_real(type);
02582
02583 zN = AssignExpr(block,WN_Realpart(rtype,WN_LdidPreg(type,zN_in)),rtype);
02584 ziN = AssignExpr(block,WN_Imagpart(rtype,WN_LdidPreg(type,zN_in)),rtype);
02585
02586 {
02587
02588
02589
02590 WN *norm, *add, *mpy, *sqrt;
02591
02592 norm = em_preg_hypot(block, rtype, zN, ziN);
02593
02594 absN = AssignExpr(block, norm, rtype);
02595
02596 add = WN_Add(rtype,
02597 WN_LdidPreg(rtype, absN),
02598 WN_Abs(rtype, WN_LdidPreg(rtype, zN)));
02599
02600 mpy = WN_Mpy(rtype,
02601 add,
02602 WN_Floatconst(rtype, .5000));
02603
02604 sqrt = WN_Sqrt(rtype, mpy);
02605
02606 t1N = AssignExpr(block, sqrt, rtype);
02607 }
02608 {
02609
02610
02611
02612 WN *le, *lt, *cond, *neg, *sel;
02613
02614 le = WN_LE(rtype,
02615 WN_LdidPreg(rtype, zN),
02616 WN_Zerocon(rtype));
02617
02618 lt = WN_LT(rtype,
02619 WN_LdidPreg(rtype, ziN),
02620 WN_Zerocon(rtype));
02621
02622 cond = WN_LAND(le, lt);
02623
02624 neg = WN_Neg(rtype, WN_LdidPreg(rtype, t1N));
02625
02626 sel = WN_Select(rtype,
02627 cond,
02628 neg,
02629 WN_LdidPreg(rtype, t1N));
02630
02631 t2N = AssignExpr(block, sel, rtype);
02632 }
02633 {
02634
02635
02636
02637 WN *div, *mpy;
02638
02639 div = WN_Div(rtype,
02640 WN_LdidPreg(rtype, ziN),
02641 WN_LdidPreg(rtype, t2N));
02642
02643 mpy = WN_Mpy(rtype,
02644 div,
02645 WN_Floatconst(rtype, .5000));
02646
02647 t3N = AssignExpr(block, mpy, rtype);
02648 }
02649 {
02650
02651
02652
02653
02654 WN *gt, *realpart, *imagpart;
02655
02656 gt = WN_GT(rtype,
02657 WN_LdidPreg(rtype, zN),
02658 WN_Zerocon(rtype));
02659
02660 realpart = WN_Select(rtype,
02661 gt,
02662 WN_LdidPreg(rtype, t2N),
02663 WN_LdidPreg(rtype, t3N));
02664
02665 gt = WN_GT(rtype,
02666 WN_LdidPreg(rtype, zN),
02667 WN_Zerocon(rtype));
02668
02669 imagpart = WN_Select(rtype,
02670 gt,
02671 WN_LdidPreg(rtype, t3N),
02672 WN_LdidPreg(rtype, t2N));
02673
02674 return WN_Complex(type, realpart, imagpart);
02675 }
02676 }
02677
02678
02679
02680
02681
02682
02683
02684 static WN *em_complex_sqrt(WN *block, WN *z)
02685 {
02686 PREG_NUM zN;
02687 WN *sqrt, *if_else;
02688 TYPE_ID type = WN_rtype(z);
02689
02690 zN = AssignExpr(block, z, type);
02691
02692 if_else = WN_CreateBlock();
02693
02694 sqrt = em_complex_sqrt_preg(if_else, type, zN);
02695
02696 sqrt = checkForZero(block, type, zN, if_else, sqrt);
02697
02698 return sqrt;
02699 }
02700
02701
02702
02703
02704
02705
02706
02707
02708
02709 static WN *em_conjg(WN *block, WN *x)
02710 {
02711 PREG_NUM zN;
02712 TYPE_ID type = WN_rtype(x);
02713 TYPE_ID rtype = Mtype_complex_to_real(type);
02714 WN *realpart, *imagpart;
02715
02716 zN = AssignExpr(block, x, type);
02717
02718 realpart = WN_Realpart(rtype, WN_LdidPreg(type, zN));
02719
02720 imagpart = WN_Neg(rtype,
02721 WN_Imagpart(rtype, WN_LdidPreg(type, zN)));
02722 return WN_Complex(type, realpart, imagpart);
02723 }
02724
02725
02726
02727
02728
02729
02730
02731
02732 #define M_LOG10 0.4342944819032518276511289189166050822943970058036665661144537831658646492088707747292249493384317483
02733 #define M_LOG10Q 0.434294481903251827651128918916605082294L
02734 static WN *em_alog10(WN *block, WN *x)
02735 {
02736 TYPE_ID type = WN_rtype(x);
02737 INTRINSIC logID;
02738 WN *log, *mpy;
02739
02740 switch(type)
02741 {
02742 case MTYPE_F4: logID = INTRN_F4LOG; break;
02743 case MTYPE_F8: logID = INTRN_F8LOG; break;
02744 case MTYPE_FQ: logID = INTRN_FQLOG; break;
02745 }
02746
02747 log = Intrinsic(type, logID, 1, x, NULL);
02748
02749 if (type != MTYPE_FQ) {
02750 mpy = WN_Mpy(type,
02751 WN_Floatconst(type, M_LOG10),
02752 log);
02753 } else {
02754 mpy = WN_Mpy(type,
02755 Make_Const(Host_To_Targ_Quad(M_LOG10Q)),
02756 log);
02757 }
02758 return mpy;
02759 }
02760
02761
02762
02763
02764
02765
02766
02767
02768
02769
02770 static WN *em_bclr(WN *block, WN *n, WN *i)
02771 {
02772 TYPE_ID type = WN_rtype(n);
02773 PREG_NUM iN;
02774 WN *cond, *band;
02775
02776 iN = AssignExpr(block, i, type);
02777 {
02778
02779
02780
02781 WN *shft, *bnot;
02782
02783 shft = WN_Shl(type,
02784 WN_Intconst(type, 1),
02785 WN_LdidPreg(type, iN));
02786
02787 bnot = WN_Bnot(type, shft);
02788
02789 band = WN_Band(type, n, bnot);
02790
02791 if (Fast_Bit_Allowed)
02792 return band;
02793 }
02794 {
02795
02796
02797
02798
02799 WN *le, *lt;
02800
02801 le = WN_LE(Mtype_comparison(type),
02802 WN_Zerocon(type),
02803 WN_LdidPreg(type, iN));
02804 lt = WN_LT( Mtype_comparison(type),
02805 WN_LdidPreg(type, iN),
02806 WN_Intconst(type, MTYPE_size_reg(type)));
02807 cond = WN_LAND(le, lt);
02808 }
02809 return WN_Select(type, cond, band, WN_Zerocon(type));
02810 }
02811
02812
02813
02814
02815
02816
02817
02818
02819
02820
02821 static WN *em_parity(WN *block, WN *wn)
02822 {
02823 TYPE_ID type = WN_rtype(wn);
02824 INT bitsize = MTYPE_size_reg(type);
02825
02826 if ((WN_operator(wn) == OPR_LDID || WN_operator(wn) == OPR_ILOAD)
02827 && bitsize > MTYPE_size_reg(WN_desc(wn))) {
02828 bitsize = MTYPE_size_reg(WN_desc(wn));
02829 }
02830 PREG_NUM preg = AssignExpr( block, wn, type );
02831
02832
02833 if (bitsize > 32) {
02834 wn = WN_Ashr( type, WN_LdidPreg(type, preg), WN_Intconst(MTYPE_I4, 32) );
02835 wn = WN_Bxor( type, wn, WN_LdidPreg(type, preg) );
02836 preg = AssignExpr( block, wn, type );
02837 }
02838
02839 if (bitsize > 16) {
02840 wn = WN_Ashr( type, WN_LdidPreg(type, preg), WN_Intconst(MTYPE_I4, 16) );
02841 wn = WN_Bxor( type, wn, WN_LdidPreg(type, preg) );
02842 preg = AssignExpr( block, wn, type );
02843 }
02844
02845 if (bitsize > 8) {
02846 wn = WN_Ashr( type, WN_LdidPreg(type, preg), WN_Intconst(MTYPE_I4, 8) );
02847 wn = WN_Bxor( type, wn, WN_LdidPreg(type, preg) );
02848 preg = AssignExpr( block, wn, type );
02849 }
02850
02851 wn = WN_Ashr( type, WN_LdidPreg(type, preg), WN_Intconst(MTYPE_I4, 4) );
02852 wn = WN_Bxor( type, wn, WN_LdidPreg(type, preg) );
02853
02854
02855 wn = WN_Band( type, wn, WN_Intconst(MTYPE_I4, 15) );
02856 wn = WN_Ashr( MTYPE_I4, WN_Intconst(MTYPE_I4, 0x6996), wn );
02857 wn = WN_Band( MTYPE_I4, wn, WN_Intconst(MTYPE_I4, 1) );
02858 return wn;
02859 }
02860
02861
02862
02863
02864
02865
02866
02867
02868
02869
02870
02871
02872
02873
02874 static WN *em_popcount(WN *block, WN *wn, INT bitsize)
02875 {
02876 if ( bitsize == 0 ) {
02877 Fail_FmtAssertion("em_popcount: expected nonzero bitsize");
02878 }
02879 TYPE_ID type = WN_rtype(wn);
02880
02881
02882 PREG_NUM preg = AssignExpr( block, wn, type );
02883 UINT64 mask = 0x5555555555555555ULL >> (64 - bitsize);
02884 WN *wn1 = WN_Intconst(type, mask);
02885 wn = WN_Ashr( type, WN_LdidPreg(type, preg), WN_Intconst(MTYPE_I4, 1) );
02886 wn = WN_Band( type, wn, wn1 );
02887 wn = WN_Sub( type, WN_LdidPreg(type, preg), wn );
02888
02889
02890 preg = AssignExpr( block, wn, type );
02891 mask = 0x3333333333333333ULL >> (64 - bitsize);
02892 wn1 = WN_Intconst(type, mask);
02893 PREG_NUM preg1 = AssignExpr( block, wn1, type );
02894 wn = WN_Band( type, WN_LdidPreg(type, preg), WN_LdidPreg(type, preg1) );
02895 wn1 = WN_Ashr( type, WN_LdidPreg(type, preg), WN_Intconst(MTYPE_I4, 2) );
02896 wn1 = WN_Band( type, wn1, WN_LdidPreg(type, preg1) );
02897 wn = WN_Add( type, wn, wn1 );
02898
02899
02900 preg = AssignExpr( block, wn, type );
02901 mask = 0x0f0f0f0f0f0f0f0fULL >> (64 - bitsize);
02902 wn1 = WN_Intconst(type, mask);
02903 wn = WN_Ashr( type, WN_LdidPreg(type, preg), WN_Intconst(MTYPE_I4, 4) );
02904 wn = WN_Add( type, WN_LdidPreg(type, preg), wn );
02905 wn = WN_Band( type, wn, wn1 );
02906
02907 if (bitsize > 8) {
02908
02909 preg = AssignExpr( block, wn, type );
02910 wn = WN_Ashr( type, WN_LdidPreg(type, preg), WN_Intconst(MTYPE_I4, 8) );
02911 wn = WN_Add( type, WN_LdidPreg(type, preg), wn );
02912 }
02913
02914 if (bitsize > 16) {
02915
02916 preg = AssignExpr( block, wn, type );
02917 wn = WN_Ashr( type, WN_LdidPreg(type, preg), WN_Intconst(MTYPE_I4, 16) );
02918 wn = WN_Add( type, WN_LdidPreg(type, preg), wn );
02919 }
02920
02921 if (bitsize > 32) {
02922
02923 preg = AssignExpr( block, wn, type );
02924 wn = WN_Ashr( type, WN_LdidPreg(type, preg), WN_Intconst(MTYPE_I4, 32) );
02925 wn = WN_Add( type, WN_LdidPreg(type, preg), wn );
02926 }
02927
02928 if (bitsize > 8) {
02929
02930
02931 wn = WN_CreateCvtl( OPC_U4CVTL, 8, wn );
02932 }
02933
02934 return wn;
02935 }
02936
02937
02938
02939
02940
02941
02942
02943
02944
02945
02946 static WN *em_bset(WN *block, WN *n, WN *i)
02947 {
02948 TYPE_ID type = WN_rtype(n);
02949 PREG_NUM iN;
02950 WN *cond, *bor;
02951
02952 iN = AssignExpr(block, i, type);
02953 {
02954
02955
02956
02957 WN *shft;
02958
02959 shft = WN_Shl(type,
02960 WN_Intconst(type, 1),
02961 WN_LdidPreg(type, iN));
02962
02963 bor = WN_Bior(type, n, shft);
02964
02965 if (Fast_Bit_Allowed)
02966 return bor;
02967 }
02968 {
02969
02970
02971
02972
02973 WN *le, *lt;
02974
02975 le = WN_LE(Mtype_comparison(type),
02976 WN_Zerocon(type),
02977 WN_LdidPreg(type, iN));
02978 lt = WN_LT(Mtype_comparison(type),
02979 WN_LdidPreg(type, iN),
02980 WN_Intconst(type, MTYPE_size_reg(type)));
02981 cond = WN_LAND(le, lt);
02982 }
02983 return WN_Select(type, cond, bor, WN_Zerocon(type));
02984 }
02985
02986
02987
02988
02989
02990
02991
02992
02993 static WN *em_btest(WN *block, WN *n, WN *i)
02994 {
02995 TYPE_ID type = WN_rtype(n);
02996 PREG_NUM iN;
02997 WN *cond, *band;
02998
02999 iN = AssignExpr(block, i, type);
03000 {
03001
03002
03003
03004 WN *shft;
03005
03006 shft = WN_Lshr(type,
03007 n,
03008 WN_LdidPreg(type, iN));
03009
03010 band = WN_Band(type, shft, WN_Intconst(type, 1));
03011
03012 if (Fast_Bit_Allowed)
03013 return band;
03014 }
03015 {
03016
03017
03018
03019
03020 WN *le, *lt;
03021
03022 le = WN_LE(Mtype_comparison(type),
03023 WN_Zerocon(type),
03024 WN_LdidPreg(type, iN));
03025 lt = WN_LT(Mtype_comparison(type),
03026 WN_LdidPreg(type, iN),
03027 WN_Intconst(type, MTYPE_size_reg(type)));
03028 cond = WN_LAND(le, lt);
03029 }
03030 return WN_Select(type, cond, band, WN_Zerocon(type));
03031 }
03032
03033
03034
03035
03036
03037
03038
03039
03040
03041
03042
03043
03044 static WN *WN_mask(TYPE_ID type, PREG_NUM m)
03045 {
03046 WN *gt, *neg, *sub;
03047 gt = WN_GT(type, WN_LdidPreg(type, m), WN_Zerocon(type));
03048 gt = WN_Int_Type_Conversion(gt,type);
03049 neg = WN_Neg(type, gt);
03050 sub = WN_Sub(type, WN_Intconst(type, MTYPE_size_reg(type)), WN_LdidPreg(type, m));
03051 return WN_Lshr(type, neg, sub);
03052 }
03053
03054
03055
03056
03057
03058
03059
03060
03061
03062
03063 static WN *em_mask(TYPE_ID type, WN *x, PREG_NUM m)
03064 {
03065 WN *mask;
03066
03067 mask = WN_mask(type, m);
03068
03069 return WN_Band(type, x, mask);
03070 }
03071
03072
03073
03074
03075
03076
03077
03078
03079
03080 static WN *em_mask_complement(TYPE_ID type, WN *x, PREG_NUM m)
03081 {
03082 WN *mask, *bnot;
03083
03084 mask = WN_mask(type, m);
03085
03086 bnot =WN_Bnot(type, mask);
03087
03088 return WN_Band(type, x, bnot);
03089 }
03090
03091
03092
03093
03094
03095
03096
03097
03098
03099
03100 static WN *em_bits(WN *block, WN *n, WN *i, WN *len)
03101 {
03102 TYPE_ID type = WN_rtype(n);
03103 TYPE_ID desc = WN_desc(n);
03104 PREG_NUM iN, lenN, nN;
03105 WN *cond, *band;
03106
03107 iN = AssignExpr(block, i, desc);
03108 nN = AssignExpr(block, n, desc);
03109 lenN = AssignExpr(block, len, desc);
03110 {
03111
03112
03113
03114
03115 WN *shft;
03116
03117 shft = WN_Lshr(type,
03118 WN_LdidPreg(type, nN),
03119 WN_LdidPreg(type, iN));
03120
03121 band = em_mask(type, shft, lenN);
03122
03123 if (Fast_Bit_Allowed)
03124 return band;
03125 }
03126 {
03127
03128
03129
03130
03131
03132
03133
03134
03135
03136 WN *le, *lt, *land, *add;
03137
03138 le = WN_LE(Mtype_comparison(type),
03139 WN_Zerocon(type),
03140 WN_LdidPreg(type, iN));
03141 lt = WN_LT(Mtype_comparison(type),
03142 WN_LdidPreg(type, iN),
03143 WN_Intconst(type, MTYPE_size_reg(type)));
03144 land = WN_LAND(le, lt);
03145
03146 le = WN_LE(Mtype_comparison(type),
03147 WN_Zerocon(type),
03148 WN_LdidPreg(type, lenN));
03149 land = WN_LAND(land, le);
03150
03151 add = WN_Add(type,
03152 WN_LdidPreg(type, iN),
03153 WN_LdidPreg(type, lenN));
03154
03155 lt = WN_LE(Mtype_comparison(type),
03156 add,
03157 WN_Intconst(type, MTYPE_size_reg(desc)));
03158 cond = WN_LAND(land, lt);
03159 }
03160 return WN_Select(type, cond, band, WN_LdidPreg(type, nN));
03161 }
03162
03163
03164
03165
03166
03167
03168
03169
03170
03171 static WN *em_shl(WN *block, WN *n, WN *i)
03172 {
03173 TYPE_ID type = WN_rtype(n);
03174 TYPE_ID desc = WN_desc(n);
03175 PREG_NUM iN, nN;
03176
03177 iN = AssignExpr(block, i, desc);
03178 nN = AssignExpr(block, n, desc);
03179 {
03180
03181
03182
03183
03184
03185
03186 WN *shl, *lt;
03187
03188 shl = WN_Shl(type,
03189 WN_LdidPreg(desc, nN),
03190 WN_LdidPreg(desc, iN));
03191
03192 if (Fast_Bit_Allowed)
03193 return shl;
03194
03195 lt = WN_LT(Mtype_comparison(type),
03196 WN_LdidPreg(desc, iN),
03197 WN_Intconst(type, MTYPE_size_reg(desc)));
03198
03199 return WN_Select(type, lt, shl, WN_Zerocon(type));
03200 }
03201 }
03202
03203
03204
03205
03206
03207
03208
03209
03210
03211 static WN *em_lshr(WN *block, WN *n, WN *i)
03212 {
03213 TYPE_ID type = WN_rtype(n);
03214 TYPE_ID desc = WN_desc(n);
03215 PREG_NUM iN, nN;
03216
03217 iN = AssignExpr(block, i, desc);
03218 nN = AssignExpr(block, n, desc);
03219 {
03220
03221
03222
03223 WN *val, *sub, *lt, *shr;
03224 PREG_NUM subN;
03225
03226 val = WN_Lshr(type, WN_LdidPreg(type, nN), WN_LdidPreg(type, iN));
03227
03228 sub = WN_Sub(type,
03229 WN_Intconst(type, MTYPE_size_reg(desc)),
03230 WN_LdidPreg(type, iN));
03231
03232 subN = AssignExpr(block, sub, type);
03233
03234 shr = em_mask(type, val, subN);
03235
03236 if (Fast_Bit_Allowed)
03237 return shr;
03238
03239 lt = WN_LT(Mtype_comparison(type),
03240 WN_LdidPreg(desc, iN),
03241 WN_Intconst(type, MTYPE_size_reg(desc)));
03242
03243 return WN_Select(type, lt, shr, WN_Zerocon(type));
03244 }
03245 }
03246
03247
03248
03249
03250
03251
03252
03253
03254
03255
03256 static WN *em_shft(WN *block, WN *n, WN *i)
03257 {
03258 TYPE_ID type = WN_rtype(n);
03259 TYPE_ID desc = WN_desc(n);
03260 WN *v1, *v2;
03261 PREG_NUM iN, nN;
03262
03263 iN = AssignExpr(block, i, type);
03264 nN = AssignExpr(block, n, type);
03265 {
03266
03267
03268
03269 v1 = WN_Shl(type,
03270 WN_LdidPreg(type, nN),
03271 WN_LdidPreg(type, iN));
03272 }
03273 {
03274
03275
03276
03277 WN *neg, *val, *add;
03278 PREG_NUM addN;
03279
03280 neg = WN_Neg(type, WN_LdidPreg(type, iN));
03281
03282 val = WN_Lshr(type, WN_LdidPreg(type, nN), neg);
03283
03284 add = WN_Add(type,
03285 WN_Intconst(type, MTYPE_size_reg(desc)),
03286 WN_LdidPreg(type, iN));
03287
03288 addN = AssignExpr(block, add, type);
03289
03290 v2 = em_mask(type, val, addN);
03291 }
03292 {
03293
03294
03295
03296
03297
03298
03299
03300 WN *abs, *lt, *ge, *select;
03301
03302 ge = WN_GE(Mtype_comparison(type),
03303 WN_LdidPreg(type, iN),
03304 WN_Zerocon(type));
03305
03306 select = WN_Select(type, ge, v1, v2);
03307
03308 if (Fast_Bit_Allowed)
03309 return select;
03310
03311 abs = WN_Abs(type, WN_LdidPreg(type, iN));
03312
03313 lt = WN_LT(Mtype_comparison(type),
03314 abs,
03315 WN_Intconst(type, MTYPE_size_reg(desc)));
03316
03317 return WN_Select(type, lt, select, WN_Zerocon(type));
03318 }
03319 }
03320
03321
03322
03323
03324
03325
03326
03327
03328
03329
03330
03331
03332
03333
03334
03335
03336
03337
03338
03339
03340
03341
03342
03343
03344
03345
03346
03347 static WN *em_shftc(WN *block, WN *m, WN *k, WN *ic)
03348 {
03349 TYPE_ID type = WN_rtype(m);
03350 TYPE_ID desc = WN_desc(m);
03351 WN *shiftc;
03352 PREG_NUM mN, kN, icN, kabsN, s1N, s2N;
03353
03354 mN = AssignExpr(block, m, desc);
03355 kN = AssignExpr(block, k, desc);
03356 icN = AssignExpr(block, ic, desc);
03357
03358 kabsN = AssignExpr(block,
03359 WN_Abs(type, WN_LdidPreg(type, kN)),
03360 type);
03361 {
03362
03363
03364
03365
03366 PREG_NUM subN;
03367 WN *sub, *gt, *s1, *s2;
03368
03369 sub = WN_Sub(type,
03370 WN_LdidPreg(type, icN),
03371 WN_LdidPreg(type, kabsN));
03372 subN = AssignExpr(block, sub, type);
03373
03374 gt = WN_GT(Mtype_comparison(type),
03375 WN_LdidPreg(type, kN),
03376 WN_Zerocon(type));
03377
03378 s1 = WN_Select(type, gt,
03379 WN_LdidPreg(type, kabsN),
03380 WN_LdidPreg(type, subN));
03381
03382 s2 = WN_Select(type, WN_COPY_Tree(gt),
03383 WN_LdidPreg(type, subN),
03384 WN_LdidPreg(type, kabsN));
03385
03386 s1N = AssignExpr(block, s1, type);
03387 s2N = AssignExpr(block, s2, type);
03388 }
03389 {
03390
03391
03392
03393
03394
03395
03396
03397 WN *band, *b1, *b2, *b3;
03398
03399 b1 = em_mask_complement(type, WN_LdidPreg(type, mN), icN);
03400
03401 band = em_mask(type, WN_LdidPreg(type, mN), s2N);
03402
03403 b2 = WN_Shl(type,
03404 band,
03405 WN_LdidPreg(type, s1N));
03406
03407 band = em_mask(type, WN_LdidPreg(type, mN), icN);
03408
03409 b3 = WN_Lshr(type,
03410 band,
03411 WN_LdidPreg(type, s2N));
03412
03413 shiftc = WN_Bior(type,
03414 b1,
03415 WN_Bior(type, b2, b3));
03416
03417 if (Fast_Bit_Allowed)
03418 return shiftc;
03419 }
03420 {
03421
03422
03423
03424
03425
03426
03427
03428
03429 WN *le1, *le2, *land, *le, *cond;
03430
03431 le1 = WN_LE(Mtype_comparison(type),
03432 WN_Intconst(type, 1),
03433 WN_LdidPreg(type, kabsN));
03434
03435 le2 = WN_LE(Mtype_comparison(type),
03436 WN_LdidPreg(type, kabsN),
03437 WN_LdidPreg(type, icN));
03438 land = WN_LAND(le1, le2);
03439
03440 le = WN_LE(Mtype_comparison(type),
03441 WN_LdidPreg(type, icN),
03442 WN_Intconst(type, MTYPE_size_reg(desc)));
03443 cond = WN_LAND(land, le);
03444
03445 return WN_Select(type, cond, shiftc, WN_LdidPreg(type, mN));
03446 }
03447 }
03448
03449
03450
03451
03452
03453
03454
03455
03456
03457
03458
03459
03460
03461
03462
03463
03464 static BOOL decompose_address(WN *addr, WN **base, INT64 *offset)
03465 {
03466 switch(WN_operator(addr))
03467 {
03468 case OPR_ADD:
03469 case OPR_SUB:
03470 if (WN_is_pointer(WN_kid0(addr)) && Is_Integer_Constant(WN_kid1(addr)))
03471 {
03472 *base= WN_kid0(addr);
03473
03474 *offset= ABS(WN_const_val(WN_kid1(addr)));
03475 return TRUE;
03476 }
03477 break;
03478 default:
03479 if (WN_is_pointer(addr))
03480 {
03481 *offset= 0;
03482 *base= addr;
03483 return TRUE;
03484 }
03485 }
03486 return FALSE;
03487 }
03488
03489 static TY_IDX aux_compute_alignment(WN *wn)
03490 {
03491 WN *base;
03492 INT64 offset;
03493
03494 if (decompose_address(wn, &base, &offset))
03495 {
03496 return compute_alignment_type(base, TY_pointed(WN_ty(base)), offset);
03497 }
03498 return compute_alignment_type(wn, MTYPE_To_TY(MTYPE_V), 0);
03499 }
03500
03501
03502
03503
03504
03505
03506
03507
03508
03509
03510
03511
03512
03513 static BOOL check_size(WN *size, WN *src, WN *dst)
03514 {
03515 if (Is_Integer_Constant(size))
03516 {
03517 TY_IDX srcTY, dstTY = (TY_IDX) 0;
03518
03519 INT64 n = WN_const_val(size);
03520
03521
03522
03523
03524
03525 if (n <= CG_memmove_inst_count)
03526 return TRUE;
03527 #ifdef TARG_NVISA
03528 else
03529 {
03530
03531
03532
03533 mUINT64 srcpos = WN_Get_Linenum (src);
03534 if (srcpos)
03535 ErrMsgSrcpos (EC_Memset_Too_Large, srcpos, n);
03536 else
03537 ErrMsg (EC_Memset_Too_Large, n);
03538 }
03539 #endif
03540
03541 srcTY = aux_compute_alignment(src);
03542
03543 if (dst)
03544 {
03545 TY_IDX dstTY = aux_compute_alignment(dst);
03546 n += n;
03547 }
03548
03549 {
03550 TYPE_ID quantum;
03551 INT32 copy_alignment, instructions;
03552
03553 copy_alignment = compute_copy_alignment(srcTY, dstTY, 0);
03554
03555 quantum = compute_copy_quantum(copy_alignment);
03556 instructions= n / MTYPE_alignment(quantum);
03557
03558 if (instructions <= CG_memmove_inst_count)
03559 return TRUE;
03560 }
03561 }
03562 else if (CG_memmove_nonconst)
03563 return TRUE;
03564
03565 return FALSE;
03566 }
03567
03568
03569 static void aux_memory_msg(const char *msg, WN *tree, WN *mstore)
03570 {
03571 #if 0
03572 char buff[120];
03573 INT32 n;
03574
03575
03576
03577
03578
03579 if (WN_operator(mstore) != OPR_MSTORE) {
03580 sprintf (buff, "inlined %s on line %d, size = 0",
03581 msg, Srcpos_To_Line(WN_Get_Linenum(tree)));
03582 DevWarn (buff);
03583 return;
03584 }
03585
03586 WN *load = WN_kid0(mstore);
03587 WN *size = WN_kid2(mstore);
03588
03589 n= sprintf(buff, "inlined %s on line %d, dst align=%d",
03590 msg,
03591 Srcpos_To_Line(WN_Get_Linenum(tree)),
03592 TY_align(TY_pointed(WN_ty(mstore))));
03593
03594 if (WN_opcode(load) == OPC_MLOAD)
03595 {
03596 n += sprintf(&buff[n], ", src align=%d", TY_align(TY_pointed(WN_ty(load))));
03597 }
03598
03599 if (Is_Integer_Constant(size))
03600 {
03601 n += sprintf(&buff[n], ", size = %lld", WN_const_val(size));
03602 }
03603 else
03604 {
03605 n += sprintf(&buff[n], "size = unknown");
03606 }
03607
03608 DevWarn(buff);
03609 #endif
03610 }
03611
03612 static WN *aux_memset(WN *var, WN *con, WN *size)
03613 {
03614 WN *mstore, *newcon;
03615 TY_IDX align;
03616
03617 Is_True(Is_Integer_Constant(con), ("expected integer constant in aux_memset"));
03618
03619
03620
03621
03622
03623 align = aux_compute_alignment(var);
03624
03625
03626
03627
03628 newcon= WN_I1const(WN_rtype(con), WN_const_val(con));
03629 WN_Delete(con);
03630
03631 TY_IDX ptr_ty = Make_Pointer_Type (align);
03632 mstore = aux_CreateMstore(0, ptr_ty, newcon, var, size);
03633
03634 return mstore;
03635 }
03636
03637 static WN *aux_memcpy(WN *src, WN *dst, WN *size)
03638 {
03639 WN *mload, *mstore;
03640 TY_IDX srcTY, dstTY;
03641 TY_IDX srcTY_ptr, dstTY_ptr;
03642
03643
03644
03645
03646
03647 srcTY = aux_compute_alignment(src);
03648
03649 if (TY_size(srcTY) != 0 &&
03650 WN_const_val(size) % TY_size(srcTY) != 0) {
03651
03652
03653
03654 srcTY_ptr = Make_Pointer_Type (MTYPE_To_TY (MTYPE_V));
03655 }
03656 else srcTY_ptr = Make_Pointer_Type(srcTY);
03657
03658 mload = WN_CreateMload(0, srcTY_ptr, src, size);
03659
03660 dstTY = aux_compute_alignment(dst);
03661
03662 dstTY_ptr = Make_Pointer_Type(dstTY);
03663 mstore = aux_CreateMstore(0, dstTY_ptr, mload, dst, WN_COPY_Tree(size));
03664 return mstore;
03665 }
03666
03667 static WN *em_memset(WN *block, WN *tree, WN *var, WN *con, WN *size)
03668 {
03669 WN *em = NULL;
03670
03671 if (check_size(size, var, NULL) && Is_Integer_Constant(con))
03672 {
03673 if (em = aux_memset(var, con, size))
03674 {
03675 aux_memory_msg("memset()", tree, em);
03676 WN_INSERT_BlockLast(block, em);
03677 return WN_COPY_Tree(var);
03678 }
03679 }
03680 return em;
03681 }
03682
03683 static WN *em_bzero(WN *block, WN *tree, WN *var, WN *size)
03684 {
03685 WN *em = NULL;
03686
03687 if (check_size(size, var, NULL))
03688 {
03689 WN *zero = WN_Zerocon(MTYPE_U8);
03690
03691 if (em = aux_memset(var, zero, size))
03692 {
03693 aux_memory_msg("bzero()", tree, em);
03694 }
03695 else
03696 {
03697 WN_Delete(zero);
03698 }
03699 }
03700 return em;
03701 }
03702
03703 static WN *em_bcopy(WN *block, WN *tree, WN *src, WN *dst, WN *size)
03704 {
03705 WN *em = NULL;
03706
03707 if (check_size(size, src, dst))
03708 {
03709 if (CG_bcopy_cannot_overlap ||
03710 !lower_is_aliased(src, dst, WN_const_val(size)))
03711 {
03712 if (em = aux_memcpy(src, dst, size)) {
03713 aux_memory_msg("bcopy()", tree, em);
03714 }
03715 }
03716 }
03717 return em;
03718 }
03719
03720
03721
03722
03723
03724
03725
03726
03727 static WN *em_memcpy(WN *block, WN *tree, WN *dst, WN *src, WN *size)
03728 {
03729 if (check_size(size, src, dst))
03730 {
03731 #ifdef KEY
03732
03733 if ( CG_memcpy_cannot_overlap ||
03734 ( Is_Integer_Constant(size) &&
03735 ! lower_is_aliased(src, dst, WN_const_val(size)) ) )
03736 #else
03737 if (CG_memcpy_cannot_overlap ||
03738 !lower_is_aliased(src, dst, WN_const_val(size)))
03739 #endif
03740 {
03741 if (WN *em = aux_memcpy(src, dst, size)) {
03742 aux_memory_msg("memcpy()", tree, em);
03743 WN_INSERT_BlockLast(block, em);
03744 return WN_COPY_Tree(dst);
03745 }
03746 }
03747 }
03748 return NULL;
03749 }
03750
03751
03752
03753
03754
03755
03756
03757 static WN *em_memmove(WN *block, WN *tree, WN *dst, WN *src, WN *size)
03758 {
03759 if (check_size(size, src, dst))
03760 {
03761 if (CG_memmove_cannot_overlap ||
03762 !lower_is_aliased(src, dst, WN_const_val(size)))
03763 {
03764 if (WN *em = aux_memcpy(src, dst, size)) {
03765 aux_memory_msg("memmove()", tree, em);
03766 WN_INSERT_BlockLast(block, em);
03767 return WN_COPY_Tree(dst);
03768 }
03769 }
03770 }
03771 return NULL;
03772 }
03773
03774 #ifdef TARG_X8664
03775 extern
03776 ST *Get_Vararg_Save_Area_Info(int &fixed_int_parms, int &fixed_float_parms,
03777 ST *&upformal);
03778
03779
03780 static WN *em_x8664_va_start(WN *block, WN *ap)
03781 {
03782 TY_IDX ty_idx;
03783
03784 INT fixed_int_parms, fixed_float_parms;
03785 BOOL direct;
03786 BOOL non_leaf = FALSE;
03787 if (WN_operator(ap) == OPR_LDA) {
03788 ty_idx = WN_ty(ap);
03789 Is_True(TY_kind(ty_idx) == KIND_POINTER,
03790 ("em_x8664_va_start: argument not of pointer type"));
03791 ty_idx = TY_pointed(ty_idx);
03792 #if 0 // bug 10098
03793 Is_True(TY_kind(ty_idx) == KIND_ARRAY && TY_size(ty_idx) == 24,
03794 ("em_x8664_va_start: argument pointer does not point to type va_list"));
03795 #endif
03796 direct = TRUE;
03797
03798 }
03799 else if (WN_operator(ap) == OPR_LDID) {
03800 ty_idx = WN_ty(ap);
03801 Is_True(TY_kind(ty_idx) == KIND_POINTER,
03802 ("em_x8664_va_start: argument not of pointer type"));
03803 ty_idx = TY_pointed(ty_idx);
03804 Is_True(TY_size(ty_idx) == 24,
03805 ("em_x8664_va_start: argument pointer does not point to type va_list"));
03806 direct = FALSE;
03807
03808 }
03809 else {
03810 non_leaf = TRUE;
03811 direct = FALSE;
03812 }
03813
03814 ST *upformal;
03815 ST *reg_save_area = Get_Vararg_Save_Area_Info(fixed_int_parms, fixed_float_parms, upformal);
03816 WN *wn;
03817 WN *addr;
03818
03819 wn = WN_Intconst(MTYPE_I4, fixed_int_parms * 8);
03820 if (direct)
03821 wn = WN_Stid(MTYPE_I4, WN_offset(ap), WN_st(ap), MTYPE_To_TY(MTYPE_I4), wn);
03822 else {
03823 if (! non_leaf)
03824 addr = WN_Ldid(Pointer_Mtype, WN_offset(ap), WN_st(ap), WN_ty(ap));
03825 else addr = WN_COPY_Tree(ap);
03826 wn = WN_Istore(MTYPE_I4, 0, Make_Pointer_Type(MTYPE_To_TY(MTYPE_I4)),
03827 addr, wn);
03828 }
03829 WN_INSERT_BlockLast(block, wn);
03830
03831 wn = WN_Intconst(MTYPE_I4, fixed_float_parms * 16 + 48);
03832 if (direct)
03833 wn = WN_Stid(MTYPE_I4, 4 + WN_offset(ap), WN_st(ap), MTYPE_To_TY(MTYPE_I4), wn);
03834 else {
03835 if (! non_leaf)
03836 addr = WN_Ldid(Pointer_Mtype, WN_offset(ap), WN_st(ap), WN_ty(ap));
03837 else addr = WN_COPY_Tree(ap);
03838 wn = WN_Istore(MTYPE_I4, 4, Make_Pointer_Type(MTYPE_To_TY(MTYPE_I4)),
03839 addr, wn);
03840 }
03841 WN_INSERT_BlockLast(block, wn);
03842
03843 wn = WN_Lda(Pointer_Mtype, STB_size(upformal), upformal);
03844 if (direct)
03845 wn = WN_Stid(Pointer_Mtype, 8 + WN_offset(ap), WN_st(ap), MTYPE_To_TY(Pointer_Mtype), wn);
03846 else {
03847 if (! non_leaf)
03848 addr = WN_Ldid(Pointer_Mtype, WN_offset(ap), WN_st(ap), WN_ty(ap));
03849 else addr = WN_COPY_Tree(ap);
03850 wn = WN_Istore(Pointer_Mtype, 8,
03851 Make_Pointer_Type(MTYPE_To_TY(Pointer_Mtype)), addr, wn);
03852 }
03853
03854 if (ST_sclass(upformal) == SCLASS_UNKNOWN)
03855 Set_ST_sclass (upformal, SCLASS_FORMAL);
03856
03857 if (reg_save_area) {
03858 WN_INSERT_BlockLast(block, wn);
03859 if (TY_size(ST_type(reg_save_area)) == 8)
03860 wn = WN_Lda(Pointer_Mtype, -(fixed_int_parms * 8), reg_save_area);
03861 else wn = WN_Lda(Pointer_Mtype, -(fixed_float_parms*16)-48, reg_save_area);
03862 if (direct)
03863 wn = WN_Stid(Pointer_Mtype, 16 + WN_offset(ap), WN_st(ap), MTYPE_To_TY(Pointer_Mtype),wn);
03864 else {
03865 if (! non_leaf)
03866 addr = WN_Ldid(Pointer_Mtype, WN_offset(ap), WN_st(ap), WN_ty(ap));
03867 else addr = WN_COPY_Tree(ap);
03868 wn = WN_Istore(Pointer_Mtype, 16,
03869 Make_Pointer_Type(MTYPE_To_TY(Pointer_Mtype)), addr, wn);
03870 }
03871 }
03872 return wn;
03873 }
03874 #endif
03875
03876
03877
03878
03879
03880
03881
03882
03883
03884
03885 static COERCE INTR_coerce_runtime(WN *tree, INT32 arg)
03886 {
03887 if (OPCODE_is_intrinsic(WN_opcode(tree)))
03888 {
03889 INT32 i;
03890 INTRINSIC id = (INTRINSIC) WN_intrinsic(tree);
03891
03892 for(i=0; i < intrinsic_runtime_formals_size; i++)
03893 {
03894 if (id == INTR_id(i))
03895 {
03896 switch(arg)
03897 {
03898 case 0: return INTR_coerce0(i);
03899 case 1: return INTR_coerce1(i);
03900 default:
03901 Is_True(FALSE, ("INTR_coerce_runtime, arg >1"));
03902 }
03903 }
03904 }
03905 return COERCE_none;
03906 }
03907 else
03908 {
03909
03910
03911
03912
03913 EMULATION id = WN_emulation(tree);
03914
03915 Is_True((EM_id(id) == id), ("em_routine table in a sorry state"));
03916 return EM_coerce0(id);
03917 }
03918 }
03919
03920
03921
03922
03923
03924
03925
03926
03927
03928
03929 static TYPE_ID INTR_parameter_type(WN *tree, INT32 arg)
03930 {
03931 if (OPCODE_is_intrinsic(WN_opcode(tree)))
03932 {
03933 INT32 i;
03934 INTRINSIC id = (INTRINSIC) WN_intrinsic(tree);
03935 for(i=0; i < intrinsic_parameter_type_size; i++)
03936 {
03937 if (id == INTR_parm_id(i))
03938 {
03939 switch(arg)
03940 {
03941 case 0: return INTR_parmtype0(i);
03942 case 1: return INTR_parmtype1(i);
03943 case 2: return INTR_parmtype2(i);
03944 default:
03945
03946
03947
03948
03949
03950 return INTR_parmtype0(i);
03951 }
03952 }
03953 }
03954 Is_True(FALSE, ("INTR_parameter_type unknown for %s", INTR_intrinsic_name(tree)));
03955 }
03956 else
03957 {
03958 Is_True(FALSE, ("INTR_parameter_type not used for call by value"));
03959 }
03960 return MTYPE_V;
03961 }
03962
03963
03964
03965
03966
03967
03968
03969
03970
03971
03972
03973
03974
03975
03976 extern const char * INTR_intrinsic_name(WN *tree)
03977 {
03978 if (OPCODE_is_intrinsic(WN_opcode(tree)))
03979 {
03980 INTRINSIC id = (INTRINSIC) WN_intrinsic(tree);
03981
03982 return INTRN_rt_name(id);
03983 }
03984 else
03985 {
03986 EMULATION id = WN_emulation(tree);
03987
03988 Is_True((EM_id(id) == id), ("em_routine table in a sorry state"));
03989 return EM_rt_name(id);
03990 }
03991 }
03992
03993 static void
03994 Set_intrinsic_flags (ST *st, WN *tree)
03995 {
03996 PU& pu = Pu_Table[ST_pu (st)];
03997 if (OPCODE_is_intrinsic(WN_opcode(tree))) {
03998 INTRINSIC id = (INTRINSIC) WN_intrinsic(tree);
03999
04000
04001
04002
04003
04004
04005 if (INTRN_is_pure(id))
04006 Set_PU_is_pure (pu);
04007 if (INTRN_has_no_side_effects(id))
04008 Set_PU_no_side_effects (pu);
04009
04010 } else {
04011 EMULATION id = WN_emulation(tree);
04012
04013 if (EM_attributes(id) & PU_IS_PURE)
04014 Set_PU_is_pure (pu);
04015 if (EM_attributes(id) & NSE)
04016 Set_PU_no_side_effects (pu);
04017 }
04018 }
04019
04020
04021
04022
04023
04024
04025
04026
04027
04028
04029
04030
04031
04032
04033 static WN *by_value(WN *tree, INT32 arg)
04034 {
04035 TYPE_ID type;
04036 INTRINSIC id = (INTRINSIC) WN_intrinsic(tree);
04037 WN *child= WN_arg(tree, arg);
04038
04039 Is_True((OPCODE_is_intrinsic(WN_opcode(tree))),
04040 ("expected intrinsic call node, not %s", OPCODE_name(WN_opcode(tree))));
04041
04042 if (INTRN_by_value(id)==TRUE)
04043 {
04044 return child;
04045 }
04046
04047 type = INTR_parameter_type(tree, arg);
04048
04049 Is_True((type != MTYPE_V), ("unexpected void type"));
04050
04051 if (WN_operator_is(child, OPR_LDA))
04052 {
04053 return WN_Ldid(type,
04054 WN_lda_offset(child),
04055 WN_st(child),
04056 MTYPE_To_TY(type));
04057 }
04058 return WN_Iload(type, 0, MTYPE_To_TY(type), child);
04059 }
04060
04061
04062
04063
04064
04065
04066
04067
04068
04069
04070
04071
04072
04073
04074
04075
04076 static WN *return_conversion(INTRINSIC id, TYPE_ID type, WN *function)
04077 {
04078 if (MTYPE_is_integral(type))
04079 {
04080 TYPE_ID return_type = INTR_return_mtype(id);
04081
04082 if (MTYPE_is_integral(return_type))
04083 {
04084 if (return_type != type)
04085 {
04086 return WN_Type_Conversion(function, return_type);
04087 }
04088 else if (WN_rtype(function) != type)
04089 {
04090 DevWarn("Unexpected return_conversion() while processing intrinsic %s",
04091 INTRN_rt_name(id));
04092 return WN_Type_Conversion(function, return_type);
04093 }
04094 }
04095 }
04096 return function;
04097 }
04098
04099
04100
04101
04102
04103
04104
04105
04106
04107
04108
04109
04110
04111
04112 extern WN *make_pointer_to_node(WN *block, WN *tree)
04113 {
04114 switch (WN_operator(tree))
04115 {
04116 case OPR_ILOAD:
04117 return WN_kid0(tree);
04118
04119 case OPR_ISTORE:
04120 return WN_kid1(tree);
04121
04122 case OPR_LDID:
04123 if (WN_class(tree) == CLASS_PREG)
04124 break;
04125 return WN_Lda(Pointer_type, WN_load_offset(tree), WN_st(tree));
04126
04127 case OPR_STID:
04128 return WN_Lda(Pointer_type, WN_store_offset(tree), WN_st(tree));
04129
04130 case OPR_ARRAY:
04131 case OPR_LDA:
04132 return tree;
04133 }
04134 {
04135 TYPE_ID type = WN_rtype(tree);
04136 ST *st = Gen_Temp_Symbol( MTYPE_To_TY(type), "complex-temp-expr");
04137 WN *stid;
04138
04139 Is_True((WN_operator_is(tree, OPR_PARM)==FALSE),("bad parm"));
04140
04141
04142
04143 stid = WN_Stid (type, 0, st, ST_type(st), tree);
04144 WN_INSERT_BlockLast(block, stid);
04145
04146 return WN_Lda(Pointer_type, WN_store_offset(stid), st);
04147 }
04148 }
04149
04150
04151
04152
04153
04154
04155
04156
04157
04158
04159 static ST *GenLocalTable(WN *block, TYPE_ID element, INT32 n, WN **init)
04160 {
04161 INT32 i;
04162 TY_IDX arrayTY;
04163 ST *arrayST;
04164
04165 arrayTY = Make_Array_Type (element, 1, n);
04166 {
04167 static INT32 table_cnt = 0;
04168 char buffer[32];
04169 sprintf(buffer, "localtable.%d", ++table_cnt);
04170
04171 arrayST = Gen_Temp_Symbol(arrayTY, buffer);
04172 }
04173
04174 for(i=0; i<n; i++)
04175 {
04176 WN *st;
04177
04178 st = WN_Stid(element,
04179 i * MTYPE_RegisterSize(element),
04180 arrayST,
04181 arrayTY,
04182 init[i]);
04183 WN_INSERT_BlockLast(block, st);
04184 }
04185
04186 return arrayST;
04187 }
04188
04189
04190
04191
04192
04193
04194
04195
04196
04197
04198
04199
04200
04201
04202
04203
04204
04205
04206 static WN *process_concatexpr(WN *block, WN *tree)
04207 {
04208 INT16 nsrc;
04209 WN **wn;
04210 WN *srcAddr, *srcSize, *srcNp;
04211
04212 nsrc = (WN_kid_count(tree)-2) / 2;
04213
04214 wn = (WN **) alloca(nsrc * sizeof(WN));
04215 {
04216
04217
04218
04219 ST *srcST;
04220 INT32 i;
04221
04222 for(i=0; i<nsrc; i++)
04223 wn[i] = WN_arg(tree, i+2);
04224
04225 srcST = GenLocalTable(block, Pointer_type, nsrc, wn);
04226 srcAddr = WN_Lda(Pointer_type, 0, srcST);
04227 }
04228 {
04229
04230
04231
04232 ST *sizeST;
04233 INT32 i;
04234
04235 for(i=0; i<nsrc; i++)
04236 wn[i] = WN_arg(tree, i+2+nsrc);
04237
04238 sizeST = GenLocalTable(block, Integer_type, nsrc, wn);
04239 srcSize = WN_Lda(Pointer_type, 0, sizeST);
04240 }
04241 {
04242 WN *count;
04243
04244 count = WN_Intconst(Integer_type, nsrc);
04245
04246 srcNp = make_pointer_to_node(block, count);
04247 }
04248
04249
04250
04251
04252
04253
04254 {
04255 WN *kids[5];
04256 WN *s_cat;
04257 INTRINSIC id = (INTRINSIC) WN_intrinsic(tree);
04258 BOOL byvalue = INTRN_by_value(id);
04259
04260 kids[0] = WN_kid(tree, 0);
04261 kids[1] = createParm( srcAddr, byvalue );
04262 kids[2] = createParm( srcSize, byvalue );
04263 kids[3] = createParm( srcNp, byvalue );
04264 kids[4] = WN_kid(tree, 1);
04265
04266 s_cat = WN_Create_Intrinsic(WN_opcode(tree), id, 5, kids);
04267 return s_cat;
04268 }
04269 }
04270
04271
04272
04273
04274
04275
04276
04277
04278
04279
04280
04281
04282
04283
04284
04285
04286
04287
04288 static const char *Weak_Runtimes[] = {
04289 "__C_runtime_error",
04290
04291 NULL
04292 };
04293
04294 static void
04295 Annotate_Weak_Runtime ( ST *func, const char *name )
04296 {
04297 const char **weak_rt = Weak_Runtimes;
04298
04299 while ( *weak_rt != NULL ) {
04300 if ( strcmp ( *weak_rt, name ) == 0 ) {
04301 Set_ST_is_weak_symbol ( func );
04302 return;
04303 }
04304 ++weak_rt;
04305 }
04306 }
04307
04308
04309
04310
04311
04312
04313
04314
04315
04316
04317 extern WN *intrinsic_runtime(WN *block, WN *tree)
04318 {
04319 INT16 n;
04320 INT16 argC = 0;
04321 WN *args[MAX_INTRINSIC_ARGS];
04322 const char *function = INTR_intrinsic_name(tree);
04323 BOOL byvalue = FALSE;
04324 BOOL parmMod= FALSE;
04325
04326 Is_True((function), ("cannot emulate (null function)"));
04327
04328 if (OPCODE_is_intrinsic(WN_opcode(tree)))
04329 {
04330 switch(WN_intrinsic(tree))
04331 {
04332 case INTRN_CONCATEXPR:
04333 tree = process_concatexpr(block, tree);
04334 break;
04335 }
04336
04337 byvalue = INTRN_by_value(WN_intrinsic(tree));
04338 }
04339
04340 {
04341
04342
04343
04344
04345
04346
04347 TYPE_ID rtype = WN_rtype(tree);
04348
04349 switch(rtype)
04350 {
04351 #ifdef TARG_X8664
04352 case MTYPE_C4:
04353 case MTYPE_C8:
04354 if (Is_Target_64bit())
04355 break;
04356
04357 #endif
04358 case MTYPE_CQ:
04359 {
04360 ST *retST = Gen_Temp_Symbol(MTYPE_To_TY(rtype), "return_temp");
04361
04362 Set_BE_ST_addr_used_locally(retST);
04363
04364 args[ argC++] = createParm(WN_Lda(Pointer_type, 0, retST), FALSE);
04365 parmMod= TRUE;
04366 }
04367 break;
04368 default:
04369 break;
04370 }
04371 }
04372
04373 for(n = 0; n < WN_num_actuals(tree); n++)
04374 {
04375 WN *actual = WN_kid(tree, n);
04376 COERCE coerce = INTR_coerce_runtime(tree, n);
04377
04378 switch(coerce)
04379 {
04380 case COERCE_none:
04381 args[ argC++] = actual;
04382 break;
04383
04384 case COERCE_struct_by_value:
04385 {
04386 TYPE_ID type = WN_rtype(actual);
04387 TY_IDX complexTY;
04388 WN *mload;
04389 INT32 size = MTYPE_size_min(type) >> 3;
04390
04391
04392
04393
04394
04395 TY& ty = New_TY (complexTY);
04396 ty = Ty_Table[MTYPE_To_TY(type)];
04397 Set_TY_mtype (ty, MTYPE_M);
04398 Set_TY_align_exp (complexTY, 3);
04399
04400 TY_IDX complex_ptr = Make_Pointer_Type(complexTY);
04401
04402 if (WN_operator_is(actual, OPR_PARM))
04403 actual = WN_kid0(actual);
04404
04405 mload = WN_CreateMload(0, complex_ptr,
04406 make_pointer_to_node(block, actual),
04407 WN_Intconst(Integer_type, size));
04408 args[ argC++] = mload;
04409 }
04410
04411 case COERCE_struct_by_reference:
04412 break;
04413
04414 case COERCE_split_complex:
04415 {
04416 TYPE_ID type = WN_rtype(actual);
04417 TYPE_ID rtype = Mtype_complex_to_real(type);
04418 PREG_NUM valN;
04419
04420 if (WN_operator_is(actual, OPR_PARM))
04421 actual = WN_kid0(actual);
04422
04423 valN = AssignExpr(block, actual, type);
04424
04425 args[ argC++] = WN_Realpart(rtype, WN_LdidPreg(type, valN));
04426 args[ argC++] = WN_Imagpart(rtype, WN_LdidPreg(type, valN));
04427 }
04428 break;
04429
04430 default:
04431 Fail_FmtAssertion("coerce case does not exist coerce = %d", coerce);
04432 }
04433 }
04434
04435 {
04436 TYPE_ID rtype = WN_rtype(tree);
04437 TY_IDX ty = Make_Function_Type( MTYPE_To_TY(rtype));
04438
04439 #ifdef TARG_X8664
04440
04441
04442
04443
04444
04445
04446 Set_TY_has_prototype(ty);
04447
04448 ST* st = NULL;
04449
04450
04451
04452
04453
04454
04455
04456
04457
04458
04459
04460
04461
04462
04463
04464
04465 if( Is_Target_64bit() &&
04466
04467 !Is_Target_Anyx86() &&
04468 OPT_Fast_Math &&
04469 ( WN_intrinsic(tree) == INTRN_F8COS ||
04470 WN_intrinsic(tree) == INTRN_F8EXP ||
04471 WN_intrinsic(tree) == INTRN_F4EXP ||
04472 WN_intrinsic(tree) == INTRN_F8LOG ||
04473 WN_intrinsic(tree) == INTRN_F4LOG ||
04474 WN_intrinsic(tree) == INTRN_F8EXPEXPR ||
04475 WN_intrinsic(tree) == INTRN_F4EXPEXPR ||
04476 WN_intrinsic(tree) == INTRN_F8SIN ||
04477 WN_intrinsic(tree) == INTRN_SINCOS ||
04478 WN_intrinsic(tree) == INTRN_F8VSIN ||
04479 WN_intrinsic(tree) == INTRN_F8VCOS ||
04480 WN_intrinsic(tree) == INTRN_F8VEXP ||
04481 WN_intrinsic(tree) == INTRN_F4VEXP ||
04482 WN_intrinsic(tree) == INTRN_F4VLOG ||
04483 WN_intrinsic(tree) == INTRN_F8VLOG ) ) {
04484 BOOL vector_call_check_constant_stride = FALSE;
04485 switch (WN_intrinsic(tree)) {
04486 case INTRN_F8COS: st = Gen_Intrinsic_Function(ty, "fastcos"); break;
04487 case INTRN_F8EXP: st = Gen_Intrinsic_Function(ty, "fastexp"); break;
04488 case INTRN_F4EXP: st = Gen_Intrinsic_Function(ty, "fastexpf"); break;
04489 case INTRN_F8LOG: st = Gen_Intrinsic_Function(ty, "fastlog"); break;
04490 case INTRN_F4LOG: st = Gen_Intrinsic_Function(ty, "fastlogf"); break;
04491 case INTRN_F8EXPEXPR:st = Gen_Intrinsic_Function(ty, "fastpow"); break;
04492 case INTRN_F4EXPEXPR:st = Gen_Intrinsic_Function(ty, "fastpowf"); break;
04493 case INTRN_F8SIN: st = Gen_Intrinsic_Function(ty, "fastsin"); break;
04494 case INTRN_SINCOS: st = Gen_Intrinsic_Function(ty, "fastsincos");break;
04495
04496 case INTRN_F8VSIN:
04497 st = Gen_Intrinsic_Function(ty, "vrda_sin");
04498 vector_call_check_constant_stride = TRUE;
04499 break;
04500 case INTRN_F8VCOS:
04501 st = Gen_Intrinsic_Function(ty, "vrda_cos");
04502 vector_call_check_constant_stride = TRUE;
04503 break;
04504 case INTRN_F8VEXP:
04505 st = Gen_Intrinsic_Function(ty, "vrda_exp");
04506 vector_call_check_constant_stride = TRUE;
04507 break;
04508 case INTRN_F4VEXP:
04509 st = Gen_Intrinsic_Function(ty, "vrsa_expf");
04510 vector_call_check_constant_stride = TRUE;
04511 break;
04512 case INTRN_F8VLOG:
04513 st = Gen_Intrinsic_Function(ty, "vrda_log");
04514 vector_call_check_constant_stride = TRUE;
04515 break;
04516 case INTRN_F4VLOG:
04517 st = Gen_Intrinsic_Function(ty, "vrsa_logf");
04518 vector_call_check_constant_stride = TRUE;
04519 break;
04520 }
04521
04522 if ( vector_call_check_constant_stride ) {
04523 WN* x = WN_kid(tree, 0);
04524 WN* y = WN_kid(tree, 1);
04525 WN* count = WN_kid(tree, 2);
04526 WN* stridex = WN_kid(tree, 3);
04527 WN* stridey = WN_kid(tree, 4);
04528 if ( WN_operator(WN_kid0(stridex)) != OPR_INTCONST ||
04529 WN_operator(WN_kid0(stridey)) != OPR_INTCONST ||
04530 WN_const_val(WN_kid0(stridex)) != 1 ||
04531 WN_const_val(WN_kid0(stridey)) != 1 )
04532 st = Gen_Intrinsic_Function(ty, function);
04533 else {
04534 args[ 0 ] = count;
04535 args[ 1 ] = x;
04536 args[ 2 ] = y;
04537 argC = 3;
04538 }
04539 }
04540
04541 #if defined(TARG_X8664) && !defined(OSP_OPT)
04542
04543 } else if (WN_intrinsic(tree) == INTRN_MEMSET &&
04544 OPT_Fast_Stdlib &&
04545 Is_Target_64bit()) {
04546 if (Is_Target_EM64T() || Is_Target_Core() || Is_Target_Wolfdale())
04547 st = Gen_Intrinsic_Function(ty, "memset.pathscale.em64t");
04548 else
04549 st = Gen_Intrinsic_Function(ty, "memset.pathscale.opteron");
04550
04551
04552 } else if (WN_intrinsic(tree) == INTRN_MEMCPY &&
04553 OPT_Fast_Stdlib &&
04554 Is_Target_64bit()) {
04555 if (Is_Target_EM64T() || Is_Target_Core() || Is_Target_Wolfdale())
04556 st = Gen_Intrinsic_Function(ty, "__memcpy_pathscale_em64t");
04557 else
04558 st = Gen_Intrinsic_Function(ty, "__memcpy_pathscale_opteron");
04559 #endif
04560 } else if (WN_intrinsic(tree) == INTRN_POPCOUNT &&
04561 MTYPE_byte_size(WN_rtype(WN_kid0(tree))) <= 4 &&
04562 Is_Target_32bit()) {
04563 st = Gen_Intrinsic_Function(ty, "__popcountsi2");
04564 #if defined(TARG_X8664) && !defined(OSP_OPT)
04565
04566 } else if (WN_intrinsic(tree) == INTRN_PARITY &&
04567 MTYPE_byte_size(WN_rtype(WN_kid0(tree))) <= 4 &&
04568 Is_Target_32bit()) {
04569 st = Gen_Intrinsic_Function(ty, "__paritysi2");
04570 #endif
04571 } else {
04572 st = Gen_Intrinsic_Function(ty, function);
04573 }
04574 #elif defined(TARG_MIPS) && !defined(TARG_SL)
04575
04576 #if 0 // Using __popcountsi2 fails at link-time on cross-compiler.
04577 ST *st = NULL;
04578 if (WN_intrinsic(tree) == INTRN_POPCOUNT &&
04579 MTYPE_byte_size(WN_rtype(WN_kid0(tree))) <= 4) {
04580 st = Gen_Intrinsic_Function(ty, "__popcountsi2");
04581 } else
04582 st = Gen_Intrinsic_Function(ty, function);
04583 #else
04584 if (WN_intrinsic(tree) == INTRN_POPCOUNT &&
04585 MTYPE_byte_size(WN_rtype(WN_kid0(tree))) <= 4) {
04586
04587
04588
04589 WN *wn_cvt = WN_Cvt( MTYPE_U4, MTYPE_U8, WN_kid0( args[0] ) );
04590 args[0] = WN_CreateParm( MTYPE_U8, wn_cvt,
04591 MTYPE_To_TY( MTYPE_U8 ), WN_PARM_BY_VALUE );
04592 }
04593 ST *st = Gen_Intrinsic_Function(ty, function);
04594 #endif
04595
04596 #else
04597 ST *st = Gen_Intrinsic_Function(ty, function);
04598 #endif // KEY
04599
04600 WN *call;
04601
04602
04603
04604
04605 Set_intrinsic_flags (st, tree);
04606 Annotate_Weak_Runtime ( st, function );
04607
04608 #if defined(TARG_X8664)
04609 if (! Is_Target_64bit()) {
04610 call = WN_Create(OPR_CALL, rtype, MTYPE_V, argC);
04611 WN_st_idx(call) = ST_st_idx(st);
04612 }
04613 else
04614 #endif
04615 call = WN_Call(rtype, MTYPE_V, argC, st);
04616 WN_call_flag(call) = WN_call_flag(tree);
04617
04618 WN_annotate_call_flags(call, st);
04619
04620
04621
04622
04623 if (parmMod)
04624 WN_Set_Call_Parm_Mod(call);
04625
04626 while (--argC >= 0)
04627 {
04628 WN_actual(call, argC) = createParm(args[ argC], byvalue);
04629 }
04630
04631
04632 if ( Cur_PU_Feedback )
04633 Cur_PU_Feedback->FB_set_in_out_same_node( call );
04634
04635 return call;
04636 }
04637 }
04638
04639
04640
04641
04642
04643
04644
04645 static WN *emulate_intrinsic_op(WN *block, WN *tree)
04646 {
04647 INTRINSIC id = (INTRINSIC) WN_intrinsic(tree);
04648 TYPE_ID rtype = WN_rtype(tree);
04649 WN *function;
04650
04651 Is_True((OPCODE_is_intrinsic(WN_opcode(tree))),
04652 ("expected intrinsic call node, not %s", OPCODE_name(WN_opcode(tree))));
04653 Is_True((INTRN_is_actual(WN_intrinsic(tree))==FALSE),
04654 ("cannot emulate INTRN_is_actual"));
04655
04656 switch(id) {
04657 case INTRN_I4EXPEXPR:
04658 case INTRN_I8EXPEXPR:
04659
04660
04661
04662 return em_exp_int(block, by_value(tree, 0), by_value(tree,1), rtype);
04663
04664 case INTRN_F4I4EXPEXPR:
04665 case INTRN_F4I8EXPEXPR:
04666 case INTRN_F8I4EXPEXPR:
04667 case INTRN_F8I8EXPEXPR:
04668 case INTRN_FQI4EXPEXPR:
04669 case INTRN_FQI8EXPEXPR:
04670 case INTRN_C4I4EXPEXPR:
04671 case INTRN_C4I8EXPEXPR:
04672 case INTRN_C8I4EXPEXPR:
04673 case INTRN_C8I8EXPEXPR:
04674 case INTRN_CQI4EXPEXPR:
04675 case INTRN_CQI8EXPEXPR:
04676
04677
04678
04679
04680 return em_exp_int(block, by_value(tree, 0), by_value(tree,1), rtype);
04681
04682 case INTRN_F4EXPEXPR:
04683 case INTRN_F8EXPEXPR:
04684 case INTRN_FQEXPEXPR:
04685 case INTRN_C4EXPEXPR:
04686 case INTRN_C8EXPEXPR:
04687 case INTRN_CQEXPEXPR:
04688 if (Fast_Exp_Allowed)
04689 return em_exp_float(block, by_value(tree, 0), by_value(tree, 1), rtype);
04690 break;
04691
04692 case INTRN_F4MOD:
04693 case INTRN_F8MOD:
04694 case INTRN_FQMOD:
04695 return em_mod_float(block, by_value(tree, 0), by_value(tree, 1));
04696
04697 case INTRN_I1DIM:
04698 case INTRN_I2DIM:
04699 function= em_dim(block, by_value(tree, 0), by_value(tree, 1));
04700 return return_conversion(id, rtype, function);
04701
04702 case INTRN_I4DIM:
04703 case INTRN_I8DIM:
04704 case INTRN_F4DIM:
04705 case INTRN_F8DIM:
04706 case INTRN_FQDIM:
04707 return em_dim(block, by_value(tree, 0), by_value(tree, 1));
04708
04709 case INTRN_F8F4PROD:
04710 case INTRN_FQF8PROD:
04711 return em_prod(block, rtype, by_value(tree, 0), by_value(tree, 1));
04712
04713 case INTRN_I1SIGN:
04714 case INTRN_I2SIGN:
04715 function= em_sign(block, by_value(tree, 0), by_value(tree, 1));
04716 return return_conversion(id, rtype, function);
04717
04718 case INTRN_I4SIGN:
04719 case INTRN_I8SIGN:
04720 case INTRN_F4SIGN:
04721 case INTRN_F8SIGN:
04722 case INTRN_FQSIGN:
04723 return em_sign(block, by_value(tree, 0), by_value(tree, 1));
04724
04725 case INTRN_F4AINT:
04726 case INTRN_F8AINT:
04727 case INTRN_FQAINT:
04728 return em_aint(block, rtype, by_value(tree, 0));
04729
04730 case INTRN_I2F4NINT:
04731 case INTRN_I4F4NINT:
04732 case INTRN_I8F4NINT:
04733 case INTRN_I2F8IDNINT:
04734 case INTRN_I4F8IDNINT:
04735 case INTRN_I8F8IDNINT:
04736 case INTRN_I2FQIQNINT:
04737 case INTRN_I4FQIQNINT:
04738 case INTRN_I8FQIQNINT:
04739 return em_nearest_int(block, rtype, by_value(tree, 0));
04740
04741 case INTRN_F4ANINT:
04742 case INTRN_F8ANINT:
04743 case INTRN_FQANINT:
04744 return em_nearest_aint(block, rtype, by_value(tree, 0));
04745
04746 case INTRN_I4CLEN:
04747 return em_clen(block, by_value(tree, 1));
04748
04749 case INTRN_U4I4ALLOCA:
04750 case INTRN_U8I8ALLOCA:
04751 return em_alloca(block, tree);
04752
04753 case INTRN_U4READSTACKPOINTER:
04754 case INTRN_U8READSTACKPOINTER:
04755 return em_readstackpointer(Pointer_type);
04756
04757 #ifdef KEY
04758 case INTRN_U4READFRAMEPOINTER:
04759 case INTRN_U8READFRAMEPOINTER:
04760 return em_readframepointer(Pointer_type);
04761 #endif
04762
04763 case INTRN_U4I4SETSTACKPOINTER:
04764 case INTRN_U8I8SETSTACKPOINTER:
04765 return em_setstackpointer(block, Pointer_type, by_value(tree, 0));
04766
04767 case INTRN_C4CONJG:
04768 case INTRN_C8CONJG:
04769 case INTRN_CQCONJG:
04770 return em_conjg(block, by_value(tree, 0));
04771
04772
04773
04774
04775
04776
04777 case INTRN_I1BCLR:
04778 case INTRN_I2BCLR:
04779 case INTRN_I4BCLR:
04780 case INTRN_I8BCLR:
04781
04782
04783
04784
04785
04786 return em_bclr(block, by_value(tree, 0), by_value(tree, 1));
04787
04788 case INTRN_I1BSET:
04789 case INTRN_I2BSET:
04790 case INTRN_I4BSET:
04791 case INTRN_I8BSET:
04792
04793
04794
04795
04796
04797 function= em_bset(block, by_value(tree, 0), by_value(tree, 1));
04798 return return_conversion(id, rtype, function);
04799
04800
04801 case INTRN_I1BTEST:
04802 case INTRN_I2BTEST:
04803 case INTRN_I4BTEST:
04804 case INTRN_I8BTEST:
04805
04806
04807
04808
04809
04810 return em_btest(block, by_value(tree, 0), by_value(tree, 1));
04811
04812 case INTRN_I1BITS:
04813 case INTRN_I2BITS:
04814 case INTRN_I4BITS:
04815 case INTRN_I8BITS:
04816
04817
04818
04819
04820
04821
04822
04823
04824 return em_bits(block, by_value(tree, 0), by_value(tree, 1), by_value(tree, 2));
04825
04826
04827 case INTRN_I1SHL:
04828 case INTRN_I2SHL:
04829
04830
04831
04832
04833
04834
04835
04836 function= em_shl(block, by_value(tree, 0), by_value(tree, 1));
04837 return return_conversion(id, rtype, function);
04838
04839 case INTRN_I1SHR:
04840 case INTRN_I2SHR:
04841 function= em_lshr(block, by_value(tree, 0), by_value(tree, 1));
04842 return return_conversion(id, rtype, function);
04843
04844 case INTRN_I1SHFT:
04845 case INTRN_I2SHFT:
04846 case INTRN_I4SHFT:
04847 case INTRN_I8SHFT:
04848
04849
04850
04851
04852
04853
04854
04855
04856 function= em_shft(block, by_value(tree, 0), by_value(tree, 1));
04857 return return_conversion(id, rtype, function);
04858
04859 case INTRN_I1SHFTC:
04860 case INTRN_I2SHFTC:
04861 case INTRN_I4SHFTC:
04862 case INTRN_I8SHFTC:
04863 function= em_shftc(block, by_value(tree, 0), by_value(tree, 1), by_value(tree, 2));
04864 return return_conversion(id, rtype, function);
04865
04866 case INTRN_I4POPPAR:
04867 case INTRN_I8POPPAR:
04868 case INTRN_PARITY:
04869 function= em_parity(block, by_value(tree, 0));
04870 return return_conversion(id, rtype, function);
04871
04872 case INTRN_I1POPCNT:
04873 case INTRN_I2POPCNT:
04874 case INTRN_I4POPCNT:
04875 case INTRN_I8POPCNT:
04876 case INTRN_POPCOUNT:
04877 {
04878 INT bitsize = MTYPE_size_reg(WN_rtype(by_value(tree, 0)));
04879 switch (id) {
04880 case INTRN_I1POPCNT: bitsize = 8; break;
04881 case INTRN_I2POPCNT: bitsize = 16; break;
04882 case INTRN_I4POPCNT: bitsize = 32; break;
04883 case INTRN_I8POPCNT: bitsize = 64; break;
04884 }
04885 function = em_popcount(block, by_value(tree, 0), bitsize);
04886 }
04887 return return_conversion(id, rtype, function);
04888
04889 case INTRN_CLGE:
04890 case INTRN_CLGT:
04891 case INTRN_CLLE:
04892 case INTRN_CLLT:
04893 case INTRN_CEQEXPR:
04894 case INTRN_CNEEXPR:
04895 case INTRN_CGEEXPR:
04896 case INTRN_CGTEXPR:
04897 case INTRN_CLEEXPR:
04898 case INTRN_CLTEXPR:
04899
04900
04901
04902 break;
04903
04904 case INTRN_SUBSTRINGEXPR:
04905 case INTRN_CONCATEXPR:
04906 case INTRN_CASSIGNSTMT:
04907
04908 case INTRN_F4EXP:
04909 case INTRN_F8EXP:
04910 case INTRN_FQEXP:
04911 break;
04912
04913 case INTRN_C4EXP:
04914 case INTRN_C8EXP:
04915 case INTRN_CQEXP:
04916
04917
04918
04919
04920 return em_complex_exp(block, by_value(tree, 0));
04921
04922 case INTRN_F4LOG:
04923 case INTRN_F8LOG:
04924 case INTRN_FQLOG:
04925 break;
04926
04927 case INTRN_C4LOG:
04928 case INTRN_C8LOG:
04929 case INTRN_CQLOG:
04930
04931
04932
04933
04934 return em_complex_log(block, by_value(tree, 0));
04935
04936 case INTRN_F4LOG10:
04937 case INTRN_F8LOG10:
04938 case INTRN_FQLOG10:
04939
04940
04941
04942 return em_alog10(block, by_value(tree, 0));
04943
04944 case INTRN_F4COS:
04945 case INTRN_F8COS:
04946 case INTRN_FQCOS:
04947 case INTRN_F4SIN:
04948 case INTRN_F8SIN:
04949 case INTRN_FQSIN:
04950 case INTRN_F4TAN:
04951 case INTRN_F8TAN:
04952 case INTRN_FQTAN:
04953 case INTRN_F4COSD:
04954 case INTRN_F8COSD:
04955 case INTRN_FQCOSD:
04956 case INTRN_F4SIND:
04957 case INTRN_F8SIND:
04958 case INTRN_FQSIND:
04959 case INTRN_F4TAND:
04960 case INTRN_F8TAND:
04961 case INTRN_FQTAND:
04962 case INTRN_F4COSH:
04963 case INTRN_F8COSH:
04964 case INTRN_FQCOSH:
04965 case INTRN_F4SINH:
04966 case INTRN_F8SINH:
04967 case INTRN_FQSINH:
04968 case INTRN_F4TANH:
04969 case INTRN_F8TANH:
04970 case INTRN_FQTANH:
04971 case INTRN_F4ACOS:
04972 case INTRN_F8ACOS:
04973 case INTRN_FQACOS:
04974 case INTRN_F4ASIN:
04975 case INTRN_F8ASIN:
04976 case INTRN_FQASIN:
04977 case INTRN_F4ATAN:
04978 case INTRN_F8ATAN:
04979 case INTRN_FQATAN:
04980 case INTRN_F4ACOSD:
04981 case INTRN_F8ACOSD:
04982 case INTRN_FQACOSD:
04983 case INTRN_F4ASIND:
04984 case INTRN_F8ASIND:
04985 case INTRN_FQASIND:
04986 case INTRN_F4ATAND:
04987 case INTRN_F8ATAND:
04988 case INTRN_FQATAND:
04989 case INTRN_F4ATAN2:
04990 case INTRN_F8ATAN2:
04991 case INTRN_FQATAN2:
04992 case INTRN_F4ATAN2D:
04993 case INTRN_F8ATAN2D:
04994 case INTRN_FQATAN2D:
04995 break;
04996
04997 case INTRN_C4COS:
04998 case INTRN_C8COS:
04999 case INTRN_CQCOS:
05000
05001
05002
05003
05004 return em_complex_cos(block, by_value(tree, 0));
05005
05006 case INTRN_F4C4ABS:
05007 case INTRN_F8C8ABS:
05008 case INTRN_FQCQABS:
05009 return em_complex_abs(block, by_value(tree, 0));
05010
05011 case INTRN_C4SIN:
05012 case INTRN_C8SIN:
05013 case INTRN_CQSIN:
05014
05015
05016
05017
05018 return em_complex_sin(block, by_value(tree, 0));
05019
05020 case INTRN_F4CIS:
05021 case INTRN_F8CIS:
05022 case INTRN_FQCIS:
05023
05024
05025
05026
05027
05028 break;
05029
05030 case INTRN_U4I4MALLOC:
05031 if ( DEBUG_Trap_Uv )
05032 WN_intrinsic(tree) = INTRN_U4I4TRAPUV_MALLOC;
05033 break;
05034
05035 case INTRN_U8I8MALLOC:
05036 if ( DEBUG_Trap_Uv )
05037 WN_intrinsic(tree) = INTRN_U8I8TRAPUV_MALLOC;
05038 break;
05039
05040 case INTRN_U4FREE:
05041 case INTRN_U8FREE:
05042 case INTRN_MDATE:
05043 case INTRN_I4DATE:
05044 case INTRN_I8DATE:
05045 case INTRN_I4ERRSNS:
05046 case INTRN_I8ERRSNS:
05047 case INTRN_VEXIT:
05048 case INTRN_I4EXIT:
05049 case INTRN_I8EXIT:
05050 case INTRN_TIME:
05051 case INTRN_F4SECNDS:
05052 case INTRN_F8SECNDS:
05053 case INTRN_PAUSE:
05054 case INTRN_STOP:
05055 case INTRN_F77_BOUNDS_ERR:
05056 case INTRN_F4I4RAN:
05057 case INTRN_F4I8RAN:
05058 case INTRN_F8I4RAN:
05059 case INTRN_F8I8RAN:
05060 case INTRN_FQI4RAN:
05061 case INTRN_FQI8RAN:
05062 break;
05063
05064 case INTRN_I8DIVFLOOR:
05065 case INTRN_I4DIVFLOOR:
05066 case INTRN_U4DIVFLOOR:
05067 case INTRN_U8DIVFLOOR:
05068 return em_divfloor(block, rtype, by_value(tree, 0), by_value(tree, 1));
05069
05070 case INTRN_I4DIVCEIL:
05071 case INTRN_I8DIVCEIL:
05072 case INTRN_U4DIVCEIL:
05073 case INTRN_U8DIVCEIL:
05074 return em_divceil(block, rtype, by_value(tree, 0), by_value(tree, 1));
05075
05076 case INTRN_I4MODFLOOR:
05077 case INTRN_I8MODFLOOR:
05078 case INTRN_U4MODFLOOR:
05079 case INTRN_U8MODFLOOR:
05080 case INTRN_I4MODCEIL:
05081 case INTRN_I8MODCEIL:
05082 case INTRN_U4MODCEIL:
05083 case INTRN_U8MODCEIL:
05084 Is_True(FALSE,
05085 ("%s not yet implemented. Micheal Wolf said this would never, ever, ever. be needed. Go away", INTR_intrinsic_name(tree)));
05086 break;
05087
05088 case INTRN_I1MVBITS:
05089 case INTRN_I2MVBITS:
05090 case INTRN_I4MVBITS:
05091 case INTRN_I8MVBITS:
05092
05093 case INTRN_I4CINDEX:
05094 break;
05095
05096 case INTRN_BZERO:
05097 if (CG_mem_intrinsics)
05098 {
05099 return em_bzero(block, tree, WN_arg(tree, 0), WN_arg(tree, 1));
05100 }
05101 break;
05102
05103 case INTRN_MEMSET:
05104 #if !defined(KEY) || defined(TARG_SL) || defined(TARG_NVISA) // Don't emulate memset; call PathScale memset instead.
05105 if (CG_mem_intrinsics)
05106 {
05107 return em_memset(block, tree, WN_arg(tree, 0), WN_arg(tree, 1), WN_arg(tree, 2));
05108 }
05109 #endif
05110 break;
05111
05112 case INTRN_BCOPY:
05113 if (CG_mem_intrinsics)
05114 {
05115 return em_bcopy(block, tree, WN_arg(tree, 0), WN_arg(tree, 1), WN_arg(tree, 2));
05116 }
05117 break;
05118
05119 case INTRN_MEMCPY:
05120 if (CG_mem_intrinsics)
05121 {
05122 return em_memcpy(block, tree, WN_arg(tree, 0), WN_arg(tree, 1), WN_arg(tree, 2));
05123 }
05124 break;
05125
05126 case INTRN_MEMMOVE:
05127 if (CG_mem_intrinsics)
05128 {
05129 return em_memmove(block, tree, WN_arg(tree, 0), WN_arg(tree, 1), WN_arg(tree, 2));
05130 }
05131 break;
05132
05133 #ifdef TARG_X8664
05134 case INTRN_VA_START:
05135 if (strcmp(Get_Error_Phase(), "VHO Processing") == 0)
05136 break;
05137 return em_x8664_va_start(block, WN_arg(tree, 0));
05138 break;
05139 #endif
05140
05141 #if defined(KEY) && !defined(TARG_SL)
05142 case INTRN_F4CBRT:
05143 case INTRN_F8CBRT:
05144 break;
05145 #endif
05146
05147 default:
05148 break;
05149 }
05150
05151 return NULL;
05152 }
05153
05154
05155 extern WN *emulate(WN *block, WN *tree)
05156 {
05157 WN *wn = NULL;
05158
05159 if (OPCODE_is_intrinsic(WN_opcode(tree)))
05160 {
05161 if (Inline_Intrinsics_Allowed)
05162 {
05163 wn = emulate_intrinsic_op(block, tree);
05164 }
05165 }
05166 else
05167 {
05168 switch(WN_operator(tree))
05169 {
05170 case OPR_NEG:
05171 if (MTYPE_is_quad(WN_rtype(tree)))
05172 {
05173 wn = em_quad_neg(block, tree);
05174 }
05175 break;
05176
05177 case OPR_SELECT:
05178 if (MTYPE_is_quad(WN_rtype(tree)))
05179 {
05180 wn = em_split_select(block, tree);
05181 }
05182 break;
05183
05184 case OPR_SQRT:
05185 if (MTYPE_is_complex(WN_rtype(tree)))
05186 {
05187 if (Inline_Intrinsics_Allowed)
05188 {
05189 wn = em_complex_sqrt(block, WN_kid0(tree));
05190 }
05191 }
05192 break;
05193
05194 case OPR_ALLOCA:
05195 wn = em_alloca(block,tree);
05196 break;
05197
05198 default:
05199 break;
05200 }
05201 }
05202
05203 return wn;
05204 }
05205
05206 #ifdef KEY // bug 6938
05207 extern WN *emulate_fast_exp(WN *block, WN *tree)
05208 {
05209 if (! Inline_Intrinsics_Allowed)
05210 return NULL;
05211
05212 INTRINSIC id = (INTRINSIC) WN_intrinsic(tree);
05213 TYPE_ID rtype = WN_rtype(tree);
05214
05215 switch(id) {
05216 case INTRN_I4EXPEXPR:
05217 case INTRN_I8EXPEXPR:
05218
05219
05220
05221 return em_exp_int(block, by_value(tree, 0), by_value(tree,1), rtype);
05222
05223 case INTRN_F4I4EXPEXPR:
05224 case INTRN_F4I8EXPEXPR:
05225 case INTRN_F8I4EXPEXPR:
05226 case INTRN_F8I8EXPEXPR:
05227 case INTRN_FQI4EXPEXPR:
05228 case INTRN_FQI8EXPEXPR:
05229 case INTRN_C4I4EXPEXPR:
05230 case INTRN_C4I8EXPEXPR:
05231 case INTRN_C8I4EXPEXPR:
05232 case INTRN_C8I8EXPEXPR:
05233 case INTRN_CQI4EXPEXPR:
05234 case INTRN_CQI8EXPEXPR:
05235
05236
05237
05238
05239 return em_exp_int(block, by_value(tree, 0), by_value(tree,1), rtype);
05240
05241 case INTRN_F4EXPEXPR:
05242 case INTRN_F8EXPEXPR:
05243 case INTRN_FQEXPEXPR:
05244 case INTRN_C4EXPEXPR:
05245 case INTRN_C8EXPEXPR:
05246 case INTRN_CQEXPEXPR:
05247 if (Fast_Exp_Allowed)
05248 return em_exp_float(block, by_value(tree, 0), by_value(tree, 1), rtype);
05249 break;
05250 default: ;
05251 break;
05252 }
05253
05254 return NULL;
05255 }
05256 #endif