00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "config.h"
00024 #include "system.h"
00025 #include "coretypes.h"
00026 #include "tm.h"
00027 #include "rtl.h"
00028 #include "tree.h"
00029 #include "tm_p.h"
00030 #include "regs.h"
00031 #include "hard-reg-set.h"
00032 #include "flags.h"
00033 #include "real.h"
00034 #include "insn-config.h"
00035 #include "recog.h"
00036 #include "function.h"
00037 #include "expr.h"
00038 #include "toplev.h"
00039 #include "output.h"
00040 #include "ggc.h"
00041 #include "target.h"
00042
00043
00044
00045
00046
00047
00048
00049 #define HWI_SIGN_EXTEND(low) \
00050 ((((HOST_WIDE_INT) low) < 0) ? ((HOST_WIDE_INT) -1) : ((HOST_WIDE_INT) 0))
00051
00052 static rtx neg_const_int (enum machine_mode, rtx);
00053 static bool plus_minus_operand_p (rtx);
00054 static int simplify_plus_minus_op_data_cmp (const void *, const void *);
00055 static rtx simplify_plus_minus (enum rtx_code, enum machine_mode, rtx,
00056 rtx, int);
00057 static rtx simplify_immed_subreg (enum machine_mode, rtx, enum machine_mode,
00058 unsigned int);
00059 static rtx simplify_associative_operation (enum rtx_code, enum machine_mode,
00060 rtx, rtx);
00061 static rtx simplify_relational_operation_1 (enum rtx_code, enum machine_mode,
00062 enum machine_mode, rtx, rtx);
00063
00064
00065
00066 static rtx
00067 neg_const_int (enum machine_mode mode, rtx i)
00068 {
00069 return gen_int_mode (- INTVAL (i), mode);
00070 }
00071
00072
00073
00074
00075 bool
00076 mode_signbit_p (enum machine_mode mode, rtx x)
00077 {
00078 unsigned HOST_WIDE_INT val;
00079 unsigned int width;
00080
00081 if (GET_MODE_CLASS (mode) != MODE_INT)
00082 return false;
00083
00084 width = GET_MODE_BITSIZE (mode);
00085 if (width == 0)
00086 return false;
00087
00088 if (width <= HOST_BITS_PER_WIDE_INT
00089 && GET_CODE (x) == CONST_INT)
00090 val = INTVAL (x);
00091 else if (width <= 2 * HOST_BITS_PER_WIDE_INT
00092 && GET_CODE (x) == CONST_DOUBLE
00093 && CONST_DOUBLE_LOW (x) == 0)
00094 {
00095 val = CONST_DOUBLE_HIGH (x);
00096 width -= HOST_BITS_PER_WIDE_INT;
00097 }
00098 else
00099 return false;
00100
00101 if (width < HOST_BITS_PER_WIDE_INT)
00102 val &= ((unsigned HOST_WIDE_INT) 1 << width) - 1;
00103 return val == ((unsigned HOST_WIDE_INT) 1 << (width - 1));
00104 }
00105
00106
00107
00108
00109 rtx
00110 simplify_gen_binary (enum rtx_code code, enum machine_mode mode, rtx op0,
00111 rtx op1)
00112 {
00113 rtx tem;
00114
00115
00116 if (GET_RTX_CLASS (code) == RTX_COMM_ARITH
00117 && swap_commutative_operands_p (op0, op1))
00118 tem = op0, op0 = op1, op1 = tem;
00119
00120
00121 tem = simplify_binary_operation (code, mode, op0, op1);
00122 if (tem)
00123 return tem;
00124
00125
00126
00127
00128 if (code == PLUS || code == MINUS)
00129 {
00130 tem = simplify_plus_minus (code, mode, op0, op1, 1);
00131 if (tem)
00132 return tem;
00133 }
00134
00135 return gen_rtx_fmt_ee (code, mode, op0, op1);
00136 }
00137
00138
00139
00140 rtx
00141 avoid_constant_pool_reference (rtx x)
00142 {
00143 rtx c, tmp, addr;
00144 enum machine_mode cmode;
00145
00146 switch (GET_CODE (x))
00147 {
00148 case MEM:
00149 break;
00150
00151 case FLOAT_EXTEND:
00152
00153 tmp = XEXP (x, 0);
00154 c = avoid_constant_pool_reference (tmp);
00155 if (c != tmp && GET_CODE (c) == CONST_DOUBLE)
00156 {
00157 REAL_VALUE_TYPE d;
00158
00159 REAL_VALUE_FROM_CONST_DOUBLE (d, c);
00160 return CONST_DOUBLE_FROM_REAL_VALUE (d, GET_MODE (x));
00161 }
00162 return x;
00163
00164 default:
00165 return x;
00166 }
00167
00168 addr = XEXP (x, 0);
00169
00170
00171 addr = targetm.delegitimize_address (addr);
00172
00173 if (GET_CODE (addr) == LO_SUM)
00174 addr = XEXP (addr, 1);
00175
00176 if (GET_CODE (addr) != SYMBOL_REF
00177 || ! CONSTANT_POOL_ADDRESS_P (addr))
00178 return x;
00179
00180 c = get_pool_constant (addr);
00181 cmode = get_pool_mode (addr);
00182
00183
00184
00185
00186 if (cmode != GET_MODE (x))
00187 {
00188 c = simplify_subreg (GET_MODE (x), c, cmode, 0);
00189 return c ? c : x;
00190 }
00191
00192 return c;
00193 }
00194
00195
00196
00197 bool
00198 constant_pool_reference_p (rtx x)
00199 {
00200 return avoid_constant_pool_reference (x) != x;
00201 }
00202
00203
00204
00205
00206 rtx
00207 simplify_gen_unary (enum rtx_code code, enum machine_mode mode, rtx op,
00208 enum machine_mode op_mode)
00209 {
00210 rtx tem;
00211
00212
00213 if ((tem = simplify_unary_operation (code, mode, op, op_mode)) != 0)
00214 return tem;
00215
00216 return gen_rtx_fmt_e (code, mode, op);
00217 }
00218
00219
00220
00221 rtx
00222 simplify_gen_ternary (enum rtx_code code, enum machine_mode mode,
00223 enum machine_mode op0_mode, rtx op0, rtx op1, rtx op2)
00224 {
00225 rtx tem;
00226
00227
00228 if (0 != (tem = simplify_ternary_operation (code, mode, op0_mode,
00229 op0, op1, op2)))
00230 return tem;
00231
00232 return gen_rtx_fmt_eee (code, mode, op0, op1, op2);
00233 }
00234
00235
00236
00237
00238 rtx
00239 simplify_gen_relational (enum rtx_code code, enum machine_mode mode,
00240 enum machine_mode cmp_mode, rtx op0, rtx op1)
00241 {
00242 rtx tem;
00243
00244 if (0 != (tem = simplify_relational_operation (code, mode, cmp_mode,
00245 op0, op1)))
00246 return tem;
00247
00248 return gen_rtx_fmt_ee (code, mode, op0, op1);
00249 }
00250
00251
00252
00253
00254 rtx
00255 simplify_replace_rtx (rtx x, rtx old_rtx, rtx new_rtx)
00256 {
00257 enum rtx_code code = GET_CODE (x);
00258 enum machine_mode mode = GET_MODE (x);
00259 enum machine_mode op_mode;
00260 rtx op0, op1, op2;
00261
00262
00263
00264
00265
00266 if (x == old_rtx)
00267 return new_rtx;
00268
00269 switch (GET_RTX_CLASS (code))
00270 {
00271 case RTX_UNARY:
00272 op0 = XEXP (x, 0);
00273 op_mode = GET_MODE (op0);
00274 op0 = simplify_replace_rtx (op0, old_rtx, new_rtx);
00275 if (op0 == XEXP (x, 0))
00276 return x;
00277 return simplify_gen_unary (code, mode, op0, op_mode);
00278
00279 case RTX_BIN_ARITH:
00280 case RTX_COMM_ARITH:
00281 op0 = simplify_replace_rtx (XEXP (x, 0), old_rtx, new_rtx);
00282 op1 = simplify_replace_rtx (XEXP (x, 1), old_rtx, new_rtx);
00283 if (op0 == XEXP (x, 0) && op1 == XEXP (x, 1))
00284 return x;
00285 return simplify_gen_binary (code, mode, op0, op1);
00286
00287 case RTX_COMPARE:
00288 case RTX_COMM_COMPARE:
00289 op0 = XEXP (x, 0);
00290 op1 = XEXP (x, 1);
00291 op_mode = GET_MODE (op0) != VOIDmode ? GET_MODE (op0) : GET_MODE (op1);
00292 op0 = simplify_replace_rtx (op0, old_rtx, new_rtx);
00293 op1 = simplify_replace_rtx (op1, old_rtx, new_rtx);
00294 if (op0 == XEXP (x, 0) && op1 == XEXP (x, 1))
00295 return x;
00296 return simplify_gen_relational (code, mode, op_mode, op0, op1);
00297
00298 case RTX_TERNARY:
00299 case RTX_BITFIELD_OPS:
00300 op0 = XEXP (x, 0);
00301 op_mode = GET_MODE (op0);
00302 op0 = simplify_replace_rtx (op0, old_rtx, new_rtx);
00303 op1 = simplify_replace_rtx (XEXP (x, 1), old_rtx, new_rtx);
00304 op2 = simplify_replace_rtx (XEXP (x, 2), old_rtx, new_rtx);
00305 if (op0 == XEXP (x, 0) && op1 == XEXP (x, 1) && op2 == XEXP (x, 2))
00306 return x;
00307 if (op_mode == VOIDmode)
00308 op_mode = GET_MODE (op0);
00309 return simplify_gen_ternary (code, mode, op_mode, op0, op1, op2);
00310
00311 case RTX_EXTRA:
00312
00313 if (code == SUBREG)
00314 {
00315 op0 = simplify_replace_rtx (SUBREG_REG (x), old_rtx, new_rtx);
00316 if (op0 == SUBREG_REG (x))
00317 return x;
00318 op0 = simplify_gen_subreg (GET_MODE (x), op0,
00319 GET_MODE (SUBREG_REG (x)),
00320 SUBREG_BYTE (x));
00321 return op0 ? op0 : x;
00322 }
00323 break;
00324
00325 case RTX_OBJ:
00326 if (code == MEM)
00327 {
00328 op0 = simplify_replace_rtx (XEXP (x, 0), old_rtx, new_rtx);
00329 if (op0 == XEXP (x, 0))
00330 return x;
00331 return replace_equiv_address_nv (x, op0);
00332 }
00333 else if (code == LO_SUM)
00334 {
00335 op0 = simplify_replace_rtx (XEXP (x, 0), old_rtx, new_rtx);
00336 op1 = simplify_replace_rtx (XEXP (x, 1), old_rtx, new_rtx);
00337
00338
00339 if (GET_CODE (op0) == HIGH && rtx_equal_p (XEXP (op0, 0), op1))
00340 return op1;
00341
00342 if (op0 == XEXP (x, 0) && op1 == XEXP (x, 1))
00343 return x;
00344 return gen_rtx_LO_SUM (mode, op0, op1);
00345 }
00346 else if (code == REG)
00347 {
00348 if (rtx_equal_p (x, old_rtx))
00349 return new_rtx;
00350 }
00351 break;
00352
00353 default:
00354 break;
00355 }
00356 return x;
00357 }
00358
00359
00360
00361
00362 rtx
00363 simplify_unary_operation (enum rtx_code code, enum machine_mode mode,
00364 rtx op, enum machine_mode op_mode)
00365 {
00366 unsigned int width = GET_MODE_BITSIZE (mode);
00367 rtx trueop = avoid_constant_pool_reference (op);
00368
00369 if (code == VEC_DUPLICATE)
00370 {
00371 gcc_assert (VECTOR_MODE_P (mode));
00372 if (GET_MODE (trueop) != VOIDmode)
00373 {
00374 if (!VECTOR_MODE_P (GET_MODE (trueop)))
00375 gcc_assert (GET_MODE_INNER (mode) == GET_MODE (trueop));
00376 else
00377 gcc_assert (GET_MODE_INNER (mode) == GET_MODE_INNER
00378 (GET_MODE (trueop)));
00379 }
00380 if (GET_CODE (trueop) == CONST_INT || GET_CODE (trueop) == CONST_DOUBLE
00381 || GET_CODE (trueop) == CONST_VECTOR)
00382 {
00383 int elt_size = GET_MODE_SIZE (GET_MODE_INNER (mode));
00384 unsigned n_elts = (GET_MODE_SIZE (mode) / elt_size);
00385 rtvec v = rtvec_alloc (n_elts);
00386 unsigned int i;
00387
00388 if (GET_CODE (trueop) != CONST_VECTOR)
00389 for (i = 0; i < n_elts; i++)
00390 RTVEC_ELT (v, i) = trueop;
00391 else
00392 {
00393 enum machine_mode inmode = GET_MODE (trueop);
00394 int in_elt_size = GET_MODE_SIZE (GET_MODE_INNER (inmode));
00395 unsigned in_n_elts = (GET_MODE_SIZE (inmode) / in_elt_size);
00396
00397 gcc_assert (in_n_elts < n_elts);
00398 gcc_assert ((n_elts % in_n_elts) == 0);
00399 for (i = 0; i < n_elts; i++)
00400 RTVEC_ELT (v, i) = CONST_VECTOR_ELT (trueop, i % in_n_elts);
00401 }
00402 return gen_rtx_CONST_VECTOR (mode, v);
00403 }
00404 }
00405 else if (GET_CODE (op) == CONST)
00406 return simplify_unary_operation (code, mode, XEXP (op, 0), op_mode);
00407
00408 if (VECTOR_MODE_P (mode) && GET_CODE (trueop) == CONST_VECTOR)
00409 {
00410 int elt_size = GET_MODE_SIZE (GET_MODE_INNER (mode));
00411 unsigned n_elts = (GET_MODE_SIZE (mode) / elt_size);
00412 enum machine_mode opmode = GET_MODE (trueop);
00413 int op_elt_size = GET_MODE_SIZE (GET_MODE_INNER (opmode));
00414 unsigned op_n_elts = (GET_MODE_SIZE (opmode) / op_elt_size);
00415 rtvec v = rtvec_alloc (n_elts);
00416 unsigned int i;
00417
00418 gcc_assert (op_n_elts == n_elts);
00419 for (i = 0; i < n_elts; i++)
00420 {
00421 rtx x = simplify_unary_operation (code, GET_MODE_INNER (mode),
00422 CONST_VECTOR_ELT (trueop, i),
00423 GET_MODE_INNER (opmode));
00424 if (!x)
00425 return 0;
00426 RTVEC_ELT (v, i) = x;
00427 }
00428 return gen_rtx_CONST_VECTOR (mode, v);
00429 }
00430
00431
00432
00433
00434
00435 if (code == FLOAT && GET_MODE (trueop) == VOIDmode
00436 && (GET_CODE (trueop) == CONST_DOUBLE || GET_CODE (trueop) == CONST_INT))
00437 {
00438 HOST_WIDE_INT hv, lv;
00439 REAL_VALUE_TYPE d;
00440
00441 if (GET_CODE (trueop) == CONST_INT)
00442 lv = INTVAL (trueop), hv = HWI_SIGN_EXTEND (lv);
00443 else
00444 lv = CONST_DOUBLE_LOW (trueop), hv = CONST_DOUBLE_HIGH (trueop);
00445
00446 REAL_VALUE_FROM_INT (d, lv, hv, mode);
00447 d = real_value_truncate (mode, d);
00448 return CONST_DOUBLE_FROM_REAL_VALUE (d, mode);
00449 }
00450 else if (code == UNSIGNED_FLOAT && GET_MODE (trueop) == VOIDmode
00451 && (GET_CODE (trueop) == CONST_DOUBLE
00452 || GET_CODE (trueop) == CONST_INT))
00453 {
00454 HOST_WIDE_INT hv, lv;
00455 REAL_VALUE_TYPE d;
00456
00457 if (GET_CODE (trueop) == CONST_INT)
00458 lv = INTVAL (trueop), hv = HWI_SIGN_EXTEND (lv);
00459 else
00460 lv = CONST_DOUBLE_LOW (trueop), hv = CONST_DOUBLE_HIGH (trueop);
00461
00462 if (op_mode == VOIDmode)
00463 {
00464
00465
00466 if (hv < 0)
00467 return 0;
00468 }
00469 else if (GET_MODE_BITSIZE (op_mode) >= HOST_BITS_PER_WIDE_INT * 2)
00470 ;
00471 else
00472 hv = 0, lv &= GET_MODE_MASK (op_mode);
00473
00474 REAL_VALUE_FROM_UNSIGNED_INT (d, lv, hv, mode);
00475 d = real_value_truncate (mode, d);
00476 return CONST_DOUBLE_FROM_REAL_VALUE (d, mode);
00477 }
00478
00479 if (GET_CODE (trueop) == CONST_INT
00480 && width <= HOST_BITS_PER_WIDE_INT && width > 0)
00481 {
00482 HOST_WIDE_INT arg0 = INTVAL (trueop);
00483 HOST_WIDE_INT val;
00484
00485 switch (code)
00486 {
00487 case NOT:
00488 val = ~ arg0;
00489 break;
00490
00491 case NEG:
00492 val = - arg0;
00493 break;
00494
00495 case ABS:
00496 val = (arg0 >= 0 ? arg0 : - arg0);
00497 break;
00498
00499 case FFS:
00500
00501
00502 arg0 &= GET_MODE_MASK (mode);
00503 val = exact_log2 (arg0 & (- arg0)) + 1;
00504 break;
00505
00506 case CLZ:
00507 arg0 &= GET_MODE_MASK (mode);
00508 if (arg0 == 0 && CLZ_DEFINED_VALUE_AT_ZERO (mode, val))
00509 ;
00510 else
00511 val = GET_MODE_BITSIZE (mode) - floor_log2 (arg0) - 1;
00512 break;
00513
00514 case CTZ:
00515 arg0 &= GET_MODE_MASK (mode);
00516 if (arg0 == 0)
00517 {
00518
00519
00520 if (! CTZ_DEFINED_VALUE_AT_ZERO (mode, val))
00521 val = GET_MODE_BITSIZE (mode);
00522 }
00523 else
00524 val = exact_log2 (arg0 & -arg0);
00525 break;
00526
00527 case POPCOUNT:
00528 arg0 &= GET_MODE_MASK (mode);
00529 val = 0;
00530 while (arg0)
00531 val++, arg0 &= arg0 - 1;
00532 break;
00533
00534 case PARITY:
00535 arg0 &= GET_MODE_MASK (mode);
00536 val = 0;
00537 while (arg0)
00538 val++, arg0 &= arg0 - 1;
00539 val &= 1;
00540 break;
00541
00542 case TRUNCATE:
00543 val = arg0;
00544 break;
00545
00546 case ZERO_EXTEND:
00547
00548
00549 gcc_assert (op_mode != VOIDmode);
00550 if (GET_MODE_BITSIZE (op_mode) == HOST_BITS_PER_WIDE_INT)
00551 {
00552
00553
00554
00555 gcc_assert (width == GET_MODE_BITSIZE (op_mode));
00556 val = arg0;
00557 }
00558 else if (GET_MODE_BITSIZE (op_mode) < HOST_BITS_PER_WIDE_INT)
00559 val = arg0 & ~((HOST_WIDE_INT) (-1) << GET_MODE_BITSIZE (op_mode));
00560 else
00561 return 0;
00562 break;
00563
00564 case SIGN_EXTEND:
00565 if (op_mode == VOIDmode)
00566 op_mode = mode;
00567 if (GET_MODE_BITSIZE (op_mode) == HOST_BITS_PER_WIDE_INT)
00568 {
00569
00570
00571
00572 gcc_assert (width == GET_MODE_BITSIZE (op_mode));
00573 val = arg0;
00574 }
00575 else if (GET_MODE_BITSIZE (op_mode) < HOST_BITS_PER_WIDE_INT)
00576 {
00577 val
00578 = arg0 & ~((HOST_WIDE_INT) (-1) << GET_MODE_BITSIZE (op_mode));
00579 if (val
00580 & ((HOST_WIDE_INT) 1 << (GET_MODE_BITSIZE (op_mode) - 1)))
00581 val -= (HOST_WIDE_INT) 1 << GET_MODE_BITSIZE (op_mode);
00582 }
00583 else
00584 return 0;
00585 break;
00586
00587 case SQRT:
00588 case FLOAT_EXTEND:
00589 case FLOAT_TRUNCATE:
00590 case SS_TRUNCATE:
00591 case US_TRUNCATE:
00592 return 0;
00593
00594 default:
00595 gcc_unreachable ();
00596 }
00597
00598 val = trunc_int_for_mode (val, mode);
00599
00600 return GEN_INT (val);
00601 }
00602
00603
00604
00605 else if (GET_MODE (trueop) == VOIDmode
00606 && width <= HOST_BITS_PER_WIDE_INT * 2
00607 && (GET_CODE (trueop) == CONST_DOUBLE
00608 || GET_CODE (trueop) == CONST_INT))
00609 {
00610 unsigned HOST_WIDE_INT l1, lv;
00611 HOST_WIDE_INT h1, hv;
00612
00613 if (GET_CODE (trueop) == CONST_DOUBLE)
00614 l1 = CONST_DOUBLE_LOW (trueop), h1 = CONST_DOUBLE_HIGH (trueop);
00615 else
00616 l1 = INTVAL (trueop), h1 = HWI_SIGN_EXTEND (l1);
00617
00618 switch (code)
00619 {
00620 case NOT:
00621 lv = ~ l1;
00622 hv = ~ h1;
00623 break;
00624
00625 case NEG:
00626 neg_double (l1, h1, &lv, &hv);
00627 break;
00628
00629 case ABS:
00630 if (h1 < 0)
00631 neg_double (l1, h1, &lv, &hv);
00632 else
00633 lv = l1, hv = h1;
00634 break;
00635
00636 case FFS:
00637 hv = 0;
00638 if (l1 == 0)
00639 {
00640 if (h1 == 0)
00641 lv = 0;
00642 else
00643 lv = HOST_BITS_PER_WIDE_INT + exact_log2 (h1 & -h1) + 1;
00644 }
00645 else
00646 lv = exact_log2 (l1 & -l1) + 1;
00647 break;
00648
00649 case CLZ:
00650 hv = 0;
00651 if (h1 != 0)
00652 lv = GET_MODE_BITSIZE (mode) - floor_log2 (h1) - 1
00653 - HOST_BITS_PER_WIDE_INT;
00654 else if (l1 != 0)
00655 lv = GET_MODE_BITSIZE (mode) - floor_log2 (l1) - 1;
00656 else if (! CLZ_DEFINED_VALUE_AT_ZERO (mode, lv))
00657 lv = GET_MODE_BITSIZE (mode);
00658 break;
00659
00660 case CTZ:
00661 hv = 0;
00662 if (l1 != 0)
00663 lv = exact_log2 (l1 & -l1);
00664 else if (h1 != 0)
00665 lv = HOST_BITS_PER_WIDE_INT + exact_log2 (h1 & -h1);
00666 else if (! CTZ_DEFINED_VALUE_AT_ZERO (mode, lv))
00667 lv = GET_MODE_BITSIZE (mode);
00668 break;
00669
00670 case POPCOUNT:
00671 hv = 0;
00672 lv = 0;
00673 while (l1)
00674 lv++, l1 &= l1 - 1;
00675 while (h1)
00676 lv++, h1 &= h1 - 1;
00677 break;
00678
00679 case PARITY:
00680 hv = 0;
00681 lv = 0;
00682 while (l1)
00683 lv++, l1 &= l1 - 1;
00684 while (h1)
00685 lv++, h1 &= h1 - 1;
00686 lv &= 1;
00687 break;
00688
00689 case TRUNCATE:
00690
00691 lv = l1, hv = h1;
00692 break;
00693
00694 case ZERO_EXTEND:
00695 gcc_assert (op_mode != VOIDmode);
00696
00697 if (GET_MODE_BITSIZE (op_mode) > HOST_BITS_PER_WIDE_INT)
00698 return 0;
00699
00700 hv = 0;
00701 lv = l1 & GET_MODE_MASK (op_mode);
00702 break;
00703
00704 case SIGN_EXTEND:
00705 if (op_mode == VOIDmode
00706 || GET_MODE_BITSIZE (op_mode) > HOST_BITS_PER_WIDE_INT)
00707 return 0;
00708 else
00709 {
00710 lv = l1 & GET_MODE_MASK (op_mode);
00711 if (GET_MODE_BITSIZE (op_mode) < HOST_BITS_PER_WIDE_INT
00712 && (lv & ((HOST_WIDE_INT) 1
00713 << (GET_MODE_BITSIZE (op_mode) - 1))) != 0)
00714 lv -= (HOST_WIDE_INT) 1 << GET_MODE_BITSIZE (op_mode);
00715
00716 hv = HWI_SIGN_EXTEND (lv);
00717 }
00718 break;
00719
00720 case SQRT:
00721 return 0;
00722
00723 default:
00724 return 0;
00725 }
00726
00727 return immed_double_const (lv, hv, mode);
00728 }
00729
00730 else if (GET_CODE (trueop) == CONST_DOUBLE
00731 && GET_MODE_CLASS (mode) == MODE_FLOAT)
00732 {
00733 REAL_VALUE_TYPE d, t;
00734 REAL_VALUE_FROM_CONST_DOUBLE (d, trueop);
00735
00736 switch (code)
00737 {
00738 case SQRT:
00739 if (HONOR_SNANS (mode) && real_isnan (&d))
00740 return 0;
00741 real_sqrt (&t, mode, &d);
00742 d = t;
00743 break;
00744 case ABS:
00745 d = REAL_VALUE_ABS (d);
00746 break;
00747 case NEG:
00748 d = REAL_VALUE_NEGATE (d);
00749 break;
00750 case FLOAT_TRUNCATE:
00751 d = real_value_truncate (mode, d);
00752 break;
00753 case FLOAT_EXTEND:
00754
00755 break;
00756 case FIX:
00757 real_arithmetic (&d, FIX_TRUNC_EXPR, &d, NULL);
00758 break;
00759 case NOT:
00760 {
00761 long tmp[4];
00762 int i;
00763
00764 real_to_target (tmp, &d, GET_MODE (trueop));
00765 for (i = 0; i < 4; i++)
00766 tmp[i] = ~tmp[i];
00767 real_from_target (&d, tmp, mode);
00768 }
00769 break;
00770 default:
00771 gcc_unreachable ();
00772 }
00773 return CONST_DOUBLE_FROM_REAL_VALUE (d, mode);
00774 }
00775
00776 else if (GET_CODE (trueop) == CONST_DOUBLE
00777 && GET_MODE_CLASS (GET_MODE (trueop)) == MODE_FLOAT
00778 && GET_MODE_CLASS (mode) == MODE_INT
00779 && width <= 2*HOST_BITS_PER_WIDE_INT && width > 0)
00780 {
00781
00782
00783
00784
00785
00786 HOST_WIDE_INT xh, xl, th, tl;
00787 REAL_VALUE_TYPE x, t;
00788 REAL_VALUE_FROM_CONST_DOUBLE (x, trueop);
00789 switch (code)
00790 {
00791 case FIX:
00792 if (REAL_VALUE_ISNAN (x))
00793 return const0_rtx;
00794
00795
00796 if (width > HOST_BITS_PER_WIDE_INT)
00797 {
00798 th = ((unsigned HOST_WIDE_INT) 1
00799 << (width - HOST_BITS_PER_WIDE_INT - 1)) - 1;
00800 tl = -1;
00801 }
00802 else
00803 {
00804 th = 0;
00805 tl = ((unsigned HOST_WIDE_INT) 1 << (width - 1)) - 1;
00806 }
00807 real_from_integer (&t, VOIDmode, tl, th, 0);
00808 if (REAL_VALUES_LESS (t, x))
00809 {
00810 xh = th;
00811 xl = tl;
00812 break;
00813 }
00814
00815
00816 if (width > HOST_BITS_PER_WIDE_INT)
00817 {
00818 th = (HOST_WIDE_INT) -1 << (width - HOST_BITS_PER_WIDE_INT - 1);
00819 tl = 0;
00820 }
00821 else
00822 {
00823 th = -1;
00824 tl = (HOST_WIDE_INT) -1 << (width - 1);
00825 }
00826 real_from_integer (&t, VOIDmode, tl, th, 0);
00827 if (REAL_VALUES_LESS (x, t))
00828 {
00829 xh = th;
00830 xl = tl;
00831 break;
00832 }
00833 REAL_VALUE_TO_INT (&xl, &xh, x);
00834 break;
00835
00836 case UNSIGNED_FIX:
00837 if (REAL_VALUE_ISNAN (x) || REAL_VALUE_NEGATIVE (x))
00838 return const0_rtx;
00839
00840
00841 if (width == 2*HOST_BITS_PER_WIDE_INT)
00842 {
00843 th = -1;
00844 tl = -1;
00845 }
00846 else if (width >= HOST_BITS_PER_WIDE_INT)
00847 {
00848 th = ((unsigned HOST_WIDE_INT) 1
00849 << (width - HOST_BITS_PER_WIDE_INT)) - 1;
00850 tl = -1;
00851 }
00852 else
00853 {
00854 th = 0;
00855 tl = ((unsigned HOST_WIDE_INT) 1 << width) - 1;
00856 }
00857 real_from_integer (&t, VOIDmode, tl, th, 1);
00858 if (REAL_VALUES_LESS (t, x))
00859 {
00860 xh = th;
00861 xl = tl;
00862 break;
00863 }
00864
00865 REAL_VALUE_TO_INT (&xl, &xh, x);
00866 break;
00867
00868 default:
00869 gcc_unreachable ();
00870 }
00871 return immed_double_const (xl, xh, mode);
00872 }
00873
00874
00875
00876 else
00877 {
00878 enum rtx_code reversed;
00879 rtx temp;
00880
00881
00882
00883 switch (code)
00884 {
00885 case NOT:
00886
00887 if (GET_CODE (op) == NOT)
00888 return XEXP (op, 0);
00889
00890
00891 if (COMPARISON_P (op)
00892 && (mode == BImode || STORE_FLAG_VALUE == -1)
00893 && ((reversed = reversed_comparison_code (op, NULL_RTX))
00894 != UNKNOWN))
00895 return simplify_gen_relational (reversed, mode, VOIDmode,
00896 XEXP (op, 0), XEXP (op, 1));
00897
00898
00899 if (GET_CODE (op) == PLUS
00900 && XEXP (op, 1) == constm1_rtx)
00901 return simplify_gen_unary (NEG, mode, XEXP (op, 0), mode);
00902
00903
00904 if (GET_CODE (op) == NEG)
00905 return plus_constant (XEXP (op, 0), -1);
00906
00907
00908 if (GET_CODE (op) == XOR
00909 && GET_CODE (XEXP (op, 1)) == CONST_INT
00910 && (temp = simplify_unary_operation (NOT, mode,
00911 XEXP (op, 1),
00912 mode)) != 0)
00913 return simplify_gen_binary (XOR, mode, XEXP (op, 0), temp);
00914
00915
00916 if (GET_CODE (op) == PLUS
00917 && GET_CODE (XEXP (op, 1)) == CONST_INT
00918 && mode_signbit_p (mode, XEXP (op, 1))
00919 && (temp = simplify_unary_operation (NOT, mode,
00920 XEXP (op, 1),
00921 mode)) != 0)
00922 return simplify_gen_binary (XOR, mode, XEXP (op, 0), temp);
00923
00924
00925
00926
00927
00928
00929
00930
00931 if (GET_CODE (op) == ASHIFT
00932 && XEXP (op, 0) == const1_rtx)
00933 {
00934 temp = simplify_gen_unary (NOT, mode, const1_rtx, mode);
00935 return simplify_gen_binary (ROTATE, mode, temp, XEXP (op, 1));
00936 }
00937
00938
00939
00940 if (STORE_FLAG_VALUE == -1
00941 && COMPARISON_P (op)
00942 && (reversed = reversed_comparison_code (op, NULL_RTX))
00943 != UNKNOWN)
00944 return simplify_gen_relational (reversed, mode, VOIDmode,
00945 XEXP (op, 0), XEXP (op, 1));
00946
00947
00948
00949
00950
00951 if (STORE_FLAG_VALUE == -1
00952 && GET_CODE (op) == ASHIFTRT
00953 && GET_CODE (XEXP (op, 1)) == CONST_INT
00954 && INTVAL (XEXP (op, 1)) == GET_MODE_BITSIZE (mode) - 1)
00955 return simplify_gen_relational (GE, mode, VOIDmode,
00956 XEXP (op, 0), const0_rtx);
00957
00958 break;
00959
00960 case NEG:
00961
00962 if (GET_CODE (op) == NEG)
00963 return XEXP (op, 0);
00964
00965
00966 if (GET_CODE (op) == PLUS
00967 && XEXP (op, 1) == const1_rtx)
00968 return simplify_gen_unary (NOT, mode, XEXP (op, 0), mode);
00969
00970
00971 if (GET_CODE (op) == NOT)
00972 return plus_constant (XEXP (op, 0), 1);
00973
00974
00975
00976
00977
00978
00979 if (GET_CODE (op) == MINUS
00980 && !HONOR_SIGNED_ZEROS (mode)
00981 && !HONOR_SIGN_DEPENDENT_ROUNDING (mode))
00982 return simplify_gen_binary (MINUS, mode, XEXP (op, 1),
00983 XEXP (op, 0));
00984
00985 if (GET_CODE (op) == PLUS
00986 && !HONOR_SIGNED_ZEROS (mode)
00987 && !HONOR_SIGN_DEPENDENT_ROUNDING (mode))
00988 {
00989
00990 if (GET_CODE (XEXP (op, 1)) == CONST_INT
00991 || GET_CODE (XEXP (op, 1)) == CONST_DOUBLE)
00992 {
00993 temp = simplify_unary_operation (NEG, mode, XEXP (op, 1),
00994 mode);
00995 if (temp)
00996 return simplify_gen_binary (MINUS, mode, temp,
00997 XEXP (op, 0));
00998 }
00999
01000
01001 temp = simplify_gen_unary (NEG, mode, XEXP (op, 0), mode);
01002 return simplify_gen_binary (MINUS, mode, temp, XEXP (op, 1));
01003 }
01004
01005
01006
01007 if (GET_CODE (op) == MULT
01008 && !HONOR_SIGN_DEPENDENT_ROUNDING (mode))
01009 {
01010 temp = simplify_gen_unary (NEG, mode, XEXP (op, 0), mode);
01011 return simplify_gen_binary (MULT, mode, temp, XEXP (op, 1));
01012 }
01013
01014
01015
01016
01017 if (GET_CODE (op) == ASHIFT)
01018 {
01019 temp = simplify_unary_operation (NEG, mode, XEXP (op, 0),
01020 mode);
01021 if (temp)
01022 return simplify_gen_binary (ASHIFT, mode, temp,
01023 XEXP (op, 1));
01024 }
01025
01026
01027
01028 if (GET_CODE (op) == ASHIFTRT
01029 && GET_CODE (XEXP (op, 1)) == CONST_INT
01030 && INTVAL (XEXP (op, 1)) == GET_MODE_BITSIZE (mode) - 1)
01031 return simplify_gen_binary (LSHIFTRT, mode,
01032 XEXP (op, 0), XEXP (op, 1));
01033
01034
01035
01036 if (GET_CODE (op) == LSHIFTRT
01037 && GET_CODE (XEXP (op, 1)) == CONST_INT
01038 && INTVAL (XEXP (op, 1)) == GET_MODE_BITSIZE (mode) - 1)
01039 return simplify_gen_binary (ASHIFTRT, mode,
01040 XEXP (op, 0), XEXP (op, 1));
01041
01042 break;
01043
01044 case SIGN_EXTEND:
01045
01046
01047
01048
01049 if (GET_CODE (op) == TRUNCATE
01050 && GET_MODE (XEXP (op, 0)) == mode
01051 && GET_CODE (XEXP (op, 0)) == MINUS
01052 && GET_CODE (XEXP (XEXP (op, 0), 0)) == LABEL_REF
01053 && GET_CODE (XEXP (XEXP (op, 0), 1)) == LABEL_REF)
01054 return XEXP (op, 0);
01055
01056
01057
01058
01059 if (GET_CODE (op) == SUBREG
01060 && SUBREG_PROMOTED_VAR_P (op)
01061 && ! SUBREG_PROMOTED_UNSIGNED_P (op)
01062 && GET_MODE (XEXP (op, 0)) == mode)
01063 return XEXP (op, 0);
01064
01065 #if defined(POINTERS_EXTEND_UNSIGNED) && !defined(HAVE_ptr_extend)
01066 if (! POINTERS_EXTEND_UNSIGNED
01067 && mode == Pmode && GET_MODE (op) == ptr_mode
01068 && (CONSTANT_P (op)
01069 || (GET_CODE (op) == SUBREG
01070 && REG_P (SUBREG_REG (op))
01071 && REG_POINTER (SUBREG_REG (op))
01072 && GET_MODE (SUBREG_REG (op)) == Pmode)))
01073 return convert_memory_address (Pmode, op);
01074 #endif
01075 break;
01076
01077 case ZERO_EXTEND:
01078
01079
01080
01081 if (GET_CODE (op) == SUBREG
01082 && SUBREG_PROMOTED_VAR_P (op)
01083 && SUBREG_PROMOTED_UNSIGNED_P (op) > 0
01084 && GET_MODE (XEXP (op, 0)) == mode)
01085 return XEXP (op, 0);
01086
01087 #if defined(POINTERS_EXTEND_UNSIGNED) && !defined(HAVE_ptr_extend)
01088 if (POINTERS_EXTEND_UNSIGNED > 0
01089 && mode == Pmode && GET_MODE (op) == ptr_mode
01090 && (CONSTANT_P (op)
01091 || (GET_CODE (op) == SUBREG
01092 && REG_P (SUBREG_REG (op))
01093 && REG_POINTER (SUBREG_REG (op))
01094 && GET_MODE (SUBREG_REG (op)) == Pmode)))
01095 return convert_memory_address (Pmode, op);
01096 #endif
01097 break;
01098
01099 default:
01100 break;
01101 }
01102
01103 return 0;
01104 }
01105 }
01106
01107
01108
01109
01110
01111
01112
01113 static rtx
01114 simplify_associative_operation (enum rtx_code code, enum machine_mode mode,
01115 rtx op0, rtx op1)
01116 {
01117 rtx tem;
01118
01119
01120 if (GET_CODE (op1) == code)
01121 {
01122
01123 if (GET_CODE (op0) == code)
01124 {
01125 tem = simplify_gen_binary (code, mode, op0, XEXP (op1, 0));
01126 return simplify_gen_binary (code, mode, tem, XEXP (op1, 1));
01127 }
01128
01129
01130 if (! swap_commutative_operands_p (op1, op0))
01131 return simplify_gen_binary (code, mode, op1, op0);
01132
01133 tem = op0;
01134 op0 = op1;
01135 op1 = tem;
01136 }
01137
01138 if (GET_CODE (op0) == code)
01139 {
01140
01141 if (swap_commutative_operands_p (XEXP (op0, 1), op1))
01142 {
01143 tem = simplify_gen_binary (code, mode, XEXP (op0, 0), op1);
01144 return simplify_gen_binary (code, mode, tem, XEXP (op0, 1));
01145 }
01146
01147
01148 tem = swap_commutative_operands_p (XEXP (op0, 1), op1)
01149 ? simplify_binary_operation (code, mode, op1, XEXP (op0, 1))
01150 : simplify_binary_operation (code, mode, XEXP (op0, 1), op1);
01151 if (tem != 0)
01152 return simplify_gen_binary (code, mode, XEXP (op0, 0), tem);
01153
01154
01155 tem = swap_commutative_operands_p (XEXP (op0, 0), op1)
01156 ? simplify_binary_operation (code, mode, op1, XEXP (op0, 0))
01157 : simplify_binary_operation (code, mode, XEXP (op0, 0), op1);
01158 if (tem != 0)
01159 return simplify_gen_binary (code, mode, tem, XEXP (op0, 1));
01160 }
01161
01162 return 0;
01163 }
01164
01165
01166
01167
01168
01169
01170 rtx
01171 simplify_binary_operation (enum rtx_code code, enum machine_mode mode,
01172 rtx op0, rtx op1)
01173 {
01174 HOST_WIDE_INT arg0, arg1, arg0s, arg1s;
01175 HOST_WIDE_INT val;
01176 unsigned int width = GET_MODE_BITSIZE (mode);
01177 rtx trueop0, trueop1;
01178 rtx tem;
01179
01180
01181
01182
01183
01184 gcc_assert (GET_RTX_CLASS (code) != RTX_COMPARE);
01185 gcc_assert (GET_RTX_CLASS (code) != RTX_COMM_COMPARE);
01186
01187
01188 if (GET_RTX_CLASS (code) == RTX_COMM_ARITH
01189 && swap_commutative_operands_p (op0, op1))
01190 {
01191 tem = op0, op0 = op1, op1 = tem;
01192 }
01193
01194 trueop0 = avoid_constant_pool_reference (op0);
01195 trueop1 = avoid_constant_pool_reference (op1);
01196
01197 if (VECTOR_MODE_P (mode)
01198 && code != VEC_CONCAT
01199 && GET_CODE (trueop0) == CONST_VECTOR
01200 && GET_CODE (trueop1) == CONST_VECTOR)
01201 {
01202 unsigned n_elts = GET_MODE_NUNITS (mode);
01203 enum machine_mode op0mode = GET_MODE (trueop0);
01204 unsigned op0_n_elts = GET_MODE_NUNITS (op0mode);
01205 enum machine_mode op1mode = GET_MODE (trueop1);
01206 unsigned op1_n_elts = GET_MODE_NUNITS (op1mode);
01207 rtvec v = rtvec_alloc (n_elts);
01208 unsigned int i;
01209
01210 gcc_assert (op0_n_elts == n_elts);
01211 gcc_assert (op1_n_elts == n_elts);
01212 for (i = 0; i < n_elts; i++)
01213 {
01214 rtx x = simplify_binary_operation (code, GET_MODE_INNER (mode),
01215 CONST_VECTOR_ELT (trueop0, i),
01216 CONST_VECTOR_ELT (trueop1, i));
01217 if (!x)
01218 return 0;
01219 RTVEC_ELT (v, i) = x;
01220 }
01221
01222 return gen_rtx_CONST_VECTOR (mode, v);
01223 }
01224
01225 if (VECTOR_MODE_P (mode)
01226 && code == VEC_CONCAT
01227 && CONSTANT_P (trueop0) && CONSTANT_P (trueop1))
01228 {
01229 unsigned n_elts = GET_MODE_NUNITS (mode);
01230 rtvec v = rtvec_alloc (n_elts);
01231
01232 gcc_assert (n_elts >= 2);
01233 if (n_elts == 2)
01234 {
01235 gcc_assert (GET_CODE (trueop0) != CONST_VECTOR);
01236 gcc_assert (GET_CODE (trueop1) != CONST_VECTOR);
01237
01238 RTVEC_ELT (v, 0) = trueop0;
01239 RTVEC_ELT (v, 1) = trueop1;
01240 }
01241 else
01242 {
01243 unsigned op0_n_elts = GET_MODE_NUNITS (GET_MODE (trueop0));
01244 unsigned op1_n_elts = GET_MODE_NUNITS (GET_MODE (trueop1));
01245 unsigned i;
01246
01247 gcc_assert (GET_CODE (trueop0) == CONST_VECTOR);
01248 gcc_assert (GET_CODE (trueop1) == CONST_VECTOR);
01249 gcc_assert (op0_n_elts + op1_n_elts == n_elts);
01250
01251 for (i = 0; i < op0_n_elts; ++i)
01252 RTVEC_ELT (v, i) = XVECEXP (trueop0, 0, i);
01253 for (i = 0; i < op1_n_elts; ++i)
01254 RTVEC_ELT (v, op0_n_elts+i) = XVECEXP (trueop1, 0, i);
01255 }
01256
01257 return gen_rtx_CONST_VECTOR (mode, v);
01258 }
01259
01260 if (GET_MODE_CLASS (mode) == MODE_FLOAT
01261 && GET_CODE (trueop0) == CONST_DOUBLE
01262 && GET_CODE (trueop1) == CONST_DOUBLE
01263 && mode == GET_MODE (op0) && mode == GET_MODE (op1))
01264 {
01265 if (code == AND
01266 || code == IOR
01267 || code == XOR)
01268 {
01269 long tmp0[4];
01270 long tmp1[4];
01271 REAL_VALUE_TYPE r;
01272 int i;
01273
01274 real_to_target (tmp0, CONST_DOUBLE_REAL_VALUE (op0),
01275 GET_MODE (op0));
01276 real_to_target (tmp1, CONST_DOUBLE_REAL_VALUE (op1),
01277 GET_MODE (op1));
01278 for (i = 0; i < 4; i++)
01279 {
01280 switch (code)
01281 {
01282 case AND:
01283 tmp0[i] &= tmp1[i];
01284 break;
01285 case IOR:
01286 tmp0[i] |= tmp1[i];
01287 break;
01288 case XOR:
01289 tmp0[i] ^= tmp1[i];
01290 break;
01291 default:
01292 gcc_unreachable ();
01293 }
01294 }
01295 real_from_target (&r, tmp0, mode);
01296 return CONST_DOUBLE_FROM_REAL_VALUE (r, mode);
01297 }
01298 else
01299 {
01300 REAL_VALUE_TYPE f0, f1, value, result;
01301 bool inexact;
01302
01303 REAL_VALUE_FROM_CONST_DOUBLE (f0, trueop0);
01304 REAL_VALUE_FROM_CONST_DOUBLE (f1, trueop1);
01305 real_convert (&f0, mode, &f0);
01306 real_convert (&f1, mode, &f1);
01307
01308 if (HONOR_SNANS (mode)
01309 && (REAL_VALUE_ISNAN (f0) || REAL_VALUE_ISNAN (f1)))
01310 return 0;
01311
01312 if (code == DIV
01313 && REAL_VALUES_EQUAL (f1, dconst0)
01314 && (flag_trapping_math || ! MODE_HAS_INFINITIES (mode)))
01315 return 0;
01316
01317 if (MODE_HAS_INFINITIES (mode) && HONOR_NANS (mode)
01318 && flag_trapping_math
01319 && REAL_VALUE_ISINF (f0) && REAL_VALUE_ISINF (f1))
01320 {
01321 int s0 = REAL_VALUE_NEGATIVE (f0);
01322 int s1 = REAL_VALUE_NEGATIVE (f1);
01323
01324 switch (code)
01325 {
01326 case PLUS:
01327
01328 if (s0 != s1)
01329 return 0;
01330 break;
01331 case MINUS:
01332
01333 if (s0 == s1)
01334 return 0;
01335 break;
01336 case DIV:
01337
01338 return 0;
01339 default:
01340 break;
01341 }
01342 }
01343
01344 if (code == MULT && MODE_HAS_INFINITIES (mode) && HONOR_NANS (mode)
01345 && flag_trapping_math
01346 && ((REAL_VALUE_ISINF (f0) && REAL_VALUES_EQUAL (f1, dconst0))
01347 || (REAL_VALUE_ISINF (f1)
01348 && REAL_VALUES_EQUAL (f0, dconst0))))
01349
01350 return 0;
01351
01352 inexact = real_arithmetic (&value, rtx_to_tree_code (code),
01353 &f0, &f1);
01354 real_convert (&result, mode, &value);
01355
01356
01357
01358
01359
01360
01361 if ((flag_rounding_math
01362 || (REAL_MODE_FORMAT_COMPOSITE_P (mode)
01363 && !flag_unsafe_math_optimizations))
01364 && (inexact || !real_identical (&result, &value)))
01365 return NULL_RTX;
01366
01367 return CONST_DOUBLE_FROM_REAL_VALUE (result, mode);
01368 }
01369 }
01370
01371
01372 if (GET_MODE_CLASS (mode) == MODE_INT
01373 && width == HOST_BITS_PER_WIDE_INT * 2
01374 && (GET_CODE (trueop0) == CONST_DOUBLE
01375 || GET_CODE (trueop0) == CONST_INT)
01376 && (GET_CODE (trueop1) == CONST_DOUBLE
01377 || GET_CODE (trueop1) == CONST_INT))
01378 {
01379 unsigned HOST_WIDE_INT l1, l2, lv, lt;
01380 HOST_WIDE_INT h1, h2, hv, ht;
01381
01382 if (GET_CODE (trueop0) == CONST_DOUBLE)
01383 l1 = CONST_DOUBLE_LOW (trueop0), h1 = CONST_DOUBLE_HIGH (trueop0);
01384 else
01385 l1 = INTVAL (trueop0), h1 = HWI_SIGN_EXTEND (l1);
01386
01387 if (GET_CODE (trueop1) == CONST_DOUBLE)
01388 l2 = CONST_DOUBLE_LOW (trueop1), h2 = CONST_DOUBLE_HIGH (trueop1);
01389 else
01390 l2 = INTVAL (trueop1), h2 = HWI_SIGN_EXTEND (l2);
01391
01392 switch (code)
01393 {
01394 case MINUS:
01395
01396 neg_double (l2, h2, &lv, &hv);
01397 l2 = lv, h2 = hv;
01398
01399
01400
01401 case PLUS:
01402 add_double (l1, h1, l2, h2, &lv, &hv);
01403 break;
01404
01405 case MULT:
01406 mul_double (l1, h1, l2, h2, &lv, &hv);
01407 break;
01408
01409 case DIV:
01410 if (div_and_round_double (TRUNC_DIV_EXPR, 0, l1, h1, l2, h2,
01411 &lv, &hv, <, &ht))
01412 return 0;
01413 break;
01414
01415 case MOD:
01416 if (div_and_round_double (TRUNC_DIV_EXPR, 0, l1, h1, l2, h2,
01417 <, &ht, &lv, &hv))
01418 return 0;
01419 break;
01420
01421 case UDIV:
01422 if (div_and_round_double (TRUNC_DIV_EXPR, 1, l1, h1, l2, h2,
01423 &lv, &hv, <, &ht))
01424 return 0;
01425 break;
01426
01427 case UMOD:
01428 if (div_and_round_double (TRUNC_DIV_EXPR, 1, l1, h1, l2, h2,
01429 <, &ht, &lv, &hv))
01430 return 0;
01431 break;
01432
01433 case AND:
01434 lv = l1 & l2, hv = h1 & h2;
01435 break;
01436
01437 case IOR:
01438 lv = l1 | l2, hv = h1 | h2;
01439 break;
01440
01441 case XOR:
01442 lv = l1 ^ l2, hv = h1 ^ h2;
01443 break;
01444
01445 case SMIN:
01446 if (h1 < h2
01447 || (h1 == h2
01448 && ((unsigned HOST_WIDE_INT) l1
01449 < (unsigned HOST_WIDE_INT) l2)))
01450 lv = l1, hv = h1;
01451 else
01452 lv = l2, hv = h2;
01453 break;
01454
01455 case SMAX:
01456 if (h1 > h2
01457 || (h1 == h2
01458 && ((unsigned HOST_WIDE_INT) l1
01459 > (unsigned HOST_WIDE_INT) l2)))
01460 lv = l1, hv = h1;
01461 else
01462 lv = l2, hv = h2;
01463 break;
01464
01465 case UMIN:
01466 if ((unsigned HOST_WIDE_INT) h1 < (unsigned HOST_WIDE_INT) h2
01467 || (h1 == h2
01468 && ((unsigned HOST_WIDE_INT) l1
01469 < (unsigned HOST_WIDE_INT) l2)))
01470 lv = l1, hv = h1;
01471 else
01472 lv = l2, hv = h2;
01473 break;
01474
01475 case UMAX:
01476 if ((unsigned HOST_WIDE_INT) h1 > (unsigned HOST_WIDE_INT) h2
01477 || (h1 == h2
01478 && ((unsigned HOST_WIDE_INT) l1
01479 > (unsigned HOST_WIDE_INT) l2)))
01480 lv = l1, hv = h1;
01481 else
01482 lv = l2, hv = h2;
01483 break;
01484
01485 case LSHIFTRT: case ASHIFTRT:
01486 case ASHIFT:
01487 case ROTATE: case ROTATERT:
01488 if (SHIFT_COUNT_TRUNCATED)
01489 l2 &= (GET_MODE_BITSIZE (mode) - 1), h2 = 0;
01490
01491 if (h2 != 0 || l2 >= GET_MODE_BITSIZE (mode))
01492 return 0;
01493
01494 if (code == LSHIFTRT || code == ASHIFTRT)
01495 rshift_double (l1, h1, l2, GET_MODE_BITSIZE (mode), &lv, &hv,
01496 code == ASHIFTRT);
01497 else if (code == ASHIFT)
01498 lshift_double (l1, h1, l2, GET_MODE_BITSIZE (mode), &lv, &hv, 1);
01499 else if (code == ROTATE)
01500 lrotate_double (l1, h1, l2, GET_MODE_BITSIZE (mode), &lv, &hv);
01501 else
01502 rrotate_double (l1, h1, l2, GET_MODE_BITSIZE (mode), &lv, &hv);
01503 break;
01504
01505 default:
01506 return 0;
01507 }
01508
01509 return immed_double_const (lv, hv, mode);
01510 }
01511
01512 if (GET_CODE (op0) != CONST_INT || GET_CODE (op1) != CONST_INT
01513 || width > HOST_BITS_PER_WIDE_INT || width == 0)
01514 {
01515
01516
01517
01518 switch (code)
01519 {
01520 case PLUS:
01521
01522
01523
01524
01525 if (!HONOR_SIGNED_ZEROS (mode) && trueop1 == CONST0_RTX (mode))
01526 return op0;
01527
01528
01529
01530 if (GET_CODE (op0) == NEG)
01531 return simplify_gen_binary (MINUS, mode, op1, XEXP (op0, 0));
01532 else if (GET_CODE (op1) == NEG)
01533 return simplify_gen_binary (MINUS, mode, op0, XEXP (op1, 0));
01534
01535
01536 if (INTEGRAL_MODE_P (mode)
01537 && GET_CODE (op0) == NOT
01538 && trueop1 == const1_rtx)
01539 return simplify_gen_unary (NEG, mode, XEXP (op0, 0), mode);
01540
01541
01542
01543
01544
01545
01546
01547 if (CONSTANT_P (op0) && GET_MODE (op0) != VOIDmode
01548 && GET_CODE (op1) == CONST_INT)
01549 return plus_constant (op0, INTVAL (op1));
01550 else if (CONSTANT_P (op1) && GET_MODE (op1) != VOIDmode
01551 && GET_CODE (op0) == CONST_INT)
01552 return plus_constant (op1, INTVAL (op0));
01553
01554
01555
01556
01557
01558
01559
01560 if (SCALAR_INT_MODE_P (mode))
01561 {
01562 HOST_WIDE_INT coeff0h = 0, coeff1h = 0;
01563 unsigned HOST_WIDE_INT coeff0l = 1, coeff1l = 1;
01564 rtx lhs = op0, rhs = op1;
01565
01566 if (GET_CODE (lhs) == NEG)
01567 {
01568 coeff0l = -1;
01569 coeff0h = -1;
01570 lhs = XEXP (lhs, 0);
01571 }
01572 else if (GET_CODE (lhs) == MULT
01573 && GET_CODE (XEXP (lhs, 1)) == CONST_INT)
01574 {
01575 coeff0l = INTVAL (XEXP (lhs, 1));
01576 coeff0h = INTVAL (XEXP (lhs, 1)) < 0 ? -1 : 0;
01577 lhs = XEXP (lhs, 0);
01578 }
01579 else if (GET_CODE (lhs) == ASHIFT
01580 && GET_CODE (XEXP (lhs, 1)) == CONST_INT
01581 && INTVAL (XEXP (lhs, 1)) >= 0
01582 && INTVAL (XEXP (lhs, 1)) < HOST_BITS_PER_WIDE_INT)
01583 {
01584 coeff0l = ((HOST_WIDE_INT) 1) << INTVAL (XEXP (lhs, 1));
01585 coeff0h = 0;
01586 lhs = XEXP (lhs, 0);
01587 }
01588
01589 if (GET_CODE (rhs) == NEG)
01590 {
01591 coeff1l = -1;
01592 coeff1h = -1;
01593 rhs = XEXP (rhs, 0);
01594 }
01595 else if (GET_CODE (rhs) == MULT
01596 && GET_CODE (XEXP (rhs, 1)) == CONST_INT)
01597 {
01598 coeff1l = INTVAL (XEXP (rhs, 1));
01599 coeff1h = INTVAL (XEXP (rhs, 1)) < 0 ? -1 : 0;
01600 rhs = XEXP (rhs, 0);
01601 }
01602 else if (GET_CODE (rhs) == ASHIFT
01603 && GET_CODE (XEXP (rhs, 1)) == CONST_INT
01604 && INTVAL (XEXP (rhs, 1)) >= 0
01605 && INTVAL (XEXP (rhs, 1)) < HOST_BITS_PER_WIDE_INT)
01606 {
01607 coeff1l = ((HOST_WIDE_INT) 1) << INTVAL (XEXP (rhs, 1));
01608 coeff1h = 0;
01609 rhs = XEXP (rhs, 0);
01610 }
01611
01612 if (rtx_equal_p (lhs, rhs))
01613 {
01614 rtx orig = gen_rtx_PLUS (mode, op0, op1);
01615 rtx coeff;
01616 unsigned HOST_WIDE_INT l;
01617 HOST_WIDE_INT h;
01618
01619 add_double (coeff0l, coeff0h, coeff1l, coeff1h, &l, &h);
01620 coeff = immed_double_const (l, h, mode);
01621
01622 tem = simplify_gen_binary (MULT, mode, lhs, coeff);
01623 return rtx_cost (tem, SET) <= rtx_cost (orig, SET)
01624 ? tem : 0;
01625 }
01626 }
01627
01628
01629 if ((GET_CODE (op1) == CONST_INT
01630 || GET_CODE (op1) == CONST_DOUBLE)
01631 && GET_CODE (op0) == XOR
01632 && (GET_CODE (XEXP (op0, 1)) == CONST_INT
01633 || GET_CODE (XEXP (op0, 1)) == CONST_DOUBLE)
01634 && mode_signbit_p (mode, op1))
01635 return simplify_gen_binary (XOR, mode, XEXP (op0, 0),
01636 simplify_gen_binary (XOR, mode, op1,
01637 XEXP (op0, 1)));
01638
01639
01640
01641
01642
01643
01644
01645 if (INTEGRAL_MODE_P (mode)
01646 && (plus_minus_operand_p (op0)
01647 || plus_minus_operand_p (op1))
01648 && (tem = simplify_plus_minus (code, mode, op0, op1, 0)) != 0)
01649 return tem;
01650
01651
01652
01653 if (FLOAT_MODE_P (mode)
01654 && flag_unsafe_math_optimizations)
01655 {
01656 tem = simplify_associative_operation (code, mode, op0, op1);
01657 if (tem)
01658 return tem;
01659 }
01660 break;
01661
01662 case COMPARE:
01663 #ifdef HAVE_cc0
01664
01665
01666
01667
01668
01669
01670 if ((TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
01671 || ! FLOAT_MODE_P (mode) || flag_unsafe_math_optimizations)
01672 && trueop1 == CONST0_RTX (mode))
01673 return op0;
01674 #endif
01675
01676
01677 if (((GET_CODE (op0) == GT && GET_CODE (op1) == LT)
01678 || (GET_CODE (op0) == GTU && GET_CODE (op1) == LTU))
01679 && XEXP (op0, 1) == const0_rtx && XEXP (op1, 1) == const0_rtx)
01680 {
01681 rtx xop00 = XEXP (op0, 0);
01682 rtx xop10 = XEXP (op1, 0);
01683
01684 #ifdef HAVE_cc0
01685 if (GET_CODE (xop00) == CC0 && GET_CODE (xop10) == CC0)
01686 #else
01687 if (REG_P (xop00) && REG_P (xop10)
01688 && GET_MODE (xop00) == GET_MODE (xop10)
01689 && REGNO (xop00) == REGNO (xop10)
01690 && GET_MODE_CLASS (GET_MODE (xop00)) == MODE_CC
01691 && GET_MODE_CLASS (GET_MODE (xop10)) == MODE_CC)
01692 #endif
01693 return xop00;
01694 }
01695 break;
01696
01697 case MINUS:
01698
01699
01700
01701 if (rtx_equal_p (trueop0, trueop1)
01702 && ! side_effects_p (op0)
01703 && (! FLOAT_MODE_P (mode) || flag_unsafe_math_optimizations))
01704 return CONST0_RTX (mode);
01705
01706
01707
01708
01709
01710 if (!HONOR_SIGNED_ZEROS (mode) && trueop0 == CONST0_RTX (mode))
01711 return simplify_gen_unary (NEG, mode, op1, mode);
01712
01713
01714 if (trueop0 == constm1_rtx)
01715 return simplify_gen_unary (NOT, mode, op1, mode);
01716
01717
01718
01719
01720 if (!(HONOR_SIGNED_ZEROS (mode)
01721 && HONOR_SIGN_DEPENDENT_ROUNDING (mode))
01722 && trueop1 == CONST0_RTX (mode))
01723 return op0;
01724
01725
01726
01727
01728
01729
01730
01731 if (SCALAR_INT_MODE_P (mode))
01732 {
01733 HOST_WIDE_INT coeff0h = 0, negcoeff1h = -1;
01734 unsigned HOST_WIDE_INT coeff0l = 1, negcoeff1l = -1;
01735 rtx lhs = op0, rhs = op1;
01736
01737 if (GET_CODE (lhs) == NEG)
01738 {
01739 coeff0l = -1;
01740 coeff0h = -1;
01741 lhs = XEXP (lhs, 0);
01742 }
01743 else if (GET_CODE (lhs) == MULT
01744 && GET_CODE (XEXP (lhs, 1)) == CONST_INT)
01745 {
01746 coeff0l = INTVAL (XEXP (lhs, 1));
01747 coeff0h = INTVAL (XEXP (lhs, 1)) < 0 ? -1 : 0;
01748 lhs = XEXP (lhs, 0);
01749 }
01750 else if (GET_CODE (lhs) == ASHIFT
01751 && GET_CODE (XEXP (lhs, 1)) == CONST_INT
01752 && INTVAL (XEXP (lhs, 1)) >= 0
01753 && INTVAL (XEXP (lhs, 1)) < HOST_BITS_PER_WIDE_INT)
01754 {
01755 coeff0l = ((HOST_WIDE_INT) 1) << INTVAL (XEXP (lhs, 1));
01756 coeff0h = 0;
01757 lhs = XEXP (lhs, 0);
01758 }
01759
01760 if (GET_CODE (rhs) == NEG)
01761 {
01762 negcoeff1l = 1;
01763 negcoeff1h = 0;
01764 rhs = XEXP (rhs, 0);
01765 }
01766 else if (GET_CODE (rhs) == MULT
01767 && GET_CODE (XEXP (rhs, 1)) == CONST_INT)
01768 {
01769 negcoeff1l = -INTVAL (XEXP (rhs, 1));
01770 negcoeff1h = INTVAL (XEXP (rhs, 1)) <= 0 ? 0 : -1;
01771 rhs = XEXP (rhs, 0);
01772 }
01773 else if (GET_CODE (rhs) == ASHIFT
01774 && GET_CODE (XEXP (rhs, 1)) == CONST_INT
01775 && INTVAL (XEXP (rhs, 1)) >= 0
01776 && INTVAL (XEXP (rhs, 1)) < HOST_BITS_PER_WIDE_INT)
01777 {
01778 negcoeff1l = -(((HOST_WIDE_INT) 1)
01779 << INTVAL (XEXP (rhs, 1)));
01780 negcoeff1h = -1;
01781 rhs = XEXP (rhs, 0);
01782 }
01783
01784 if (rtx_equal_p (lhs, rhs))
01785 {
01786 rtx orig = gen_rtx_MINUS (mode, op0, op1);
01787 rtx coeff;
01788 unsigned HOST_WIDE_INT l;
01789 HOST_WIDE_INT h;
01790
01791 add_double (coeff0l, coeff0h, negcoeff1l, negcoeff1h,
01792 &l, &h);
01793 coeff = immed_double_const (l, h, mode);
01794
01795 tem = simplify_gen_binary (MULT, mode, lhs, coeff);
01796 return rtx_cost (tem, SET) <= rtx_cost (orig, SET)
01797 ? tem : 0;
01798 }
01799 }
01800
01801
01802 if (GET_CODE (op1) == NEG)
01803 return simplify_gen_binary (PLUS, mode, op0, XEXP (op1, 0));
01804
01805
01806 if (GET_CODE (op0) == NEG
01807 && (GET_CODE (op1) == CONST_INT
01808 || GET_CODE (op1) == CONST_DOUBLE))
01809 {
01810 tem = simplify_unary_operation (NEG, mode, op1, mode);
01811 if (tem)
01812 return simplify_gen_binary (MINUS, mode, tem, XEXP (op0, 0));
01813 }
01814
01815
01816
01817
01818
01819
01820
01821 if (INTEGRAL_MODE_P (mode)
01822 && (plus_minus_operand_p (op0)
01823 || plus_minus_operand_p (op1))
01824 && (tem = simplify_plus_minus (code, mode, op0, op1, 0)) != 0)
01825 return tem;
01826
01827
01828 if (GET_CODE (op1) == CONST_INT && GET_MODE (op0) != VOIDmode)
01829 return simplify_gen_binary (PLUS, mode,
01830 op0,
01831 neg_const_int (mode, op1));
01832
01833
01834 if (GET_CODE (op1) == AND)
01835 {
01836 if (rtx_equal_p (op0, XEXP (op1, 0)))
01837 {
01838 tem = simplify_gen_unary (NOT, mode, XEXP (op1, 1),
01839 GET_MODE (XEXP (op1, 1)));
01840 return simplify_gen_binary (AND, mode, op0, tem);
01841 }
01842 if (rtx_equal_p (op0, XEXP (op1, 1)))
01843 {
01844 tem = simplify_gen_unary (NOT, mode, XEXP (op1, 0),
01845 GET_MODE (XEXP (op1, 0)));
01846 return simplify_gen_binary (AND, mode, op0, tem);
01847 }
01848 }
01849 break;
01850
01851 case MULT:
01852 if (trueop1 == constm1_rtx)
01853 return simplify_gen_unary (NEG, mode, op0, mode);
01854
01855
01856
01857
01858
01859 if (!HONOR_NANS (mode)
01860 && !HONOR_SIGNED_ZEROS (mode)
01861 && trueop1 == CONST0_RTX (mode)
01862 && ! side_effects_p (op0))
01863 return op1;
01864
01865
01866
01867 if (!HONOR_SNANS (mode)
01868 && trueop1 == CONST1_RTX (mode))
01869 return op0;
01870
01871
01872
01873 if (GET_CODE (trueop1) == CONST_INT
01874 && (val = exact_log2 (INTVAL (trueop1))) >= 0
01875
01876
01877
01878 && (width <= HOST_BITS_PER_WIDE_INT
01879 || val != HOST_BITS_PER_WIDE_INT - 1))
01880 return simplify_gen_binary (ASHIFT, mode, op0, GEN_INT (val));
01881
01882
01883 else if (GET_CODE (trueop1) == CONST_DOUBLE
01884 && (GET_MODE (trueop1) == VOIDmode
01885 || GET_MODE_CLASS (GET_MODE (trueop1)) == MODE_INT)
01886 && GET_MODE (op0) == mode
01887 && CONST_DOUBLE_LOW (trueop1) == 0
01888 && (val = exact_log2 (CONST_DOUBLE_HIGH (trueop1))) >= 0)
01889 return simplify_gen_binary (ASHIFT, mode, op0,
01890 GEN_INT (val
01891 + HOST_BITS_PER_WIDE_INT));
01892
01893
01894 if (GET_CODE (trueop1) == CONST_DOUBLE
01895 && GET_MODE_CLASS (GET_MODE (trueop1)) == MODE_FLOAT
01896 && GET_MODE (op0) == mode)
01897 {
01898 REAL_VALUE_TYPE d;
01899 REAL_VALUE_FROM_CONST_DOUBLE (d, trueop1);
01900
01901 if (REAL_VALUES_EQUAL (d, dconst2))
01902 return simplify_gen_binary (PLUS, mode, op0, copy_rtx (op0));
01903
01904 if (REAL_VALUES_EQUAL (d, dconstm1))
01905 return simplify_gen_unary (NEG, mode, op0, mode);
01906 }
01907
01908
01909
01910 if (! FLOAT_MODE_P (mode)
01911 || flag_unsafe_math_optimizations)
01912 {
01913 tem = simplify_associative_operation (code, mode, op0, op1);
01914 if (tem)
01915 return tem;
01916 }
01917 break;
01918
01919 case IOR:
01920 if (trueop1 == const0_rtx)
01921 return op0;
01922 if (GET_CODE (trueop1) == CONST_INT
01923 && ((INTVAL (trueop1) & GET_MODE_MASK (mode))
01924 == GET_MODE_MASK (mode)))
01925 return op1;
01926 if (rtx_equal_p (trueop0, trueop1) && ! side_effects_p (op0))
01927 return op0;
01928
01929 if (((GET_CODE (op0) == NOT && rtx_equal_p (XEXP (op0, 0), op1))
01930 || (GET_CODE (op1) == NOT && rtx_equal_p (XEXP (op1, 0), op0)))
01931 && ! side_effects_p (op0)
01932 && SCALAR_INT_MODE_P (mode))
01933 return constm1_rtx;
01934 tem = simplify_associative_operation (code, mode, op0, op1);
01935 if (tem)
01936 return tem;
01937 break;
01938
01939 case XOR:
01940 if (trueop1 == const0_rtx)
01941 return op0;
01942 if (GET_CODE (trueop1) == CONST_INT
01943 && ((INTVAL (trueop1) & GET_MODE_MASK (mode))
01944 == GET_MODE_MASK (mode)))
01945 return simplify_gen_unary (NOT, mode, op0, mode);
01946 if (trueop0 == trueop1
01947 && ! side_effects_p (op0)
01948 && GET_MODE_CLASS (mode) != MODE_CC)
01949 return CONST0_RTX (mode);
01950
01951
01952 if ((GET_CODE (op1) == CONST_INT
01953 || GET_CODE (op1) == CONST_DOUBLE)
01954 && mode_signbit_p (mode, op1))
01955 return simplify_gen_binary (PLUS, mode, op0, op1);
01956
01957 if ((GET_CODE (op1) == CONST_INT
01958 || GET_CODE (op1) == CONST_DOUBLE)
01959 && GET_CODE (op0) == PLUS
01960 && (GET_CODE (XEXP (op0, 1)) == CONST_INT
01961 || GET_CODE (XEXP (op0, 1)) == CONST_DOUBLE)
01962 && mode_signbit_p (mode, XEXP (op0, 1)))
01963 return simplify_gen_binary (XOR, mode, XEXP (op0, 0),
01964 simplify_gen_binary (XOR, mode, op1,
01965 XEXP (op0, 1)));
01966
01967 tem = simplify_associative_operation (code, mode, op0, op1);
01968 if (tem)
01969 return tem;
01970 break;
01971
01972 case AND:
01973 if (trueop1 == CONST0_RTX (mode) && ! side_effects_p (op0))
01974 return trueop1;
01975
01976
01977 if (GET_CODE (trueop1) == CONST_INT
01978 && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT
01979 && (nonzero_bits (trueop0, mode) & ~INTVAL (trueop1)) == 0)
01980 return op0;
01981 if (trueop0 == trueop1 && ! side_effects_p (op0)
01982 && GET_MODE_CLASS (mode) != MODE_CC)
01983 return op0;
01984
01985 if (((GET_CODE (op0) == NOT && rtx_equal_p (XEXP (op0, 0), op1))
01986 || (GET_CODE (op1) == NOT && rtx_equal_p (XEXP (op1, 0), op0)))
01987 && ! side_effects_p (op0)
01988 && GET_MODE_CLASS (mode) != MODE_CC)
01989 return CONST0_RTX (mode);
01990
01991
01992
01993 if ((GET_CODE (op0) == SIGN_EXTEND
01994 || GET_CODE (op0) == ZERO_EXTEND)
01995 && GET_CODE (trueop1) == CONST_INT
01996 && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT
01997 && (~GET_MODE_MASK (GET_MODE (XEXP (op0, 0)))
01998 & INTVAL (trueop1)) == 0)
01999 {
02000 enum machine_mode imode = GET_MODE (XEXP (op0, 0));
02001 tem = simplify_gen_binary (AND, imode, XEXP (op0, 0),
02002 gen_int_mode (INTVAL (trueop1),
02003 imode));
02004 return simplify_gen_unary (ZERO_EXTEND, mode, tem, imode);
02005 }
02006
02007
02008
02009
02010
02011
02012 if (GET_CODE (trueop1) == CONST_INT
02013 && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT
02014 && ~INTVAL (trueop1)
02015 && (INTVAL (trueop1) & (INTVAL (trueop1) + 1)) == 0
02016 && (GET_CODE (op0) == PLUS || GET_CODE (op0) == MINUS))
02017 {
02018 rtx pmop[2];
02019 int which;
02020
02021 pmop[0] = XEXP (op0, 0);
02022 pmop[1] = XEXP (op0, 1);
02023
02024 for (which = 0; which < 2; which++)
02025 {
02026 tem = pmop[which];
02027 switch (GET_CODE (tem))
02028 {
02029 case AND:
02030 if (GET_CODE (XEXP (tem, 1)) == CONST_INT
02031 && (INTVAL (XEXP (tem, 1)) & INTVAL (trueop1))
02032 == INTVAL (trueop1))
02033 pmop[which] = XEXP (tem, 0);
02034 break;
02035 case IOR:
02036 case XOR:
02037 if (GET_CODE (XEXP (tem, 1)) == CONST_INT
02038 && (INTVAL (XEXP (tem, 1)) & INTVAL (trueop1)) == 0)
02039 pmop[which] = XEXP (tem, 0);
02040 break;
02041 default:
02042 break;
02043 }
02044 }
02045
02046 if (pmop[0] != XEXP (op0, 0) || pmop[1] != XEXP (op0, 1))
02047 {
02048 tem = simplify_gen_binary (GET_CODE (op0), mode,
02049 pmop[0], pmop[1]);
02050 return simplify_gen_binary (code, mode, tem, op1);
02051 }
02052 }
02053 tem = simplify_associative_operation (code, mode, op0, op1);
02054 if (tem)
02055 return tem;
02056 break;
02057
02058 case UDIV:
02059
02060 if (trueop0 == CONST0_RTX (mode))
02061 {
02062 if (side_effects_p (op1))
02063 return simplify_gen_binary (AND, mode, op1, trueop0);
02064 return trueop0;
02065 }
02066
02067 if (trueop1 == CONST1_RTX (mode))
02068 {
02069
02070 rtx x = gen_lowpart_common (mode, op0);
02071 if (x)
02072 return x;
02073 if (mode != GET_MODE (op0) && GET_MODE (op0) != VOIDmode)
02074 return gen_lowpart_SUBREG (mode, op0);
02075 return op0;
02076 }
02077
02078 if (GET_CODE (trueop1) == CONST_INT
02079 && (arg1 = exact_log2 (INTVAL (trueop1))) > 0)
02080 return simplify_gen_binary (LSHIFTRT, mode, op0, GEN_INT (arg1));
02081 break;
02082
02083 case DIV:
02084
02085 if (GET_MODE_CLASS (mode) == MODE_FLOAT)
02086 {
02087
02088
02089
02090
02091 if (trueop0 == CONST0_RTX (mode)
02092 && !HONOR_NANS (mode)
02093 && !HONOR_SIGNED_ZEROS (mode)
02094 && ! side_effects_p (op1))
02095 return op0;
02096
02097 if (trueop1 == CONST1_RTX (mode)
02098 && !HONOR_SNANS (mode))
02099 return op0;
02100
02101 if (GET_CODE (trueop1) == CONST_DOUBLE
02102 && trueop1 != CONST0_RTX (mode))
02103 {
02104 REAL_VALUE_TYPE d;
02105 REAL_VALUE_FROM_CONST_DOUBLE (d, trueop1);
02106
02107
02108 if (REAL_VALUES_EQUAL (d, dconstm1)
02109 && !HONOR_SNANS (mode))
02110 return simplify_gen_unary (NEG, mode, op0, mode);
02111
02112
02113
02114 if (flag_unsafe_math_optimizations
02115 && !REAL_VALUES_EQUAL (d, dconst0))
02116 {
02117 REAL_ARITHMETIC (d, RDIV_EXPR, dconst1, d);
02118 tem = CONST_DOUBLE_FROM_REAL_VALUE (d, mode);
02119 return simplify_gen_binary (MULT, mode, op0, tem);
02120 }
02121 }
02122 }
02123 else
02124 {
02125
02126 if (trueop0 == CONST0_RTX (mode))
02127 {
02128 if (side_effects_p (op1))
02129 return simplify_gen_binary (AND, mode, op1, trueop0);
02130 return trueop0;
02131 }
02132
02133 if (trueop1 == CONST1_RTX (mode))
02134 {
02135
02136 rtx x = gen_lowpart_common (mode, op0);
02137 if (x)
02138 return x;
02139 if (mode != GET_MODE (op0) && GET_MODE (op0) != VOIDmode)
02140 return gen_lowpart_SUBREG (mode, op0);
02141 return op0;
02142 }
02143
02144 if (trueop1 == constm1_rtx)
02145 {
02146 rtx x = gen_lowpart_common (mode, op0);
02147 if (!x)
02148 x = (mode != GET_MODE (op0) && GET_MODE (op0) != VOIDmode)
02149 ? gen_lowpart_SUBREG (mode, op0) : op0;
02150 return simplify_gen_unary (NEG, mode, x, mode);
02151 }
02152 }
02153 break;
02154
02155 case UMOD:
02156
02157 if (trueop0 == CONST0_RTX (mode))
02158 {
02159 if (side_effects_p (op1))
02160 return simplify_gen_binary (AND, mode, op1, trueop0);
02161 return trueop0;
02162 }
02163
02164 if (trueop1 == CONST1_RTX (mode))
02165 {
02166 if (side_effects_p (op0))
02167 return simplify_gen_binary (AND, mode, op0, CONST0_RTX (mode));
02168 return CONST0_RTX (mode);
02169 }
02170
02171 if (GET_CODE (trueop1) == CONST_INT
02172 && exact_log2 (INTVAL (trueop1)) > 0)
02173 return simplify_gen_binary (AND, mode, op0,
02174 GEN_INT (INTVAL (op1) - 1));
02175 break;
02176
02177 case MOD:
02178
02179 if (trueop0 == CONST0_RTX (mode))
02180 {
02181 if (side_effects_p (op1))
02182 return simplify_gen_binary (AND, mode, op1, trueop0);
02183 return trueop0;
02184 }
02185
02186 if (trueop1 == CONST1_RTX (mode) || trueop1 == constm1_rtx)
02187 {
02188 if (side_effects_p (op0))
02189 return simplify_gen_binary (AND, mode, op0, CONST0_RTX (mode));
02190 return CONST0_RTX (mode);
02191 }
02192 break;
02193
02194 case ROTATERT:
02195 case ROTATE:
02196 case ASHIFTRT:
02197
02198 if (GET_CODE (trueop0) == CONST_INT && width <= HOST_BITS_PER_WIDE_INT
02199 && (unsigned HOST_WIDE_INT) INTVAL (trueop0) == GET_MODE_MASK (mode)
02200 && ! side_effects_p (op1))
02201 return op0;
02202
02203
02204
02205 case ASHIFT:
02206 case LSHIFTRT:
02207 if (trueop1 == CONST0_RTX (mode))
02208 return op0;
02209 if (trueop0 == CONST0_RTX (mode) && ! side_effects_p (op1))
02210 return op0;
02211 break;
02212
02213 case SMIN:
02214 if (width <= HOST_BITS_PER_WIDE_INT
02215 && GET_CODE (trueop1) == CONST_INT
02216 && INTVAL (trueop1) == (HOST_WIDE_INT) 1 << (width -1)
02217 && ! side_effects_p (op0))
02218 return op1;
02219 if (rtx_equal_p (trueop0, trueop1) && ! side_effects_p (op0))
02220 return op0;
02221 tem = simplify_associative_operation (code, mode, op0, op1);
02222 if (tem)
02223 return tem;
02224 break;
02225
02226 case SMAX:
02227 if (width <= HOST_BITS_PER_WIDE_INT
02228 && GET_CODE (trueop1) == CONST_INT
02229 && ((unsigned HOST_WIDE_INT) INTVAL (trueop1)
02230 == (unsigned HOST_WIDE_INT) GET_MODE_MASK (mode) >> 1)
02231 && ! side_effects_p (op0))
02232 return op1;
02233 if (rtx_equal_p (trueop0, trueop1) && ! side_effects_p (op0))
02234 return op0;
02235 tem = simplify_associative_operation (code, mode, op0, op1);
02236 if (tem)
02237 return tem;
02238 break;
02239
02240 case UMIN:
02241 if (trueop1 == CONST0_RTX (mode) && ! side_effects_p (op0))
02242 return op1;
02243 if (rtx_equal_p (trueop0, trueop1) && ! side_effects_p (op0))
02244 return op0;
02245 tem = simplify_associative_operation (code, mode, op0, op1);
02246 if (tem)
02247 return tem;
02248 break;
02249
02250 case UMAX:
02251 if (trueop1 == constm1_rtx && ! side_effects_p (op0))
02252 return op1;
02253 if (rtx_equal_p (trueop0, trueop1) && ! side_effects_p (op0))
02254 return op0;
02255 tem = simplify_associative_operation (code, mode, op0, op1);
02256 if (tem)
02257 return tem;
02258 break;
02259
02260 case SS_PLUS:
02261 case US_PLUS:
02262 case SS_MINUS:
02263 case US_MINUS:
02264
02265 return 0;
02266
02267 case VEC_SELECT:
02268 if (!VECTOR_MODE_P (mode))
02269 {
02270 gcc_assert (VECTOR_MODE_P (GET_MODE (trueop0)));
02271 gcc_assert (mode == GET_MODE_INNER (GET_MODE (trueop0)));
02272 gcc_assert (GET_CODE (trueop1) == PARALLEL);
02273 gcc_assert (XVECLEN (trueop1, 0) == 1);
02274 gcc_assert (GET_CODE (XVECEXP (trueop1, 0, 0)) == CONST_INT);
02275
02276 if (GET_CODE (trueop0) == CONST_VECTOR)
02277 return CONST_VECTOR_ELT (trueop0, INTVAL (XVECEXP
02278 (trueop1, 0, 0)));
02279 }
02280 else
02281 {
02282 gcc_assert (VECTOR_MODE_P (GET_MODE (trueop0)));
02283 gcc_assert (GET_MODE_INNER (mode)
02284 == GET_MODE_INNER (GET_MODE (trueop0)));
02285 gcc_assert (GET_CODE (trueop1) == PARALLEL);
02286
02287 if (GET_CODE (trueop0) == CONST_VECTOR)
02288 {
02289 int elt_size = GET_MODE_SIZE (GET_MODE_INNER (mode));
02290 unsigned n_elts = (GET_MODE_SIZE (mode) / elt_size);
02291 rtvec v = rtvec_alloc (n_elts);
02292 unsigned int i;
02293
02294 gcc_assert (XVECLEN (trueop1, 0) == (int) n_elts);
02295 for (i = 0; i < n_elts; i++)
02296 {
02297 rtx x = XVECEXP (trueop1, 0, i);
02298
02299 gcc_assert (GET_CODE (x) == CONST_INT);
02300 RTVEC_ELT (v, i) = CONST_VECTOR_ELT (trueop0,
02301 INTVAL (x));
02302 }
02303
02304 return gen_rtx_CONST_VECTOR (mode, v);
02305 }
02306 }
02307 return 0;
02308 case VEC_CONCAT:
02309 {
02310 enum machine_mode op0_mode = (GET_MODE (trueop0) != VOIDmode
02311 ? GET_MODE (trueop0)
02312 : GET_MODE_INNER (mode));
02313 enum machine_mode op1_mode = (GET_MODE (trueop1) != VOIDmode
02314 ? GET_MODE (trueop1)
02315 : GET_MODE_INNER (mode));
02316
02317 gcc_assert (VECTOR_MODE_P (mode));
02318 gcc_assert (GET_MODE_SIZE (op0_mode) + GET_MODE_SIZE (op1_mode)
02319 == GET_MODE_SIZE (mode));
02320
02321 if (VECTOR_MODE_P (op0_mode))
02322 gcc_assert (GET_MODE_INNER (mode)
02323 == GET_MODE_INNER (op0_mode));
02324 else
02325 gcc_assert (GET_MODE_INNER (mode) == op0_mode);
02326
02327 if (VECTOR_MODE_P (op1_mode))
02328 gcc_assert (GET_MODE_INNER (mode)
02329 == GET_MODE_INNER (op1_mode));
02330 else
02331 gcc_assert (GET_MODE_INNER (mode) == op1_mode);
02332
02333 if ((GET_CODE (trueop0) == CONST_VECTOR
02334 || GET_CODE (trueop0) == CONST_INT
02335 || GET_CODE (trueop0) == CONST_DOUBLE)
02336 && (GET_CODE (trueop1) == CONST_VECTOR
02337 || GET_CODE (trueop1) == CONST_INT
02338 || GET_CODE (trueop1) == CONST_DOUBLE))
02339 {
02340 int elt_size = GET_MODE_SIZE (GET_MODE_INNER (mode));
02341 unsigned n_elts = (GET_MODE_SIZE (mode) / elt_size);
02342 rtvec v = rtvec_alloc (n_elts);
02343 unsigned int i;
02344 unsigned in_n_elts = 1;
02345
02346 if (VECTOR_MODE_P (op0_mode))
02347 in_n_elts = (GET_MODE_SIZE (op0_mode) / elt_size);
02348 for (i = 0; i < n_elts; i++)
02349 {
02350 if (i < in_n_elts)
02351 {
02352 if (!VECTOR_MODE_P (op0_mode))
02353 RTVEC_ELT (v, i) = trueop0;
02354 else
02355 RTVEC_ELT (v, i) = CONST_VECTOR_ELT (trueop0, i);
02356 }
02357 else
02358 {
02359 if (!VECTOR_MODE_P (op1_mode))
02360 RTVEC_ELT (v, i) = trueop1;
02361 else
02362 RTVEC_ELT (v, i) = CONST_VECTOR_ELT (trueop1,
02363 i - in_n_elts);
02364 }
02365 }
02366
02367 return gen_rtx_CONST_VECTOR (mode, v);
02368 }
02369 }
02370 return 0;
02371
02372 default:
02373 gcc_unreachable ();
02374 }
02375
02376 return 0;
02377 }
02378
02379
02380
02381
02382 arg0 = INTVAL (trueop0);
02383 arg1 = INTVAL (trueop1);
02384
02385 if (width < HOST_BITS_PER_WIDE_INT)
02386 {
02387 arg0 &= ((HOST_WIDE_INT) 1 << width) - 1;
02388 arg1 &= ((HOST_WIDE_INT) 1 << width) - 1;
02389
02390 arg0s = arg0;
02391 if (arg0s & ((HOST_WIDE_INT) 1 << (width - 1)))
02392 arg0s |= ((HOST_WIDE_INT) (-1) << width);
02393
02394 arg1s = arg1;
02395 if (arg1s & ((HOST_WIDE_INT) 1 << (width - 1)))
02396 arg1s |= ((HOST_WIDE_INT) (-1) << width);
02397 }
02398 else
02399 {
02400 arg0s = arg0;
02401 arg1s = arg1;
02402 }
02403
02404
02405
02406 switch (code)
02407 {
02408 case PLUS:
02409 val = arg0s + arg1s;
02410 break;
02411
02412 case MINUS:
02413 val = arg0s - arg1s;
02414 break;
02415
02416 case MULT:
02417 val = arg0s * arg1s;
02418 break;
02419
02420 case DIV:
02421 if (arg1s == 0
02422 || (arg0s == (HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT - 1)
02423 && arg1s == -1))
02424 return 0;
02425 val = arg0s / arg1s;
02426 break;
02427
02428 case MOD:
02429 if (arg1s == 0
02430 || (arg0s == (HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT - 1)
02431 && arg1s == -1))
02432 return 0;
02433 val = arg0s % arg1s;
02434 break;
02435
02436 case UDIV:
02437 if (arg1 == 0
02438 || (arg0s == (HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT - 1)
02439 && arg1s == -1))
02440 return 0;
02441 val = (unsigned HOST_WIDE_INT) arg0 / arg1;
02442 break;
02443
02444 case UMOD:
02445 if (arg1 == 0
02446 || (arg0s == (HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT - 1)
02447 && arg1s == -1))
02448 return 0;
02449 val = (unsigned HOST_WIDE_INT) arg0 % arg1;
02450 break;
02451
02452 case AND:
02453 val = arg0 & arg1;
02454 break;
02455
02456 case IOR:
02457 val = arg0 | arg1;
02458 break;
02459
02460 case XOR:
02461 val = arg0 ^ arg1;
02462 break;
02463
02464 case LSHIFTRT:
02465 case ASHIFT:
02466 case ASHIFTRT:
02467
02468
02469
02470
02471
02472
02473 if (SHIFT_COUNT_TRUNCATED)
02474 arg1 = (unsigned HOST_WIDE_INT) arg1 % width;
02475 else if (arg1 < 0 || arg1 >= GET_MODE_BITSIZE (mode))
02476 return 0;
02477
02478 val = (code == ASHIFT
02479 ? ((unsigned HOST_WIDE_INT) arg0) << arg1
02480 : ((unsigned HOST_WIDE_INT) arg0) >> arg1);
02481
02482
02483 if (code == ASHIFTRT && arg0s < 0 && arg1 > 0)
02484 val |= ((HOST_WIDE_INT) -1) << (width - arg1);
02485 break;
02486
02487 case ROTATERT:
02488 if (arg1 < 0)
02489 return 0;
02490
02491 arg1 %= width;
02492 val = ((((unsigned HOST_WIDE_INT) arg0) << (width - arg1))
02493 | (((unsigned HOST_WIDE_INT) arg0) >> arg1));
02494 break;
02495
02496 case ROTATE:
02497 if (arg1 < 0)
02498 return 0;
02499
02500 arg1 %= width;
02501 val = ((((unsigned HOST_WIDE_INT) arg0) << arg1)
02502 | (((unsigned HOST_WIDE_INT) arg0) >> (width - arg1)));
02503 break;
02504
02505 case COMPARE:
02506
02507 return 0;
02508
02509 case SMIN:
02510 val = arg0s <= arg1s ? arg0s : arg1s;
02511 break;
02512
02513 case UMIN:
02514 val = ((unsigned HOST_WIDE_INT) arg0
02515 <= (unsigned HOST_WIDE_INT) arg1 ? arg0 : arg1);
02516 break;
02517
02518 case SMAX:
02519 val = arg0s > arg1s ? arg0s : arg1s;
02520 break;
02521
02522 case UMAX:
02523 val = ((unsigned HOST_WIDE_INT) arg0
02524 > (unsigned HOST_WIDE_INT) arg1 ? arg0 : arg1);
02525 break;
02526
02527 case SS_PLUS:
02528 case US_PLUS:
02529 case SS_MINUS:
02530 case US_MINUS:
02531
02532 return 0;
02533
02534 default:
02535 gcc_unreachable ();
02536 }
02537
02538 val = trunc_int_for_mode (val, mode);
02539
02540 return GEN_INT (val);
02541 }
02542
02543
02544
02545
02546
02547
02548
02549
02550
02551
02552
02553
02554
02555 struct simplify_plus_minus_op_data
02556 {
02557 rtx op;
02558 int neg;
02559 };
02560
02561 static int
02562 simplify_plus_minus_op_data_cmp (const void *p1, const void *p2)
02563 {
02564 const struct simplify_plus_minus_op_data *d1 = p1;
02565 const struct simplify_plus_minus_op_data *d2 = p2;
02566
02567 return (commutative_operand_precedence (d2->op)
02568 - commutative_operand_precedence (d1->op));
02569 }
02570
02571 static rtx
02572 simplify_plus_minus (enum rtx_code code, enum machine_mode mode, rtx op0,
02573 rtx op1, int force)
02574 {
02575 struct simplify_plus_minus_op_data ops[8];
02576 rtx result, tem;
02577 int n_ops = 2, input_ops = 2, input_consts = 0, n_consts;
02578 int first, changed;
02579 int i, j;
02580
02581 memset (ops, 0, sizeof ops);
02582
02583
02584
02585
02586
02587 ops[0].op = op0;
02588 ops[0].neg = 0;
02589 ops[1].op = op1;
02590 ops[1].neg = (code == MINUS);
02591
02592 do
02593 {
02594 changed = 0;
02595
02596 for (i = 0; i < n_ops; i++)
02597 {
02598 rtx this_op = ops[i].op;
02599 int this_neg = ops[i].neg;
02600 enum rtx_code this_code = GET_CODE (this_op);
02601
02602 switch (this_code)
02603 {
02604 case PLUS:
02605 case MINUS:
02606 if (n_ops == 7)
02607 return NULL_RTX;
02608
02609 ops[n_ops].op = XEXP (this_op, 1);
02610 ops[n_ops].neg = (this_code == MINUS) ^ this_neg;
02611 n_ops++;
02612
02613 ops[i].op = XEXP (this_op, 0);
02614 input_ops++;
02615 changed = 1;
02616 break;
02617
02618 case NEG:
02619 ops[i].op = XEXP (this_op, 0);
02620 ops[i].neg = ! this_neg;
02621 changed = 1;
02622 break;
02623
02624 case CONST:
02625 if (n_ops < 7
02626 && GET_CODE (XEXP (this_op, 0)) == PLUS
02627 && CONSTANT_P (XEXP (XEXP (this_op, 0), 0))
02628 && CONSTANT_P (XEXP (XEXP (this_op, 0), 1)))
02629 {
02630 ops[i].op = XEXP (XEXP (this_op, 0), 0);
02631 ops[n_ops].op = XEXP (XEXP (this_op, 0), 1);
02632 ops[n_ops].neg = this_neg;
02633 n_ops++;
02634 input_consts++;
02635 changed = 1;
02636 }
02637 break;
02638
02639 case NOT:
02640
02641 if (n_ops != 7)
02642 {
02643 ops[n_ops].op = constm1_rtx;
02644 ops[n_ops++].neg = this_neg;
02645 ops[i].op = XEXP (this_op, 0);
02646 ops[i].neg = !this_neg;
02647 changed = 1;
02648 }
02649 break;
02650
02651 case CONST_INT:
02652 if (this_neg)
02653 {
02654 ops[i].op = neg_const_int (mode, this_op);
02655 ops[i].neg = 0;
02656 changed = 1;
02657 }
02658 break;
02659
02660 default:
02661 break;
02662 }
02663 }
02664 }
02665 while (changed);
02666
02667
02668 if (n_ops <= 2 && !force)
02669 return NULL_RTX;
02670
02671
02672 for (i = 0; i < n_ops; i++)
02673 if (GET_CODE (ops[i].op) == CONST)
02674 input_consts++;
02675
02676
02677
02678
02679 first = 1;
02680 do
02681 {
02682 changed = first;
02683
02684 for (i = 0; i < n_ops - 1; i++)
02685 for (j = i + 1; j < n_ops; j++)
02686 {
02687 rtx lhs = ops[i].op, rhs = ops[j].op;
02688 int lneg = ops[i].neg, rneg = ops[j].neg;
02689
02690 if (lhs != 0 && rhs != 0
02691 && (! first || (CONSTANT_P (lhs) && CONSTANT_P (rhs))))
02692 {
02693 enum rtx_code ncode = PLUS;
02694
02695 if (lneg != rneg)
02696 {
02697 ncode = MINUS;
02698 if (lneg)
02699 tem = lhs, lhs = rhs, rhs = tem;
02700 }
02701 else if (swap_commutative_operands_p (lhs, rhs))
02702 tem = lhs, lhs = rhs, rhs = tem;
02703
02704 tem = simplify_binary_operation (ncode, mode, lhs, rhs);
02705
02706
02707
02708
02709
02710 if (tem
02711 && ! (GET_CODE (tem) == CONST
02712 && GET_CODE (XEXP (tem, 0)) == ncode
02713 && XEXP (XEXP (tem, 0), 0) == lhs
02714 && XEXP (XEXP (tem, 0), 1) == rhs)
02715
02716
02717
02718 && ! (first
02719 && GET_CODE (tem) == NOT
02720 && XEXP (tem, 0) == rhs))
02721 {
02722 lneg &= rneg;
02723 if (GET_CODE (tem) == NEG)
02724 tem = XEXP (tem, 0), lneg = !lneg;
02725 if (GET_CODE (tem) == CONST_INT && lneg)
02726 tem = neg_const_int (mode, tem), lneg = 0;
02727
02728 ops[i].op = tem;
02729 ops[i].neg = lneg;
02730 ops[j].op = NULL_RTX;
02731 changed = 1;
02732 }
02733 }
02734 }
02735
02736 first = 0;
02737 }
02738 while (changed);
02739
02740
02741 for (i = 0, j = 0; j < n_ops; j++)
02742 if (ops[j].op)
02743 ops[i++] = ops[j];
02744 n_ops = i;
02745
02746
02747 qsort (ops, n_ops, sizeof (*ops), simplify_plus_minus_op_data_cmp);
02748
02749
02750 if (n_ops == 2
02751 && GET_CODE (ops[1].op) == CONST_INT
02752 && CONSTANT_P (ops[0].op)
02753 && ops[0].neg)
02754 return gen_rtx_fmt_ee (MINUS, mode, ops[1].op, ops[0].op);
02755
02756
02757
02758
02759
02760
02761
02762 if (n_ops > 1
02763 && GET_CODE (ops[n_ops - 1].op) == CONST_INT
02764 && CONSTANT_P (ops[n_ops - 2].op))
02765 {
02766 rtx value = ops[n_ops - 1].op;
02767 if (ops[n_ops - 1].neg ^ ops[n_ops - 2].neg)
02768 value = neg_const_int (mode, value);
02769 ops[n_ops - 2].op = plus_constant (ops[n_ops - 2].op, INTVAL (value));
02770 n_ops--;
02771 }
02772
02773
02774 n_consts = 0;
02775 for (i = 0; i < n_ops; i++)
02776 if (GET_CODE (ops[i].op) == CONST)
02777 n_consts++;
02778
02779
02780
02781
02782
02783 if (!force
02784 && (n_ops + n_consts > input_ops
02785 || (n_ops + n_consts == input_ops && n_consts <= input_consts)))
02786 return NULL_RTX;
02787
02788
02789
02790 for (i = 0; i < n_ops && ops[i].neg; i++)
02791 continue;
02792 if (i == n_ops)
02793 ops[0].op = gen_rtx_NEG (mode, ops[0].op);
02794 else if (i != 0)
02795 {
02796 tem = ops[0].op;
02797 ops[0] = ops[i];
02798 ops[i].op = tem;
02799 ops[i].neg = 1;
02800 }
02801
02802
02803 result = ops[0].op;
02804 for (i = 1; i < n_ops; i++)
02805 result = gen_rtx_fmt_ee (ops[i].neg ? MINUS : PLUS,
02806 mode, result, ops[i].op);
02807
02808 return result;
02809 }
02810
02811
02812 static bool
02813 plus_minus_operand_p (rtx x)
02814 {
02815 return GET_CODE (x) == PLUS
02816 || GET_CODE (x) == MINUS
02817 || (GET_CODE (x) == CONST
02818 && GET_CODE (XEXP (x, 0)) == PLUS
02819 && CONSTANT_P (XEXP (XEXP (x, 0), 0))
02820 && CONSTANT_P (XEXP (XEXP (x, 0), 1)));
02821 }
02822
02823
02824
02825
02826
02827
02828
02829
02830
02831 rtx
02832 simplify_relational_operation (enum rtx_code code, enum machine_mode mode,
02833 enum machine_mode cmp_mode, rtx op0, rtx op1)
02834 {
02835 rtx tem, trueop0, trueop1;
02836
02837 if (cmp_mode == VOIDmode)
02838 cmp_mode = GET_MODE (op0);
02839 if (cmp_mode == VOIDmode)
02840 cmp_mode = GET_MODE (op1);
02841
02842 tem = simplify_const_relational_operation (code, cmp_mode, op0, op1);
02843 if (tem)
02844 {
02845 if (GET_MODE_CLASS (mode) == MODE_FLOAT)
02846 {
02847 if (tem == const0_rtx)
02848 return CONST0_RTX (mode);
02849 #ifdef FLOAT_STORE_FLAG_VALUE
02850 {
02851 REAL_VALUE_TYPE val;
02852 val = FLOAT_STORE_FLAG_VALUE (mode);
02853 return CONST_DOUBLE_FROM_REAL_VALUE (val, mode);
02854 }
02855 #else
02856 return NULL_RTX;
02857 #endif
02858 }
02859 if (VECTOR_MODE_P (mode))
02860 {
02861 if (tem == const0_rtx)
02862 return CONST0_RTX (mode);
02863 #ifdef VECTOR_STORE_FLAG_VALUE
02864 {
02865 int i, units;
02866 rtvec v;
02867
02868 rtx val = VECTOR_STORE_FLAG_VALUE (mode);
02869 if (val == NULL_RTX)
02870 return NULL_RTX;
02871 if (val == const1_rtx)
02872 return CONST1_RTX (mode);
02873
02874 units = GET_MODE_NUNITS (mode);
02875 v = rtvec_alloc (units);
02876 for (i = 0; i < units; i++)
02877 RTVEC_ELT (v, i) = val;
02878 return gen_rtx_raw_CONST_VECTOR (mode, v);
02879 }
02880 #else
02881 return NULL_RTX;
02882 #endif
02883 }
02884
02885 return tem;
02886 }
02887
02888
02889 if (swap_commutative_operands_p (op0, op1)
02890 || (op0 == const0_rtx && op1 != const0_rtx))
02891 tem = op0, op0 = op1, op1 = tem, code = swap_condition (code);
02892
02893
02894 if (GET_CODE (op0) == COMPARE && op1 == const0_rtx)
02895 return simplify_relational_operation (code, mode, VOIDmode,
02896 XEXP (op0, 0), XEXP (op0, 1));
02897
02898 if (mode == VOIDmode
02899 || GET_MODE_CLASS (cmp_mode) == MODE_CC
02900 || CC0_P (op0))
02901 return NULL_RTX;
02902
02903 trueop0 = avoid_constant_pool_reference (op0);
02904 trueop1 = avoid_constant_pool_reference (op1);
02905 return simplify_relational_operation_1 (code, mode, cmp_mode,
02906 trueop0, trueop1);
02907 }
02908
02909
02910
02911
02912
02913
02914
02915 static rtx
02916 simplify_relational_operation_1 (enum rtx_code code, enum machine_mode mode,
02917 enum machine_mode cmp_mode, rtx op0, rtx op1)
02918 {
02919 enum rtx_code op0code = GET_CODE (op0);
02920
02921 if (GET_CODE (op1) == CONST_INT)
02922 {
02923 if (INTVAL (op1) == 0 && COMPARISON_P (op0))
02924 {
02925
02926 if (code == NE)
02927 {
02928 if (GET_MODE (op0) == mode)
02929 return simplify_rtx (op0);
02930 else
02931 return simplify_gen_relational (GET_CODE (op0), mode, VOIDmode,
02932 XEXP (op0, 0), XEXP (op0, 1));
02933 }
02934 else if (code == EQ)
02935 {
02936 enum rtx_code new_code = reversed_comparison_code (op0, NULL_RTX);
02937 if (new_code != UNKNOWN)
02938 return simplify_gen_relational (new_code, mode, VOIDmode,
02939 XEXP (op0, 0), XEXP (op0, 1));
02940 }
02941 }
02942 }
02943
02944
02945 if ((code == EQ || code == NE)
02946 && (op0code == PLUS || op0code == MINUS)
02947 && CONSTANT_P (op1)
02948 && CONSTANT_P (XEXP (op0, 1))
02949 && (INTEGRAL_MODE_P (cmp_mode) || flag_unsafe_math_optimizations))
02950 {
02951 rtx x = XEXP (op0, 0);
02952 rtx c = XEXP (op0, 1);
02953
02954 c = simplify_gen_binary (op0code == PLUS ? MINUS : PLUS,
02955 cmp_mode, op1, c);
02956 return simplify_gen_relational (code, mode, cmp_mode, x, c);
02957 }
02958
02959
02960
02961 if (code == NE
02962 && op1 == const0_rtx
02963 && GET_MODE_CLASS (mode) == MODE_INT
02964 && cmp_mode != VOIDmode
02965
02966 && mode != BImode
02967 && cmp_mode != BImode
02968 && nonzero_bits (op0, cmp_mode) == 1
02969 && STORE_FLAG_VALUE == 1)
02970 return GET_MODE_SIZE (mode) > GET_MODE_SIZE (cmp_mode)
02971 ? simplify_gen_unary (ZERO_EXTEND, mode, op0, cmp_mode)
02972 : lowpart_subreg (mode, op0, cmp_mode);
02973
02974 return NULL_RTX;
02975 }
02976
02977
02978
02979
02980
02981
02982 rtx
02983 simplify_const_relational_operation (enum rtx_code code,
02984 enum machine_mode mode,
02985 rtx op0, rtx op1)
02986 {
02987 int equal, op0lt, op0ltu, op1lt, op1ltu;
02988 rtx tem;
02989 rtx trueop0;
02990 rtx trueop1;
02991
02992 gcc_assert (mode != VOIDmode
02993 || (GET_MODE (op0) == VOIDmode
02994 && GET_MODE (op1) == VOIDmode));
02995
02996
02997 if (GET_CODE (op0) == COMPARE && op1 == const0_rtx)
02998 op1 = XEXP (op0, 1), op0 = XEXP (op0, 0);
02999
03000
03001
03002 if (GET_MODE_CLASS (GET_MODE (op0)) == MODE_CC || CC0_P (op0))
03003 return 0;
03004
03005
03006 if (swap_commutative_operands_p (op0, op1))
03007 {
03008 tem = op0, op0 = op1, op1 = tem;
03009 code = swap_condition (code);
03010 }
03011
03012 trueop0 = avoid_constant_pool_reference (op0);
03013 trueop1 = avoid_constant_pool_reference (op1);
03014
03015
03016
03017
03018
03019
03020
03021
03022
03023
03024
03025
03026 if (!flag_wrapv && INTEGRAL_MODE_P (mode) && trueop1 != const0_rtx
03027 && ! ((REG_P (op0) || GET_CODE (trueop0) == CONST_INT)
03028 && (REG_P (op1) || GET_CODE (trueop1) == CONST_INT))
03029 && 0 != (tem = simplify_binary_operation (MINUS, mode, op0, op1))
03030
03031 && ((code != EQ && code != NE) || ! nonzero_address_p (tem))
03032 && code != GTU && code != GEU && code != LTU && code != LEU)
03033 return simplify_const_relational_operation (signed_condition (code),
03034 mode, tem, const0_rtx);
03035
03036 if (flag_unsafe_math_optimizations && code == ORDERED)
03037 return const_true_rtx;
03038
03039 if (flag_unsafe_math_optimizations && code == UNORDERED)
03040 return const0_rtx;
03041
03042
03043
03044 if (! HONOR_NANS (GET_MODE (trueop0))
03045 && rtx_equal_p (trueop0, trueop1)
03046 && ! side_effects_p (trueop0))
03047 equal = 1, op0lt = 0, op0ltu = 0, op1lt = 0, op1ltu = 0;
03048
03049
03050
03051 else if (GET_CODE (trueop0) == CONST_DOUBLE
03052 && GET_CODE (trueop1) == CONST_DOUBLE
03053 && GET_MODE_CLASS (GET_MODE (trueop0)) == MODE_FLOAT)
03054 {
03055 REAL_VALUE_TYPE d0, d1;
03056
03057 REAL_VALUE_FROM_CONST_DOUBLE (d0, trueop0);
03058 REAL_VALUE_FROM_CONST_DOUBLE (d1, trueop1);
03059
03060
03061 if (REAL_VALUE_ISNAN (d0) || REAL_VALUE_ISNAN (d1))
03062 switch (code)
03063 {
03064 case UNEQ:
03065 case UNLT:
03066 case UNGT:
03067 case UNLE:
03068 case UNGE:
03069 case NE:
03070 case UNORDERED:
03071 return const_true_rtx;
03072 case EQ:
03073 case LT:
03074 case GT:
03075 case LE:
03076 case GE:
03077 case LTGT:
03078 case ORDERED:
03079 return const0_rtx;
03080 default:
03081 return 0;
03082 }
03083
03084 equal = REAL_VALUES_EQUAL (d0, d1);
03085 op0lt = op0ltu = REAL_VALUES_LESS (d0, d1);
03086 op1lt = op1ltu = REAL_VALUES_LESS (d1, d0);
03087 }
03088
03089
03090 else if ((GET_MODE_CLASS (mode) == MODE_INT || mode == VOIDmode)
03091 && (GET_CODE (trueop0) == CONST_DOUBLE
03092 || GET_CODE (trueop0) == CONST_INT)
03093 && (GET_CODE (trueop1) == CONST_DOUBLE
03094 || GET_CODE (trueop1) == CONST_INT))
03095 {
03096 int width = GET_MODE_BITSIZE (mode);
03097 HOST_WIDE_INT l0s, h0s, l1s, h1s;
03098 unsigned HOST_WIDE_INT l0u, h0u, l1u, h1u;
03099
03100
03101 if (GET_CODE (trueop0) == CONST_DOUBLE)
03102 {
03103 l0u = l0s = CONST_DOUBLE_LOW (trueop0);
03104 h0u = h0s = CONST_DOUBLE_HIGH (trueop0);
03105 }
03106 else
03107 {
03108 l0u = l0s = INTVAL (trueop0);
03109 h0u = h0s = HWI_SIGN_EXTEND (l0s);
03110 }
03111
03112 if (GET_CODE (trueop1) == CONST_DOUBLE)
03113 {
03114 l1u = l1s = CONST_DOUBLE_LOW (trueop1);
03115 h1u = h1s = CONST_DOUBLE_HIGH (trueop1);
03116 }
03117 else
03118 {
03119 l1u = l1s = INTVAL (trueop1);
03120 h1u = h1s = HWI_SIGN_EXTEND (l1s);
03121 }
03122
03123
03124
03125 if (width != 0 && width < HOST_BITS_PER_WIDE_INT)
03126 {
03127 l0u &= ((HOST_WIDE_INT) 1 << width) - 1;
03128 l1u &= ((HOST_WIDE_INT) 1 << width) - 1;
03129
03130 if (l0s & ((HOST_WIDE_INT) 1 << (width - 1)))
03131 l0s |= ((HOST_WIDE_INT) (-1) << width);
03132
03133 if (l1s & ((HOST_WIDE_INT) 1 << (width - 1)))
03134 l1s |= ((HOST_WIDE_INT) (-1) << width);
03135 }
03136 if (width != 0 && width <= HOST_BITS_PER_WIDE_INT)
03137 h0u = h1u = 0, h0s = HWI_SIGN_EXTEND (l0s), h1s = HWI_SIGN_EXTEND (l1s);
03138
03139 equal = (h0u == h1u && l0u == l1u);
03140 op0lt = (h0s < h1s || (h0s == h1s && l0u < l1u));
03141 op1lt = (h1s < h0s || (h1s == h0s && l1u < l0u));
03142 op0ltu = (h0u < h1u || (h0u == h1u && l0u < l1u));
03143 op1ltu = (h1u < h0u || (h1u == h0u && l1u < l0u));
03144 }
03145
03146
03147 else
03148 {
03149
03150 if (SCALAR_INT_MODE_P (mode)
03151 && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT)
03152 {
03153 rtx mmin, mmax;
03154 int sign;
03155
03156 if (code == GEU
03157 || code == LEU
03158 || code == GTU
03159 || code == LTU)
03160 sign = 0;
03161 else
03162 sign = 1;
03163
03164 get_mode_bounds (mode, sign, mode, &mmin, &mmax);
03165
03166 tem = NULL_RTX;
03167 switch (code)
03168 {
03169 case GEU:
03170 case GE:
03171
03172 if (rtx_equal_p (trueop1, mmin))
03173 tem = const_true_rtx;
03174 else
03175 break;
03176
03177 case LEU:
03178 case LE:
03179
03180 if (rtx_equal_p (trueop1, mmax))
03181 tem = const_true_rtx;
03182 break;
03183
03184 case GTU:
03185 case GT:
03186
03187 if (rtx_equal_p (trueop1, mmax))
03188 tem = const0_rtx;
03189 break;
03190
03191 case LTU:
03192 case LT:
03193
03194 if (rtx_equal_p (trueop1, mmin))
03195 tem = const0_rtx;
03196 break;
03197
03198 default:
03199 break;
03200 }
03201 if (tem == const0_rtx
03202 || tem == const_true_rtx)
03203 return tem;
03204 }
03205
03206 switch (code)
03207 {
03208 case EQ:
03209 if (trueop1 == const0_rtx && nonzero_address_p (op0))
03210 return const0_rtx;
03211 break;
03212
03213 case NE:
03214 if (trueop1 == const0_rtx && nonzero_address_p (op0))
03215 return const_true_rtx;
03216 break;
03217
03218 case LT:
03219
03220 if (trueop1 == CONST0_RTX (mode) && !HONOR_SNANS (mode))
03221 {
03222 tem = GET_CODE (trueop0) == FLOAT_EXTEND ? XEXP (trueop0, 0)
03223 : trueop0;
03224 if (GET_CODE (tem) == ABS)
03225 return const0_rtx;
03226 }
03227 break;
03228
03229 case GE:
03230
03231 if (trueop1 == CONST0_RTX (mode) && !HONOR_NANS (mode))
03232 {
03233 tem = GET_CODE (trueop0) == FLOAT_EXTEND ? XEXP (trueop0, 0)
03234 : trueop0;
03235 if (GET_CODE (tem) == ABS)
03236 return const_true_rtx;
03237 }
03238 break;
03239
03240 case UNGE:
03241
03242 if (trueop1 == CONST0_RTX (mode))
03243 {
03244 tem = GET_CODE (trueop0) == FLOAT_EXTEND ? XEXP (trueop0, 0)
03245 : trueop0;
03246 if (GET_CODE (tem) == ABS)
03247 return const_true_rtx;
03248 }
03249 break;
03250
03251 default:
03252 break;
03253 }
03254
03255 return 0;
03256 }
03257
03258
03259
03260 switch (code)
03261 {
03262 case EQ:
03263 case UNEQ:
03264 return equal ? const_true_rtx : const0_rtx;
03265 case NE:
03266 case LTGT:
03267 return ! equal ? const_true_rtx : const0_rtx;
03268 case LT:
03269 case UNLT:
03270 return op0lt ? const_true_rtx : const0_rtx;
03271 case GT:
03272 case UNGT:
03273 return op1lt ? const_true_rtx : const0_rtx;
03274 case LTU:
03275 return op0ltu ? const_true_rtx : const0_rtx;
03276 case GTU:
03277 return op1ltu ? const_true_rtx : const0_rtx;
03278 case LE:
03279 case UNLE:
03280 return equal || op0lt ? const_true_rtx : const0_rtx;
03281 case GE:
03282 case UNGE:
03283 return equal || op1lt ? const_true_rtx : const0_rtx;
03284 case LEU:
03285 return equal || op0ltu ? const_true_rtx : const0_rtx;
03286 case GEU:
03287 return equal || op1ltu ? const_true_rtx : const0_rtx;
03288 case ORDERED:
03289 return const_true_rtx;
03290 case UNORDERED:
03291 return const0_rtx;
03292 default:
03293 gcc_unreachable ();
03294 }
03295 }
03296
03297
03298
03299
03300
03301 rtx
03302 simplify_ternary_operation (enum rtx_code code, enum machine_mode mode,
03303 enum machine_mode op0_mode, rtx op0, rtx op1,
03304 rtx op2)
03305 {
03306 unsigned int width = GET_MODE_BITSIZE (mode);
03307
03308
03309 if (width == 0)
03310 width = HOST_BITS_PER_WIDE_INT;
03311
03312 switch (code)
03313 {
03314 case SIGN_EXTRACT:
03315 case ZERO_EXTRACT:
03316 if (GET_CODE (op0) == CONST_INT
03317 && GET_CODE (op1) == CONST_INT
03318 && GET_CODE (op2) == CONST_INT
03319 && ((unsigned) INTVAL (op1) + (unsigned) INTVAL (op2) <= width)
03320 && width <= (unsigned) HOST_BITS_PER_WIDE_INT)
03321 {
03322
03323 HOST_WIDE_INT val = INTVAL (op0);
03324
03325 if (BITS_BIG_ENDIAN)
03326 val >>= (GET_MODE_BITSIZE (op0_mode)
03327 - INTVAL (op2) - INTVAL (op1));
03328 else
03329 val >>= INTVAL (op2);
03330
03331 if (HOST_BITS_PER_WIDE_INT != INTVAL (op1))
03332 {
03333
03334 val &= ((HOST_WIDE_INT) 1 << INTVAL (op1)) - 1;
03335
03336 if (code == SIGN_EXTRACT
03337 && (val & ((HOST_WIDE_INT) 1 << (INTVAL (op1) - 1))))
03338 val |= ~ (((HOST_WIDE_INT) 1 << INTVAL (op1)) - 1);
03339 }
03340
03341
03342
03343
03344
03345 if (width < HOST_BITS_PER_WIDE_INT
03346 && ((val & ((HOST_WIDE_INT) (-1) << (width - 1)))
03347 != ((HOST_WIDE_INT) (-1) << (width - 1))))
03348 val &= ((HOST_WIDE_INT) 1 << width) - 1;
03349
03350 return gen_int_mode (val, mode);
03351 }
03352 break;
03353
03354 case IF_THEN_ELSE:
03355 if (GET_CODE (op0) == CONST_INT)
03356 return op0 != const0_rtx ? op1 : op2;
03357
03358
03359 if (rtx_equal_p (op1, op2) && ! side_effects_p (op0))
03360 return op1;
03361
03362
03363 if (GET_CODE (op0) == NE
03364 && ! side_effects_p (op0)
03365 && ! HONOR_NANS (mode)
03366 && ! HONOR_SIGNED_ZEROS (mode)
03367 && ((rtx_equal_p (XEXP (op0, 0), op1)
03368 && rtx_equal_p (XEXP (op0, 1), op2))
03369 || (rtx_equal_p (XEXP (op0, 0), op2)
03370 && rtx_equal_p (XEXP (op0, 1), op1))))
03371 return op1;
03372
03373
03374 if (GET_CODE (op0) == EQ
03375 && ! side_effects_p (op0)
03376 && ! HONOR_NANS (mode)
03377 && ! HONOR_SIGNED_ZEROS (mode)
03378 && ((rtx_equal_p (XEXP (op0, 0), op1)
03379 && rtx_equal_p (XEXP (op0, 1), op2))
03380 || (rtx_equal_p (XEXP (op0, 0), op2)
03381 && rtx_equal_p (XEXP (op0, 1), op1))))
03382 return op2;
03383
03384 if (COMPARISON_P (op0) && ! side_effects_p (op0))
03385 {
03386 enum machine_mode cmp_mode = (GET_MODE (XEXP (op0, 0)) == VOIDmode
03387 ? GET_MODE (XEXP (op0, 1))
03388 : GET_MODE (XEXP (op0, 0)));
03389 rtx temp;
03390
03391
03392 if (GET_CODE (op1) == CONST_INT && GET_CODE (op2) == CONST_INT)
03393 {
03394 HOST_WIDE_INT t = INTVAL (op1);
03395 HOST_WIDE_INT f = INTVAL (op2);
03396
03397 if (t == STORE_FLAG_VALUE && f == 0)
03398 code = GET_CODE (op0);
03399 else if (t == 0 && f == STORE_FLAG_VALUE)
03400 {
03401 enum rtx_code tmp;
03402 tmp = reversed_comparison_code (op0, NULL_RTX);
03403 if (tmp == UNKNOWN)
03404 break;
03405 code = tmp;
03406 }
03407 else
03408 break;
03409
03410 return simplify_gen_relational (code, mode, cmp_mode,
03411 XEXP (op0, 0), XEXP (op0, 1));
03412 }
03413
03414 if (cmp_mode == VOIDmode)
03415 cmp_mode = op0_mode;
03416 temp = simplify_relational_operation (GET_CODE (op0), op0_mode,
03417 cmp_mode, XEXP (op0, 0),
03418 XEXP (op0, 1));
03419
03420
03421 if (temp)
03422 {
03423 if (GET_CODE (temp) == CONST_INT)
03424 return temp == const0_rtx ? op2 : op1;
03425 else if (temp)
03426 return gen_rtx_IF_THEN_ELSE (mode, temp, op1, op2);
03427 }
03428 }
03429 break;
03430
03431 case VEC_MERGE:
03432 gcc_assert (GET_MODE (op0) == mode);
03433 gcc_assert (GET_MODE (op1) == mode);
03434 gcc_assert (VECTOR_MODE_P (mode));
03435 op2 = avoid_constant_pool_reference (op2);
03436 if (GET_CODE (op2) == CONST_INT)
03437 {
03438 int elt_size = GET_MODE_SIZE (GET_MODE_INNER (mode));
03439 unsigned n_elts = (GET_MODE_SIZE (mode) / elt_size);
03440 int mask = (1 << n_elts) - 1;
03441
03442 if (!(INTVAL (op2) & mask))
03443 return op1;
03444 if ((INTVAL (op2) & mask) == mask)
03445 return op0;
03446
03447 op0 = avoid_constant_pool_reference (op0);
03448 op1 = avoid_constant_pool_reference (op1);
03449 if (GET_CODE (op0) == CONST_VECTOR
03450 && GET_CODE (op1) == CONST_VECTOR)
03451 {
03452 rtvec v = rtvec_alloc (n_elts);
03453 unsigned int i;
03454
03455 for (i = 0; i < n_elts; i++)
03456 RTVEC_ELT (v, i) = (INTVAL (op2) & (1 << i)
03457 ? CONST_VECTOR_ELT (op0, i)
03458 : CONST_VECTOR_ELT (op1, i));
03459 return gen_rtx_CONST_VECTOR (mode, v);
03460 }
03461 }
03462 break;
03463
03464 default:
03465 gcc_unreachable ();
03466 }
03467
03468 return 0;
03469 }
03470
03471
03472
03473
03474
03475
03476
03477
03478 static rtx
03479 simplify_immed_subreg (enum machine_mode outermode, rtx op,
03480 enum machine_mode innermode, unsigned int byte)
03481 {
03482
03483 enum {
03484 max_bitsize = 512,
03485 value_bit = 8,
03486 value_mask = (1 << value_bit) - 1
03487 };
03488 unsigned char value[max_bitsize / value_bit];
03489 int value_start;
03490 int i;
03491 int elem;
03492
03493 int num_elem;
03494 rtx * elems;
03495 int elem_bitsize;
03496 rtx result_s;
03497 rtvec result_v = NULL;
03498 enum mode_class outer_class;
03499 enum machine_mode outer_submode;
03500
03501
03502 if (GET_MODE_CLASS (outermode) == MODE_CC && GET_CODE (op) == CONST_INT)
03503 return op;
03504
03505
03506 if (COMPLEX_MODE_P (outermode))
03507 return NULL_RTX;
03508
03509
03510
03511 if (GET_CODE (op) == CONST_VECTOR)
03512 {
03513 num_elem = CONST_VECTOR_NUNITS (op);
03514 elems = &CONST_VECTOR_ELT (op, 0);
03515 elem_bitsize = GET_MODE_BITSIZE (GET_MODE_INNER (innermode));
03516 }
03517 else
03518 {
03519 num_elem = 1;
03520 elems = &op;
03521 elem_bitsize = max_bitsize;
03522 }
03523
03524 gcc_assert (BITS_PER_UNIT % value_bit == 0);
03525
03526 gcc_assert (elem_bitsize % BITS_PER_UNIT == 0);
03527
03528 for (elem = 0; elem < num_elem; elem++)
03529 {
03530 unsigned char * vp;
03531 rtx el = elems[elem];
03532
03533
03534
03535 {
03536 unsigned byte = (elem * elem_bitsize) / BITS_PER_UNIT;
03537 unsigned ibyte = (((num_elem - 1 - elem) * elem_bitsize)
03538 / BITS_PER_UNIT);
03539 unsigned word_byte = WORDS_BIG_ENDIAN ? ibyte : byte;
03540 unsigned subword_byte = BYTES_BIG_ENDIAN ? ibyte : byte;
03541 unsigned bytele = (subword_byte % UNITS_PER_WORD
03542 + (word_byte / UNITS_PER_WORD) * UNITS_PER_WORD);
03543 vp = value + (bytele * BITS_PER_UNIT) / value_bit;
03544 }
03545
03546 switch (GET_CODE (el))
03547 {
03548 case CONST_INT:
03549 for (i = 0;
03550 i < HOST_BITS_PER_WIDE_INT && i < elem_bitsize;
03551 i += value_bit)
03552 *vp++ = INTVAL (el) >> i;
03553
03554 for (; i < elem_bitsize; i += value_bit)
03555 *vp++ = INTVAL (el) < 0 ? -1 : 0;
03556 break;
03557
03558 case CONST_DOUBLE:
03559 if (GET_MODE (el) == VOIDmode)
03560 {
03561
03562
03563 gcc_assert (elem_bitsize > HOST_BITS_PER_WIDE_INT);
03564
03565 for (i = 0; i < HOST_BITS_PER_WIDE_INT; i += value_bit)
03566 *vp++ = CONST_DOUBLE_LOW (el) >> i;
03567 while (i < HOST_BITS_PER_WIDE_INT * 2 && i < elem_bitsize)
03568 {
03569 *vp++
03570 = CONST_DOUBLE_HIGH (el) >> (i - HOST_BITS_PER_WIDE_INT);
03571 i += value_bit;
03572 }
03573
03574
03575 for (; i < elem_bitsize; i += value_bit)
03576 *vp++ = 0;
03577 }
03578 else
03579 {
03580 long tmp[max_bitsize / 32];
03581 int bitsize = GET_MODE_BITSIZE (GET_MODE (el));
03582
03583 gcc_assert (GET_MODE_CLASS (GET_MODE (el)) == MODE_FLOAT);
03584 gcc_assert (bitsize <= elem_bitsize);
03585 gcc_assert (bitsize % value_bit == 0);
03586
03587 real_to_target (tmp, CONST_DOUBLE_REAL_VALUE (el),
03588 GET_MODE (el));
03589
03590
03591
03592
03593
03594 for (i = 0; i < bitsize; i += value_bit)
03595 {
03596 int ibase;
03597 if (WORDS_BIG_ENDIAN)
03598 ibase = bitsize - 1 - i;
03599 else
03600 ibase = i;
03601 *vp++ = tmp[ibase / 32] >> i % 32;
03602 }
03603
03604
03605
03606 for (; i < elem_bitsize; i += value_bit)
03607 *vp++ = 0;
03608 }
03609 break;
03610
03611 default:
03612 gcc_unreachable ();
03613 }
03614 }
03615
03616
03617
03618
03619
03620 if (GET_MODE_SIZE (innermode) >= GET_MODE_SIZE (outermode))
03621 {
03622 unsigned ibyte = (GET_MODE_SIZE (innermode) - GET_MODE_SIZE (outermode)
03623 - byte);
03624 unsigned word_byte = WORDS_BIG_ENDIAN ? ibyte : byte;
03625 unsigned subword_byte = BYTES_BIG_ENDIAN ? ibyte : byte;
03626 byte = (subword_byte % UNITS_PER_WORD
03627 + (word_byte / UNITS_PER_WORD) * UNITS_PER_WORD);
03628 }
03629
03630
03631
03632 gcc_assert (byte < GET_MODE_SIZE (innermode));
03633
03634
03635 value_start = byte * (BITS_PER_UNIT / value_bit);
03636
03637
03638
03639 if (VECTOR_MODE_P (outermode))
03640 {
03641 num_elem = GET_MODE_NUNITS (outermode);
03642 result_v = rtvec_alloc (num_elem);
03643 elems = &RTVEC_ELT (result_v, 0);
03644 outer_submode = GET_MODE_INNER (outermode);
03645 }
03646 else
03647 {
03648 num_elem = 1;
03649 elems = &result_s;
03650 outer_submode = outermode;
03651 }
03652
03653 outer_class = GET_MODE_CLASS (outer_submode);
03654 elem_bitsize = GET_MODE_BITSIZE (outer_submode);
03655
03656 gcc_assert (elem_bitsize % value_bit == 0);
03657 gcc_assert (elem_bitsize + value_start * value_bit <= max_bitsize);
03658
03659 for (elem = 0; elem < num_elem; elem++)
03660 {
03661 unsigned char *vp;
03662
03663
03664
03665 {
03666 unsigned byte = (elem * elem_bitsize) / BITS_PER_UNIT;
03667 unsigned ibyte = (((num_elem - 1 - elem) * elem_bitsize)
03668 / BITS_PER_UNIT);
03669 unsigned word_byte = WORDS_BIG_ENDIAN ? ibyte : byte;
03670 unsigned subword_byte = BYTES_BIG_ENDIAN ? ibyte : byte;
03671 unsigned bytele = (subword_byte % UNITS_PER_WORD
03672 + (word_byte / UNITS_PER_WORD) * UNITS_PER_WORD);
03673 vp = value + value_start + (bytele * BITS_PER_UNIT) / value_bit;
03674 }
03675
03676 switch (outer_class)
03677 {
03678 case MODE_INT:
03679 case MODE_PARTIAL_INT:
03680 {
03681 unsigned HOST_WIDE_INT hi = 0, lo = 0;
03682
03683 for (i = 0;
03684 i < HOST_BITS_PER_WIDE_INT && i < elem_bitsize;
03685 i += value_bit)
03686 lo |= (HOST_WIDE_INT)(*vp++ & value_mask) << i;
03687 for (; i < elem_bitsize; i += value_bit)
03688 hi |= ((HOST_WIDE_INT)(*vp++ & value_mask)
03689 << (i - HOST_BITS_PER_WIDE_INT));
03690
03691
03692
03693 if (elem_bitsize <= HOST_BITS_PER_WIDE_INT)
03694 elems[elem] = gen_int_mode (lo, outer_submode);
03695 else
03696 elems[elem] = immed_double_const (lo, hi, outer_submode);
03697 }
03698 break;
03699
03700 case MODE_FLOAT:
03701 {
03702 REAL_VALUE_TYPE r;
03703 long tmp[max_bitsize / 32];
03704
03705
03706
03707
03708
03709 for (i = 0; i < max_bitsize / 32; i++)
03710 tmp[i] = 0;
03711 for (i = 0; i < elem_bitsize; i += value_bit)
03712 {
03713 int ibase;
03714 if (WORDS_BIG_ENDIAN)
03715 ibase = elem_bitsize - 1 - i;
03716 else
03717 ibase = i;
03718 tmp[ibase / 32] |= (*vp++ & value_mask) << i % 32;
03719 }
03720
03721 real_from_target (&r, tmp, outer_submode);
03722 elems[elem] = CONST_DOUBLE_FROM_REAL_VALUE (r, outer_submode);
03723 }
03724 break;
03725
03726 default:
03727 gcc_unreachable ();
03728 }
03729 }
03730 if (VECTOR_MODE_P (outermode))
03731 return gen_rtx_CONST_VECTOR (outermode, result_v);
03732 else
03733 return result_s;
03734 }
03735
03736
03737
03738 rtx
03739 simplify_subreg (enum machine_mode outermode, rtx op,
03740 enum machine_mode innermode, unsigned int byte)
03741 {
03742
03743 gcc_assert (innermode != VOIDmode);
03744 gcc_assert (outermode != VOIDmode);
03745 gcc_assert (innermode != BLKmode);
03746 gcc_assert (outermode != BLKmode);
03747
03748 gcc_assert (GET_MODE (op) == innermode
03749 || GET_MODE (op) == VOIDmode);
03750
03751 gcc_assert ((byte % GET_MODE_SIZE (outermode)) == 0);
03752 gcc_assert (byte < GET_MODE_SIZE (innermode));
03753
03754 if (outermode == innermode && !byte)
03755 return op;
03756
03757 if (GET_CODE (op) == CONST_INT
03758 || GET_CODE (op) == CONST_DOUBLE
03759 || GET_CODE (op) == CONST_VECTOR)
03760 return simplify_immed_subreg (outermode, op, innermode, byte);
03761
03762
03763
03764 if (GET_CODE (op) == SUBREG)
03765 {
03766 enum machine_mode innermostmode = GET_MODE (SUBREG_REG (op));
03767 int final_offset = byte + SUBREG_BYTE (op);
03768 rtx newx;
03769
03770 if (outermode == innermostmode
03771 && byte == 0 && SUBREG_BYTE (op) == 0)
03772 return SUBREG_REG (op);
03773
03774
03775
03776
03777
03778 if (byte == 0 && GET_MODE_SIZE (innermode) < GET_MODE_SIZE (outermode))
03779 {
03780 int difference = (GET_MODE_SIZE (innermode) - GET_MODE_SIZE (outermode));
03781 if (WORDS_BIG_ENDIAN)
03782 final_offset += (difference / UNITS_PER_WORD) * UNITS_PER_WORD;
03783 if (BYTES_BIG_ENDIAN)
03784 final_offset += difference % UNITS_PER_WORD;
03785 }
03786 if (SUBREG_BYTE (op) == 0
03787 && GET_MODE_SIZE (innermostmode) < GET_MODE_SIZE (innermode))
03788 {
03789 int difference = (GET_MODE_SIZE (innermostmode) - GET_MODE_SIZE (innermode));
03790 if (WORDS_BIG_ENDIAN)
03791 final_offset += (difference / UNITS_PER_WORD) * UNITS_PER_WORD;
03792 if (BYTES_BIG_ENDIAN)
03793 final_offset += difference % UNITS_PER_WORD;
03794 }
03795
03796
03797 if (GET_MODE_SIZE (innermostmode) > GET_MODE_SIZE (outermode))
03798 {
03799
03800 if (final_offset < 0)
03801 return NULL_RTX;
03802
03803 if (final_offset % GET_MODE_SIZE (outermode)
03804 || (unsigned) final_offset >= GET_MODE_SIZE (innermostmode))
03805 return NULL_RTX;
03806 }
03807 else
03808 {
03809 int offset = 0;
03810 int difference = (GET_MODE_SIZE (innermostmode) - GET_MODE_SIZE (outermode));
03811
03812
03813
03814 if (WORDS_BIG_ENDIAN)
03815 offset += (difference / UNITS_PER_WORD) * UNITS_PER_WORD;
03816 if (BYTES_BIG_ENDIAN)
03817 offset += difference % UNITS_PER_WORD;
03818 if (offset == final_offset)
03819 final_offset = 0;
03820 else
03821 return NULL_RTX;
03822 }
03823
03824
03825 newx = simplify_subreg (outermode, SUBREG_REG (op), innermostmode,
03826 final_offset);
03827 if (newx)
03828 return newx;
03829 if (validate_subreg (outermode, innermostmode,
03830 SUBREG_REG (op), final_offset))
03831 return gen_rtx_SUBREG (outermode, SUBREG_REG (op), final_offset);
03832 return NULL_RTX;
03833 }
03834
03835
03836
03837
03838
03839
03840 if (REG_P (op)
03841 && REGNO (op) < FIRST_PSEUDO_REGISTER
03842 #ifdef CANNOT_CHANGE_MODE_CLASS
03843 && ! (REG_CANNOT_CHANGE_MODE_P (REGNO (op), innermode, outermode)
03844 && GET_MODE_CLASS (innermode) != MODE_COMPLEX_INT
03845 && GET_MODE_CLASS (innermode) != MODE_COMPLEX_FLOAT)
03846 #endif
03847 && ((reload_completed && !frame_pointer_needed)
03848 || (REGNO (op) != FRAME_POINTER_REGNUM
03849 #if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM
03850 && REGNO (op) != HARD_FRAME_POINTER_REGNUM
03851 #endif
03852 ))
03853 #if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
03854 && REGNO (op) != ARG_POINTER_REGNUM
03855 #endif
03856 && REGNO (op) != STACK_POINTER_REGNUM
03857 && subreg_offset_representable_p (REGNO (op), innermode,
03858 byte, outermode))
03859 {
03860 unsigned int regno = REGNO (op);
03861 unsigned int final_regno
03862 = regno + subreg_regno_offset (regno, innermode, byte, outermode);
03863
03864
03865
03866
03867 if (HARD_REGNO_MODE_OK (final_regno, outermode)
03868 || ! HARD_REGNO_MODE_OK (regno, innermode))
03869 {
03870 rtx x = gen_rtx_REG_offset (op, outermode, final_regno, byte);
03871
03872
03873
03874
03875
03876
03877 if (subreg_lowpart_offset (outermode, innermode) == byte)
03878 ORIGINAL_REGNO (x) = ORIGINAL_REGNO (op);
03879 return x;
03880 }
03881 }
03882
03883
03884
03885
03886
03887
03888 if (MEM_P (op)
03889 && ! mode_dependent_address_p (XEXP (op, 0))
03890
03891
03892 && (! MEM_VOLATILE_P (op)
03893 || ! have_insn_for (SET, innermode))
03894 && GET_MODE_SIZE (outermode) <= GET_MODE_SIZE (GET_MODE (op)))
03895 return adjust_address_nv (op, outermode, byte);
03896
03897
03898
03899 if (GET_CODE (op) == CONCAT)
03900 {
03901 unsigned int inner_size, final_offset;
03902 rtx part, res;
03903
03904 inner_size = GET_MODE_UNIT_SIZE (innermode);
03905 part = byte < inner_size ? XEXP (op, 0) : XEXP (op, 1);
03906 final_offset = byte % inner_size;
03907 if (final_offset + GET_MODE_SIZE (outermode) > inner_size)
03908 return NULL_RTX;
03909
03910 res = simplify_subreg (outermode, part, GET_MODE (part), final_offset);
03911 if (res)
03912 return res;
03913 if (validate_subreg (outermode, GET_MODE (part), part, final_offset))
03914 return gen_rtx_SUBREG (outermode, part, final_offset);
03915 return NULL_RTX;
03916 }
03917
03918
03919 if ((GET_CODE (op) == ZERO_EXTEND
03920 || GET_CODE (op) == SIGN_EXTEND)
03921 && GET_MODE_BITSIZE (outermode) < GET_MODE_BITSIZE (innermode))
03922 {
03923 unsigned int bitpos = subreg_lsb_1 (outermode, innermode, byte);
03924
03925
03926
03927
03928
03929
03930
03931
03932 if (bitpos == 0)
03933 {
03934 enum machine_mode origmode = GET_MODE (XEXP (op, 0));
03935 if (outermode == origmode)
03936 return XEXP (op, 0);
03937 if (GET_MODE_BITSIZE (outermode) <= GET_MODE_BITSIZE (origmode))
03938 return simplify_gen_subreg (outermode, XEXP (op, 0), origmode,
03939 subreg_lowpart_offset (outermode,
03940 origmode));
03941 if (SCALAR_INT_MODE_P (outermode))
03942 return simplify_gen_unary (GET_CODE (op), outermode,
03943 XEXP (op, 0), origmode);
03944 }
03945
03946
03947
03948 if (GET_CODE (op) == ZERO_EXTEND
03949 && bitpos >= GET_MODE_BITSIZE (GET_MODE (XEXP (op, 0))))
03950 return CONST0_RTX (outermode);
03951 }
03952
03953
03954
03955
03956 if ((GET_CODE (op) == LSHIFTRT
03957 || GET_CODE (op) == ASHIFTRT)
03958 && SCALAR_INT_MODE_P (outermode)
03959
03960
03961
03962
03963 && (2 * GET_MODE_BITSIZE (outermode)) <= GET_MODE_BITSIZE (innermode)
03964 && GET_CODE (XEXP (op, 1)) == CONST_INT
03965 && GET_CODE (XEXP (op, 0)) == SIGN_EXTEND
03966 && GET_MODE (XEXP (XEXP (op, 0), 0)) == outermode
03967 && INTVAL (XEXP (op, 1)) < GET_MODE_BITSIZE (outermode)
03968 && subreg_lsb_1 (outermode, innermode, byte) == 0)
03969 return simplify_gen_binary (ASHIFTRT, outermode,
03970 XEXP (XEXP (op, 0), 0), XEXP (op, 1));
03971
03972
03973
03974
03975 if ((GET_CODE (op) == LSHIFTRT
03976 || GET_CODE (op) == ASHIFTRT)
03977 && SCALAR_INT_MODE_P (outermode)
03978 && GET_MODE_BITSIZE (outermode) < GET_MODE_BITSIZE (innermode)
03979 && GET_CODE (XEXP (op, 1)) == CONST_INT
03980 && GET_CODE (XEXP (op, 0)) == ZERO_EXTEND
03981 && GET_MODE (XEXP (XEXP (op, 0), 0)) == outermode
03982 && INTVAL (XEXP (op, 1)) < GET_MODE_BITSIZE (outermode)
03983 && subreg_lsb_1 (outermode, innermode, byte) == 0)
03984 return simplify_gen_binary (LSHIFTRT, outermode,
03985 XEXP (XEXP (op, 0), 0), XEXP (op, 1));
03986
03987
03988
03989
03990 if (GET_CODE (op) == ASHIFT
03991 && SCALAR_INT_MODE_P (outermode)
03992 && GET_MODE_BITSIZE (outermode) < GET_MODE_BITSIZE (innermode)
03993 && GET_CODE (XEXP (op, 1)) == CONST_INT
03994 && (GET_CODE (XEXP (op, 0)) == ZERO_EXTEND
03995 || GET_CODE (XEXP (op, 0)) == SIGN_EXTEND)
03996 && GET_MODE (XEXP (XEXP (op, 0), 0)) == outermode
03997 && INTVAL (XEXP (op, 1)) < GET_MODE_BITSIZE (outermode)
03998 && subreg_lsb_1 (outermode, innermode, byte) == 0)
03999 return simplify_gen_binary (ASHIFT, outermode,
04000 XEXP (XEXP (op, 0), 0), XEXP (op, 1));
04001
04002 return NULL_RTX;
04003 }
04004
04005
04006
04007 rtx
04008 simplify_gen_subreg (enum machine_mode outermode, rtx op,
04009 enum machine_mode innermode, unsigned int byte)
04010 {
04011 rtx newx;
04012
04013 newx = simplify_subreg (outermode, op, innermode, byte);
04014 if (newx)
04015 return newx;
04016
04017 if (GET_CODE (op) == SUBREG
04018 || GET_CODE (op) == CONCAT
04019 || GET_MODE (op) == VOIDmode)
04020 return NULL_RTX;
04021
04022 if (validate_subreg (outermode, innermode, op, byte))
04023 return gen_rtx_SUBREG (outermode, op, byte);
04024
04025 return NULL_RTX;
04026 }
04027
04028
04029
04030
04031
04032
04033
04034
04035
04036
04037
04038
04039
04040
04041
04042
04043
04044
04045
04046
04047
04048
04049
04050
04051
04052
04053
04054
04055
04056
04057
04058
04059
04060
04061
04062
04063
04064
04065
04066
04067
04068 rtx
04069 simplify_rtx (rtx x)
04070 {
04071 enum rtx_code code = GET_CODE (x);
04072 enum machine_mode mode = GET_MODE (x);
04073
04074 switch (GET_RTX_CLASS (code))
04075 {
04076 case RTX_UNARY:
04077 return simplify_unary_operation (code, mode,
04078 XEXP (x, 0), GET_MODE (XEXP (x, 0)));
04079 case RTX_COMM_ARITH:
04080 if (swap_commutative_operands_p (XEXP (x, 0), XEXP (x, 1)))
04081 return simplify_gen_binary (code, mode, XEXP (x, 1), XEXP (x, 0));
04082
04083
04084
04085 case RTX_BIN_ARITH:
04086 return simplify_binary_operation (code, mode, XEXP (x, 0), XEXP (x, 1));
04087
04088 case RTX_TERNARY:
04089 case RTX_BITFIELD_OPS:
04090 return simplify_ternary_operation (code, mode, GET_MODE (XEXP (x, 0)),
04091 XEXP (x, 0), XEXP (x, 1),
04092 XEXP (x, 2));
04093
04094 case RTX_COMPARE:
04095 case RTX_COMM_COMPARE:
04096 return simplify_relational_operation (code, mode,
04097 ((GET_MODE (XEXP (x, 0))
04098 != VOIDmode)
04099 ? GET_MODE (XEXP (x, 0))
04100 : GET_MODE (XEXP (x, 1))),
04101 XEXP (x, 0),
04102 XEXP (x, 1));
04103
04104 case RTX_EXTRA:
04105 if (code == SUBREG)
04106 return simplify_gen_subreg (mode, SUBREG_REG (x),
04107 GET_MODE (SUBREG_REG (x)),
04108 SUBREG_BYTE (x));
04109 break;
04110
04111 case RTX_OBJ:
04112 if (code == LO_SUM)
04113 {
04114
04115 if (GET_CODE (XEXP (x, 0)) == HIGH
04116 && rtx_equal_p (XEXP (XEXP (x, 0), 0), XEXP (x, 1)))
04117 return XEXP (x, 1);
04118 }
04119 break;
04120
04121 default:
04122 break;
04123 }
04124 return NULL;
04125 }