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 "rtl.h"
00026 #include "tree.h"
00027 #include "tm_p.h"
00028 #include "regs.h"
00029 #include "hard-reg-set.h"
00030 #include "flags.h"
00031 #include "real.h"
00032 #include "insn-config.h"
00033 #include "recog.h"
00034 #include "function.h"
00035 #include "expr.h"
00036 #include "toplev.h"
00037 #include "output.h"
00038 #include "ggc.h"
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057 #define NONZERO_BASE_PLUS_P(X) \
00058 ((X) == frame_pointer_rtx || (X) == hard_frame_pointer_rtx \
00059 || (X) == virtual_stack_vars_rtx \
00060 || (X) == virtual_incoming_args_rtx \
00061 || (GET_CODE (X) == PLUS && GET_CODE (XEXP (X, 1)) == CONST_INT \
00062 && (XEXP (X, 0) == frame_pointer_rtx \
00063 || XEXP (X, 0) == hard_frame_pointer_rtx \
00064 || ((X) == arg_pointer_rtx \
00065 && fixed_regs[ARG_POINTER_REGNUM]) \
00066 || XEXP (X, 0) == virtual_stack_vars_rtx \
00067 || XEXP (X, 0) == virtual_incoming_args_rtx)) \
00068 || (X) == stack_pointer_rtx \
00069 || (X) == virtual_stack_dynamic_rtx \
00070 || (X) == virtual_outgoing_args_rtx \
00071 || (GET_CODE (X) == PLUS && GET_CODE (XEXP (X, 1)) == CONST_INT \
00072 && (XEXP (X, 0) == stack_pointer_rtx \
00073 || XEXP (X, 0) == virtual_stack_dynamic_rtx \
00074 || XEXP (X, 0) == virtual_outgoing_args_rtx)) \
00075 || GET_CODE (X) == ADDRESSOF)
00076
00077
00078
00079
00080
00081 #define HWI_SIGN_EXTEND(low) \
00082 ((((HOST_WIDE_INT) low) < 0) ? ((HOST_WIDE_INT) -1) : ((HOST_WIDE_INT) 0))
00083
00084 static rtx neg_const_int PARAMS ((enum machine_mode, rtx));
00085 static int simplify_plus_minus_op_data_cmp PARAMS ((const void *,
00086 const void *));
00087 static rtx simplify_plus_minus PARAMS ((enum rtx_code,
00088 enum machine_mode, rtx,
00089 rtx, int));
00090
00091
00092
00093 static rtx
00094 neg_const_int (mode, i)
00095 enum machine_mode mode;
00096 rtx i;
00097 {
00098 return gen_int_mode (- INTVAL (i), mode);
00099 }
00100
00101
00102
00103
00104
00105 rtx
00106 simplify_gen_binary (code, mode, op0, op1)
00107 enum rtx_code code;
00108 enum machine_mode mode;
00109 rtx op0, op1;
00110 {
00111 rtx tem;
00112
00113
00114 if (GET_RTX_CLASS (code) == 'c'
00115 && swap_commutative_operands_p (op0, op1))
00116 tem = op0, op0 = op1, op1 = tem;
00117
00118
00119 tem = simplify_binary_operation (code, mode, op0, op1);
00120 if (tem)
00121 return tem;
00122
00123
00124
00125
00126 if (code == PLUS || code == MINUS)
00127 {
00128 tem = simplify_plus_minus (code, mode, op0, op1, 1);
00129 if (tem)
00130 return tem;
00131 }
00132
00133 return gen_rtx_fmt_ee (code, mode, op0, op1);
00134 }
00135
00136
00137
00138 rtx
00139 avoid_constant_pool_reference (x)
00140 rtx x;
00141 {
00142 rtx c, addr;
00143 enum machine_mode cmode;
00144
00145 if (GET_CODE (x) != MEM)
00146 return x;
00147 addr = XEXP (x, 0);
00148
00149 if (GET_CODE (addr) == LO_SUM)
00150 addr = XEXP (addr, 1);
00151
00152 if (GET_CODE (addr) != SYMBOL_REF
00153 || ! CONSTANT_POOL_ADDRESS_P (addr))
00154 return x;
00155
00156 c = get_pool_constant (addr);
00157 cmode = get_pool_mode (addr);
00158
00159
00160
00161
00162 if (cmode != GET_MODE (x))
00163 {
00164 c = simplify_subreg (GET_MODE (x), c, cmode, 0);
00165 return c ? c : x;
00166 }
00167
00168 return c;
00169 }
00170
00171
00172
00173
00174 rtx
00175 simplify_gen_unary (code, mode, op, op_mode)
00176 enum rtx_code code;
00177 enum machine_mode mode;
00178 rtx op;
00179 enum machine_mode op_mode;
00180 {
00181 rtx tem;
00182
00183
00184 if ((tem = simplify_unary_operation (code, mode, op, op_mode)) != 0)
00185 return tem;
00186
00187 return gen_rtx_fmt_e (code, mode, op);
00188 }
00189
00190
00191
00192 rtx
00193 simplify_gen_ternary (code, mode, op0_mode, op0, op1, op2)
00194 enum rtx_code code;
00195 enum machine_mode mode, op0_mode;
00196 rtx op0, op1, op2;
00197 {
00198 rtx tem;
00199
00200
00201 if (0 != (tem = simplify_ternary_operation (code, mode, op0_mode,
00202 op0, op1, op2)))
00203 return tem;
00204
00205 return gen_rtx_fmt_eee (code, mode, op0, op1, op2);
00206 }
00207
00208
00209
00210
00211
00212 rtx
00213 simplify_gen_relational (code, mode, cmp_mode, op0, op1)
00214 enum rtx_code code;
00215 enum machine_mode mode;
00216 enum machine_mode cmp_mode;
00217 rtx op0, op1;
00218 {
00219 rtx tem;
00220
00221 if ((tem = simplify_relational_operation (code, cmp_mode, op0, op1)) != 0)
00222 return tem;
00223
00224
00225 if (op0 == const0_rtx && swap_commutative_operands_p (op0, op1))
00226 tem = op0, op0 = op1, op1 = tem, code = swap_condition (code);
00227
00228
00229 if (GET_CODE (op0) == COMPARE && op1 == const0_rtx)
00230 op1 = XEXP (op0, 1), op0 = XEXP (op0, 0);
00231
00232
00233 if (code == NE && op1 == const0_rtx
00234 && GET_RTX_CLASS (GET_CODE (op0)) == '<')
00235 return op0;
00236 else if (code == EQ && op1 == const0_rtx)
00237 {
00238
00239 enum rtx_code new = reversed_comparison_code (op0, NULL_RTX);
00240 if (new != UNKNOWN)
00241 {
00242 code = new;
00243 mode = cmp_mode;
00244 op1 = XEXP (op0, 1);
00245 op0 = XEXP (op0, 0);
00246 }
00247 }
00248
00249
00250 if (swap_commutative_operands_p (op0, op1))
00251 tem = op0, op0 = op1, op1 = tem, code = swap_condition (code);
00252
00253 return gen_rtx_fmt_ee (code, mode, op0, op1);
00254 }
00255
00256
00257
00258
00259 rtx
00260 simplify_replace_rtx (x, old, new)
00261 rtx x;
00262 rtx old;
00263 rtx new;
00264 {
00265 enum rtx_code code = GET_CODE (x);
00266 enum machine_mode mode = GET_MODE (x);
00267
00268
00269
00270
00271
00272 if (x == old)
00273 return new;
00274
00275 switch (GET_RTX_CLASS (code))
00276 {
00277 case '1':
00278 {
00279 enum machine_mode op_mode = GET_MODE (XEXP (x, 0));
00280 rtx op = (XEXP (x, 0) == old
00281 ? new : simplify_replace_rtx (XEXP (x, 0), old, new));
00282
00283 return simplify_gen_unary (code, mode, op, op_mode);
00284 }
00285
00286 case '2':
00287 case 'c':
00288 return
00289 simplify_gen_binary (code, mode,
00290 simplify_replace_rtx (XEXP (x, 0), old, new),
00291 simplify_replace_rtx (XEXP (x, 1), old, new));
00292 case '<':
00293 {
00294 enum machine_mode op_mode = (GET_MODE (XEXP (x, 0)) != VOIDmode
00295 ? GET_MODE (XEXP (x, 0))
00296 : GET_MODE (XEXP (x, 1)));
00297 rtx op0 = simplify_replace_rtx (XEXP (x, 0), old, new);
00298 rtx op1 = simplify_replace_rtx (XEXP (x, 1), old, new);
00299
00300 return
00301 simplify_gen_relational (code, mode,
00302 (op_mode != VOIDmode
00303 ? op_mode
00304 : GET_MODE (op0) != VOIDmode
00305 ? GET_MODE (op0)
00306 : GET_MODE (op1)),
00307 op0, op1);
00308 }
00309
00310 case '3':
00311 case 'b':
00312 {
00313 enum machine_mode op_mode = GET_MODE (XEXP (x, 0));
00314 rtx op0 = simplify_replace_rtx (XEXP (x, 0), old, new);
00315
00316 return
00317 simplify_gen_ternary (code, mode,
00318 (op_mode != VOIDmode
00319 ? op_mode
00320 : GET_MODE (op0)),
00321 op0,
00322 simplify_replace_rtx (XEXP (x, 1), old, new),
00323 simplify_replace_rtx (XEXP (x, 2), old, new));
00324 }
00325
00326 case 'x':
00327
00328 if (code == SUBREG)
00329 {
00330 rtx exp;
00331 exp = simplify_gen_subreg (GET_MODE (x),
00332 simplify_replace_rtx (SUBREG_REG (x),
00333 old, new),
00334 GET_MODE (SUBREG_REG (x)),
00335 SUBREG_BYTE (x));
00336 if (exp)
00337 x = exp;
00338 }
00339 return x;
00340
00341 case 'o':
00342 if (code == MEM)
00343 return replace_equiv_address_nv (x,
00344 simplify_replace_rtx (XEXP (x, 0),
00345 old, new));
00346 else if (code == LO_SUM)
00347 {
00348 rtx op0 = simplify_replace_rtx (XEXP (x, 0), old, new);
00349 rtx op1 = simplify_replace_rtx (XEXP (x, 1), old, new);
00350
00351
00352 if (GET_CODE (op0) == HIGH && rtx_equal_p (XEXP (op0, 0), op1))
00353 return op1;
00354
00355 return gen_rtx_LO_SUM (mode, op0, op1);
00356 }
00357 else if (code == REG)
00358 {
00359 if (REG_P (old) && REGNO (x) == REGNO (old))
00360 return new;
00361 }
00362
00363 return x;
00364
00365 default:
00366 return x;
00367 }
00368 return x;
00369 }
00370
00371
00372
00373
00374 rtx
00375 simplify_unary_operation (code, mode, op, op_mode)
00376 enum rtx_code code;
00377 enum machine_mode mode;
00378 rtx op;
00379 enum machine_mode op_mode;
00380 {
00381 unsigned int width = GET_MODE_BITSIZE (mode);
00382 rtx trueop = avoid_constant_pool_reference (op);
00383
00384 if (code == VEC_DUPLICATE)
00385 {
00386 if (!VECTOR_MODE_P (mode))
00387 abort ();
00388 if (GET_MODE (trueop) != VOIDmode
00389 && !VECTOR_MODE_P (GET_MODE (trueop))
00390 && GET_MODE_INNER (mode) != GET_MODE (trueop))
00391 abort ();
00392 if (GET_MODE (trueop) != VOIDmode
00393 && VECTOR_MODE_P (GET_MODE (trueop))
00394 && GET_MODE_INNER (mode) != GET_MODE_INNER (GET_MODE (trueop)))
00395 abort ();
00396 if (GET_CODE (trueop) == CONST_INT || GET_CODE (trueop) == CONST_DOUBLE
00397 || GET_CODE (trueop) == CONST_VECTOR)
00398 {
00399 int elt_size = GET_MODE_SIZE (GET_MODE_INNER (mode));
00400 unsigned n_elts = (GET_MODE_SIZE (mode) / elt_size);
00401 rtvec v = rtvec_alloc (n_elts);
00402 unsigned int i;
00403
00404 if (GET_CODE (trueop) != CONST_VECTOR)
00405 for (i = 0; i < n_elts; i++)
00406 RTVEC_ELT (v, i) = trueop;
00407 else
00408 {
00409 enum machine_mode inmode = GET_MODE (trueop);
00410 int in_elt_size = GET_MODE_SIZE (GET_MODE_INNER (inmode));
00411 unsigned in_n_elts = (GET_MODE_SIZE (inmode) / in_elt_size);
00412
00413 if (in_n_elts >= n_elts || n_elts % in_n_elts)
00414 abort ();
00415 for (i = 0; i < n_elts; i++)
00416 RTVEC_ELT (v, i) = CONST_VECTOR_ELT (trueop, i % in_n_elts);
00417 }
00418 return gen_rtx_CONST_VECTOR (mode, v);
00419 }
00420 }
00421
00422
00423
00424
00425
00426 if (code == FLOAT && GET_MODE (trueop) == VOIDmode
00427 && (GET_CODE (trueop) == CONST_DOUBLE || GET_CODE (trueop) == CONST_INT))
00428 {
00429 HOST_WIDE_INT hv, lv;
00430 REAL_VALUE_TYPE d;
00431
00432 if (GET_CODE (trueop) == CONST_INT)
00433 lv = INTVAL (trueop), hv = HWI_SIGN_EXTEND (lv);
00434 else
00435 lv = CONST_DOUBLE_LOW (trueop), hv = CONST_DOUBLE_HIGH (trueop);
00436
00437 REAL_VALUE_FROM_INT (d, lv, hv, mode);
00438 d = real_value_truncate (mode, d);
00439 return CONST_DOUBLE_FROM_REAL_VALUE (d, mode);
00440 }
00441 else if (code == UNSIGNED_FLOAT && GET_MODE (trueop) == VOIDmode
00442 && (GET_CODE (trueop) == CONST_DOUBLE
00443 || GET_CODE (trueop) == CONST_INT))
00444 {
00445 HOST_WIDE_INT hv, lv;
00446 REAL_VALUE_TYPE d;
00447
00448 if (GET_CODE (trueop) == CONST_INT)
00449 lv = INTVAL (trueop), hv = HWI_SIGN_EXTEND (lv);
00450 else
00451 lv = CONST_DOUBLE_LOW (trueop), hv = CONST_DOUBLE_HIGH (trueop);
00452
00453 if (op_mode == VOIDmode)
00454 {
00455
00456
00457 if (hv < 0)
00458 return 0;
00459 }
00460 else if (GET_MODE_BITSIZE (op_mode) >= HOST_BITS_PER_WIDE_INT * 2)
00461 ;
00462 else
00463 hv = 0, lv &= GET_MODE_MASK (op_mode);
00464
00465 REAL_VALUE_FROM_UNSIGNED_INT (d, lv, hv, mode);
00466 d = real_value_truncate (mode, d);
00467 return CONST_DOUBLE_FROM_REAL_VALUE (d, mode);
00468 }
00469
00470 if (GET_CODE (trueop) == CONST_INT
00471 && width <= HOST_BITS_PER_WIDE_INT && width > 0)
00472 {
00473 HOST_WIDE_INT arg0 = INTVAL (trueop);
00474 HOST_WIDE_INT val;
00475
00476 switch (code)
00477 {
00478 case NOT:
00479 val = ~ arg0;
00480 break;
00481
00482 case NEG:
00483 val = - arg0;
00484 break;
00485
00486 case ABS:
00487 val = (arg0 >= 0 ? arg0 : - arg0);
00488 break;
00489
00490 case FFS:
00491
00492
00493 arg0 &= GET_MODE_MASK (mode);
00494 val = exact_log2 (arg0 & (- arg0)) + 1;
00495 break;
00496
00497 case TRUNCATE:
00498 val = arg0;
00499 break;
00500
00501 case ZERO_EXTEND:
00502
00503
00504 if (op_mode == VOIDmode)
00505 abort ();
00506 if (GET_MODE_BITSIZE (op_mode) == HOST_BITS_PER_WIDE_INT)
00507 {
00508
00509
00510
00511 if (width != GET_MODE_BITSIZE (op_mode))
00512 abort ();
00513 val = arg0;
00514 }
00515 else if (GET_MODE_BITSIZE (op_mode) < HOST_BITS_PER_WIDE_INT)
00516 val = arg0 & ~((HOST_WIDE_INT) (-1) << GET_MODE_BITSIZE (op_mode));
00517 else
00518 return 0;
00519 break;
00520
00521 case SIGN_EXTEND:
00522 if (op_mode == VOIDmode)
00523 op_mode = mode;
00524 if (GET_MODE_BITSIZE (op_mode) == HOST_BITS_PER_WIDE_INT)
00525 {
00526
00527
00528
00529 if (width != GET_MODE_BITSIZE (op_mode))
00530 abort ();
00531 val = arg0;
00532 }
00533 else if (GET_MODE_BITSIZE (op_mode) < HOST_BITS_PER_WIDE_INT)
00534 {
00535 val
00536 = arg0 & ~((HOST_WIDE_INT) (-1) << GET_MODE_BITSIZE (op_mode));
00537 if (val
00538 & ((HOST_WIDE_INT) 1 << (GET_MODE_BITSIZE (op_mode) - 1)))
00539 val -= (HOST_WIDE_INT) 1 << GET_MODE_BITSIZE (op_mode);
00540 }
00541 else
00542 return 0;
00543 break;
00544
00545 case SQRT:
00546 case FLOAT_EXTEND:
00547 case FLOAT_TRUNCATE:
00548 case SS_TRUNCATE:
00549 case US_TRUNCATE:
00550 return 0;
00551
00552 default:
00553 abort ();
00554 }
00555
00556 val = trunc_int_for_mode (val, mode);
00557
00558 return GEN_INT (val);
00559 }
00560
00561
00562
00563 else if (GET_MODE (trueop) == VOIDmode
00564 && width <= HOST_BITS_PER_WIDE_INT * 2
00565 && (GET_CODE (trueop) == CONST_DOUBLE
00566 || GET_CODE (trueop) == CONST_INT))
00567 {
00568 unsigned HOST_WIDE_INT l1, lv;
00569 HOST_WIDE_INT h1, hv;
00570
00571 if (GET_CODE (trueop) == CONST_DOUBLE)
00572 l1 = CONST_DOUBLE_LOW (trueop), h1 = CONST_DOUBLE_HIGH (trueop);
00573 else
00574 l1 = INTVAL (trueop), h1 = HWI_SIGN_EXTEND (l1);
00575
00576 switch (code)
00577 {
00578 case NOT:
00579 lv = ~ l1;
00580 hv = ~ h1;
00581 break;
00582
00583 case NEG:
00584 neg_double (l1, h1, &lv, &hv);
00585 break;
00586
00587 case ABS:
00588 if (h1 < 0)
00589 neg_double (l1, h1, &lv, &hv);
00590 else
00591 lv = l1, hv = h1;
00592 break;
00593
00594 case FFS:
00595 hv = 0;
00596 if (l1 == 0)
00597 lv = HOST_BITS_PER_WIDE_INT + exact_log2 (h1 & (-h1)) + 1;
00598 else
00599 lv = exact_log2 (l1 & (-l1)) + 1;
00600 break;
00601
00602 case TRUNCATE:
00603
00604 lv = l1, hv = h1;
00605 break;
00606
00607 case ZERO_EXTEND:
00608 if (op_mode == VOIDmode)
00609 abort ();
00610
00611 if (GET_MODE_BITSIZE (op_mode) > HOST_BITS_PER_WIDE_INT)
00612 return 0;
00613
00614 hv = 0;
00615 lv = l1 & GET_MODE_MASK (op_mode);
00616 break;
00617
00618 case SIGN_EXTEND:
00619 if (op_mode == VOIDmode
00620 || GET_MODE_BITSIZE (op_mode) > HOST_BITS_PER_WIDE_INT)
00621 return 0;
00622 else
00623 {
00624 lv = l1 & GET_MODE_MASK (op_mode);
00625 if (GET_MODE_BITSIZE (op_mode) < HOST_BITS_PER_WIDE_INT
00626 && (lv & ((HOST_WIDE_INT) 1
00627 << (GET_MODE_BITSIZE (op_mode) - 1))) != 0)
00628 lv -= (HOST_WIDE_INT) 1 << GET_MODE_BITSIZE (op_mode);
00629
00630 hv = HWI_SIGN_EXTEND (lv);
00631 }
00632 break;
00633
00634 case SQRT:
00635 return 0;
00636
00637 default:
00638 return 0;
00639 }
00640
00641 return immed_double_const (lv, hv, mode);
00642 }
00643
00644 else if (GET_CODE (trueop) == CONST_DOUBLE
00645 && GET_MODE_CLASS (mode) == MODE_FLOAT)
00646 {
00647 REAL_VALUE_TYPE d;
00648 REAL_VALUE_FROM_CONST_DOUBLE (d, trueop);
00649
00650 switch (code)
00651 {
00652 case SQRT:
00653
00654 return 0;
00655
00656 case ABS:
00657 d = REAL_VALUE_ABS (d);
00658 break;
00659 case NEG:
00660 d = REAL_VALUE_NEGATE (d);
00661 break;
00662 case FLOAT_TRUNCATE:
00663 d = real_value_truncate (mode, d);
00664 break;
00665 case FLOAT_EXTEND:
00666
00667 break;
00668 case FIX:
00669 real_arithmetic (&d, FIX_TRUNC_EXPR, &d, NULL);
00670 break;
00671
00672 default:
00673 abort ();
00674 }
00675 return CONST_DOUBLE_FROM_REAL_VALUE (d, mode);
00676 }
00677
00678 else if (GET_CODE (trueop) == CONST_DOUBLE
00679 && GET_MODE_CLASS (GET_MODE (trueop)) == MODE_FLOAT
00680 && GET_MODE_CLASS (mode) == MODE_INT
00681 && width <= HOST_BITS_PER_WIDE_INT && width > 0)
00682 {
00683 HOST_WIDE_INT i;
00684 REAL_VALUE_TYPE d;
00685 REAL_VALUE_FROM_CONST_DOUBLE (d, trueop);
00686 switch (code)
00687 {
00688 case FIX: i = REAL_VALUE_FIX (d); break;
00689 case UNSIGNED_FIX: i = REAL_VALUE_UNSIGNED_FIX (d); break;
00690 default:
00691 abort ();
00692 }
00693 return gen_int_mode (i, mode);
00694 }
00695
00696
00697
00698 else
00699 {
00700 enum rtx_code reversed;
00701
00702
00703 switch (code)
00704 {
00705 case NOT:
00706
00707 if (GET_CODE (op) == NOT)
00708 return XEXP (op, 0);
00709
00710
00711 if (mode == BImode && GET_RTX_CLASS (GET_CODE (op)) == '<'
00712 && ((reversed = reversed_comparison_code (op, NULL_RTX))
00713 != UNKNOWN))
00714 return gen_rtx_fmt_ee (reversed,
00715 op_mode, XEXP (op, 0), XEXP (op, 1));
00716 break;
00717
00718 case NEG:
00719
00720 if (GET_CODE (op) == NEG)
00721 return XEXP (op, 0);
00722 break;
00723
00724 case SIGN_EXTEND:
00725
00726
00727
00728
00729 if (GET_CODE (op) == TRUNCATE
00730 && GET_MODE (XEXP (op, 0)) == mode
00731 && GET_CODE (XEXP (op, 0)) == MINUS
00732 && GET_CODE (XEXP (XEXP (op, 0), 0)) == LABEL_REF
00733 && GET_CODE (XEXP (XEXP (op, 0), 1)) == LABEL_REF)
00734 return XEXP (op, 0);
00735
00736 #if defined(POINTERS_EXTEND_UNSIGNED) && !defined(HAVE_ptr_extend)
00737 if (! POINTERS_EXTEND_UNSIGNED
00738 && mode == Pmode && GET_MODE (op) == ptr_mode
00739 && (CONSTANT_P (op)
00740 || (GET_CODE (op) == SUBREG
00741 && GET_CODE (SUBREG_REG (op)) == REG
00742 && REG_POINTER (SUBREG_REG (op))
00743 && GET_MODE (SUBREG_REG (op)) == Pmode)))
00744 return convert_memory_address (Pmode, op);
00745 #endif
00746 break;
00747
00748 #if defined(POINTERS_EXTEND_UNSIGNED) && !defined(HAVE_ptr_extend)
00749 case ZERO_EXTEND:
00750 if (POINTERS_EXTEND_UNSIGNED > 0
00751 && mode == Pmode && GET_MODE (op) == ptr_mode
00752 && (CONSTANT_P (op)
00753 || (GET_CODE (op) == SUBREG
00754 && GET_CODE (SUBREG_REG (op)) == REG
00755 && REG_POINTER (SUBREG_REG (op))
00756 && GET_MODE (SUBREG_REG (op)) == Pmode)))
00757 return convert_memory_address (Pmode, op);
00758 break;
00759 #endif
00760
00761 default:
00762 break;
00763 }
00764
00765 return 0;
00766 }
00767 }
00768
00769
00770
00771
00772
00773
00774 rtx
00775 simplify_binary_operation (code, mode, op0, op1)
00776 enum rtx_code code;
00777 enum machine_mode mode;
00778 rtx op0, op1;
00779 {
00780 HOST_WIDE_INT arg0, arg1, arg0s, arg1s;
00781 HOST_WIDE_INT val;
00782 unsigned int width = GET_MODE_BITSIZE (mode);
00783 rtx tem;
00784 rtx trueop0 = avoid_constant_pool_reference (op0);
00785 rtx trueop1 = avoid_constant_pool_reference (op1);
00786
00787
00788
00789
00790
00791
00792 if (GET_RTX_CLASS (code) == '<')
00793 abort ();
00794
00795
00796 if (GET_RTX_CLASS (code) == 'c'
00797 && swap_commutative_operands_p (trueop0, trueop1))
00798 {
00799 tem = op0, op0 = op1, op1 = tem;
00800 tem = trueop0, trueop0 = trueop1, trueop1 = tem;
00801 }
00802
00803 if (GET_MODE_CLASS (mode) == MODE_FLOAT
00804 && GET_CODE (trueop0) == CONST_DOUBLE
00805 && GET_CODE (trueop1) == CONST_DOUBLE
00806 && mode == GET_MODE (op0) && mode == GET_MODE (op1))
00807 {
00808 REAL_VALUE_TYPE f0, f1, value;
00809
00810 REAL_VALUE_FROM_CONST_DOUBLE (f0, trueop0);
00811 REAL_VALUE_FROM_CONST_DOUBLE (f1, trueop1);
00812 f0 = real_value_truncate (mode, f0);
00813 f1 = real_value_truncate (mode, f1);
00814
00815 if (code == DIV
00816 && !MODE_HAS_INFINITIES (mode)
00817 && REAL_VALUES_EQUAL (f1, dconst0))
00818 return 0;
00819
00820 REAL_ARITHMETIC (value, rtx_to_tree_code (code), f0, f1);
00821
00822 value = real_value_truncate (mode, value);
00823 return CONST_DOUBLE_FROM_REAL_VALUE (value, mode);
00824 }
00825
00826
00827 if (GET_MODE_CLASS (mode) == MODE_INT
00828 && width == HOST_BITS_PER_WIDE_INT * 2
00829 && (GET_CODE (trueop0) == CONST_DOUBLE
00830 || GET_CODE (trueop0) == CONST_INT)
00831 && (GET_CODE (trueop1) == CONST_DOUBLE
00832 || GET_CODE (trueop1) == CONST_INT))
00833 {
00834 unsigned HOST_WIDE_INT l1, l2, lv;
00835 HOST_WIDE_INT h1, h2, hv;
00836
00837 if (GET_CODE (trueop0) == CONST_DOUBLE)
00838 l1 = CONST_DOUBLE_LOW (trueop0), h1 = CONST_DOUBLE_HIGH (trueop0);
00839 else
00840 l1 = INTVAL (trueop0), h1 = HWI_SIGN_EXTEND (l1);
00841
00842 if (GET_CODE (trueop1) == CONST_DOUBLE)
00843 l2 = CONST_DOUBLE_LOW (trueop1), h2 = CONST_DOUBLE_HIGH (trueop1);
00844 else
00845 l2 = INTVAL (trueop1), h2 = HWI_SIGN_EXTEND (l2);
00846
00847 switch (code)
00848 {
00849 case MINUS:
00850
00851 neg_double (l2, h2, &lv, &hv);
00852 l2 = lv, h2 = hv;
00853
00854
00855
00856 case PLUS:
00857 add_double (l1, h1, l2, h2, &lv, &hv);
00858 break;
00859
00860 case MULT:
00861 mul_double (l1, h1, l2, h2, &lv, &hv);
00862 break;
00863
00864 case DIV: case MOD: case UDIV: case UMOD:
00865
00866
00867 return 0;
00868
00869 case AND:
00870 lv = l1 & l2, hv = h1 & h2;
00871 break;
00872
00873 case IOR:
00874 lv = l1 | l2, hv = h1 | h2;
00875 break;
00876
00877 case XOR:
00878 lv = l1 ^ l2, hv = h1 ^ h2;
00879 break;
00880
00881 case SMIN:
00882 if (h1 < h2
00883 || (h1 == h2
00884 && ((unsigned HOST_WIDE_INT) l1
00885 < (unsigned HOST_WIDE_INT) l2)))
00886 lv = l1, hv = h1;
00887 else
00888 lv = l2, hv = h2;
00889 break;
00890
00891 case SMAX:
00892 if (h1 > h2
00893 || (h1 == h2
00894 && ((unsigned HOST_WIDE_INT) l1
00895 > (unsigned HOST_WIDE_INT) l2)))
00896 lv = l1, hv = h1;
00897 else
00898 lv = l2, hv = h2;
00899 break;
00900
00901 case UMIN:
00902 if ((unsigned HOST_WIDE_INT) h1 < (unsigned HOST_WIDE_INT) h2
00903 || (h1 == h2
00904 && ((unsigned HOST_WIDE_INT) l1
00905 < (unsigned HOST_WIDE_INT) l2)))
00906 lv = l1, hv = h1;
00907 else
00908 lv = l2, hv = h2;
00909 break;
00910
00911 case UMAX:
00912 if ((unsigned HOST_WIDE_INT) h1 > (unsigned HOST_WIDE_INT) h2
00913 || (h1 == h2
00914 && ((unsigned HOST_WIDE_INT) l1
00915 > (unsigned HOST_WIDE_INT) l2)))
00916 lv = l1, hv = h1;
00917 else
00918 lv = l2, hv = h2;
00919 break;
00920
00921 case LSHIFTRT: case ASHIFTRT:
00922 case ASHIFT:
00923 case ROTATE: case ROTATERT:
00924 #ifdef SHIFT_COUNT_TRUNCATED
00925 if (SHIFT_COUNT_TRUNCATED)
00926 l2 &= (GET_MODE_BITSIZE (mode) - 1), h2 = 0;
00927 #endif
00928
00929 if (h2 != 0 || l2 >= GET_MODE_BITSIZE (mode))
00930 return 0;
00931
00932 if (code == LSHIFTRT || code == ASHIFTRT)
00933 rshift_double (l1, h1, l2, GET_MODE_BITSIZE (mode), &lv, &hv,
00934 code == ASHIFTRT);
00935 else if (code == ASHIFT)
00936 lshift_double (l1, h1, l2, GET_MODE_BITSIZE (mode), &lv, &hv, 1);
00937 else if (code == ROTATE)
00938 lrotate_double (l1, h1, l2, GET_MODE_BITSIZE (mode), &lv, &hv);
00939 else
00940 rrotate_double (l1, h1, l2, GET_MODE_BITSIZE (mode), &lv, &hv);
00941 break;
00942
00943 default:
00944 return 0;
00945 }
00946
00947 return immed_double_const (lv, hv, mode);
00948 }
00949
00950 if (GET_CODE (op0) != CONST_INT || GET_CODE (op1) != CONST_INT
00951 || width > HOST_BITS_PER_WIDE_INT || width == 0)
00952 {
00953
00954
00955
00956 switch (code)
00957 {
00958 case PLUS:
00959
00960
00961
00962
00963 if (!HONOR_SIGNED_ZEROS (mode) && trueop1 == CONST0_RTX (mode))
00964 return op0;
00965
00966
00967
00968 if (GET_CODE (op0) == NEG)
00969 return simplify_gen_binary (MINUS, mode, op1, XEXP (op0, 0));
00970 else if (GET_CODE (op1) == NEG)
00971 return simplify_gen_binary (MINUS, mode, op0, XEXP (op1, 0));
00972
00973
00974 if (INTEGRAL_MODE_P (mode)
00975 && GET_CODE (op0) == NOT
00976 && trueop1 == const1_rtx)
00977 return gen_rtx_NEG (mode, XEXP (op0, 0));
00978
00979
00980
00981
00982
00983
00984
00985 if (CONSTANT_P (op0) && GET_MODE (op0) != VOIDmode
00986 && GET_CODE (op1) == CONST_INT)
00987 return plus_constant (op0, INTVAL (op1));
00988 else if (CONSTANT_P (op1) && GET_MODE (op1) != VOIDmode
00989 && GET_CODE (op0) == CONST_INT)
00990 return plus_constant (op1, INTVAL (op0));
00991
00992
00993
00994
00995
00996
00997
00998 if (! FLOAT_MODE_P (mode))
00999 {
01000 HOST_WIDE_INT coeff0 = 1, coeff1 = 1;
01001 rtx lhs = op0, rhs = op1;
01002 int had_mult = 0;
01003
01004 if (GET_CODE (lhs) == NEG)
01005 coeff0 = -1, lhs = XEXP (lhs, 0);
01006 else if (GET_CODE (lhs) == MULT
01007 && GET_CODE (XEXP (lhs, 1)) == CONST_INT)
01008 {
01009 coeff0 = INTVAL (XEXP (lhs, 1)), lhs = XEXP (lhs, 0);
01010 had_mult = 1;
01011 }
01012 else if (GET_CODE (lhs) == ASHIFT
01013 && GET_CODE (XEXP (lhs, 1)) == CONST_INT
01014 && INTVAL (XEXP (lhs, 1)) >= 0
01015 && INTVAL (XEXP (lhs, 1)) < HOST_BITS_PER_WIDE_INT)
01016 {
01017 coeff0 = ((HOST_WIDE_INT) 1) << INTVAL (XEXP (lhs, 1));
01018 lhs = XEXP (lhs, 0);
01019 }
01020
01021 if (GET_CODE (rhs) == NEG)
01022 coeff1 = -1, rhs = XEXP (rhs, 0);
01023 else if (GET_CODE (rhs) == MULT
01024 && GET_CODE (XEXP (rhs, 1)) == CONST_INT)
01025 {
01026 coeff1 = INTVAL (XEXP (rhs, 1)), rhs = XEXP (rhs, 0);
01027 had_mult = 1;
01028 }
01029 else if (GET_CODE (rhs) == ASHIFT
01030 && GET_CODE (XEXP (rhs, 1)) == CONST_INT
01031 && INTVAL (XEXP (rhs, 1)) >= 0
01032 && INTVAL (XEXP (rhs, 1)) < HOST_BITS_PER_WIDE_INT)
01033 {
01034 coeff1 = ((HOST_WIDE_INT) 1) << INTVAL (XEXP (rhs, 1));
01035 rhs = XEXP (rhs, 0);
01036 }
01037
01038 if (rtx_equal_p (lhs, rhs))
01039 {
01040 tem = simplify_gen_binary (MULT, mode, lhs,
01041 GEN_INT (coeff0 + coeff1));
01042 return (GET_CODE (tem) == MULT && ! had_mult) ? 0 : tem;
01043 }
01044 }
01045
01046
01047
01048
01049
01050
01051
01052 if (INTEGRAL_MODE_P (mode)
01053 && (GET_CODE (op0) == PLUS || GET_CODE (op0) == MINUS
01054 || GET_CODE (op1) == PLUS || GET_CODE (op1) == MINUS
01055 || (GET_CODE (op0) == CONST
01056 && GET_CODE (XEXP (op0, 0)) == PLUS)
01057 || (GET_CODE (op1) == CONST
01058 && GET_CODE (XEXP (op1, 0)) == PLUS))
01059 && (tem = simplify_plus_minus (code, mode, op0, op1, 0)) != 0)
01060 return tem;
01061 break;
01062
01063 case COMPARE:
01064 #ifdef HAVE_cc0
01065
01066
01067
01068
01069
01070
01071 if ((TARGET_FLOAT_FORMAT != IEEE_FLOAT_FORMAT
01072 || ! FLOAT_MODE_P (mode) || flag_unsafe_math_optimizations)
01073 && trueop1 == CONST0_RTX (mode))
01074 return op0;
01075 #endif
01076
01077
01078 if (((GET_CODE (op0) == GT && GET_CODE (op1) == LT)
01079 || (GET_CODE (op0) == GTU && GET_CODE (op1) == LTU))
01080 && XEXP (op0, 1) == const0_rtx && XEXP (op1, 1) == const0_rtx)
01081 {
01082 rtx xop00 = XEXP (op0, 0);
01083 rtx xop10 = XEXP (op1, 0);
01084
01085 #ifdef HAVE_cc0
01086 if (GET_CODE (xop00) == CC0 && GET_CODE (xop10) == CC0)
01087 #else
01088 if (GET_CODE (xop00) == REG && GET_CODE (xop10) == REG
01089 && GET_MODE (xop00) == GET_MODE (xop10)
01090 && REGNO (xop00) == REGNO (xop10)
01091 && GET_MODE_CLASS (GET_MODE (xop00)) == MODE_CC
01092 && GET_MODE_CLASS (GET_MODE (xop10)) == MODE_CC)
01093 #endif
01094 return xop00;
01095 }
01096 break;
01097
01098 case MINUS:
01099
01100
01101
01102 if (rtx_equal_p (trueop0, trueop1)
01103 && ! side_effects_p (op0)
01104 && (! FLOAT_MODE_P (mode) || flag_unsafe_math_optimizations))
01105 return CONST0_RTX (mode);
01106
01107
01108
01109
01110
01111 if (!HONOR_SIGNED_ZEROS (mode) && trueop0 == CONST0_RTX (mode))
01112 return gen_rtx_NEG (mode, op1);
01113
01114
01115 if (trueop0 == constm1_rtx)
01116 return gen_rtx_NOT (mode, op1);
01117
01118
01119
01120
01121 if (!(HONOR_SIGNED_ZEROS (mode)
01122 && HONOR_SIGN_DEPENDENT_ROUNDING (mode))
01123 && trueop1 == CONST0_RTX (mode))
01124 return op0;
01125
01126
01127
01128
01129
01130
01131
01132 if (! FLOAT_MODE_P (mode))
01133 {
01134 HOST_WIDE_INT coeff0 = 1, coeff1 = 1;
01135 rtx lhs = op0, rhs = op1;
01136 int had_mult = 0;
01137
01138 if (GET_CODE (lhs) == NEG)
01139 coeff0 = -1, lhs = XEXP (lhs, 0);
01140 else if (GET_CODE (lhs) == MULT
01141 && GET_CODE (XEXP (lhs, 1)) == CONST_INT)
01142 {
01143 coeff0 = INTVAL (XEXP (lhs, 1)), lhs = XEXP (lhs, 0);
01144 had_mult = 1;
01145 }
01146 else if (GET_CODE (lhs) == ASHIFT
01147 && GET_CODE (XEXP (lhs, 1)) == CONST_INT
01148 && INTVAL (XEXP (lhs, 1)) >= 0
01149 && INTVAL (XEXP (lhs, 1)) < HOST_BITS_PER_WIDE_INT)
01150 {
01151 coeff0 = ((HOST_WIDE_INT) 1) << INTVAL (XEXP (lhs, 1));
01152 lhs = XEXP (lhs, 0);
01153 }
01154
01155 if (GET_CODE (rhs) == NEG)
01156 coeff1 = - 1, rhs = XEXP (rhs, 0);
01157 else if (GET_CODE (rhs) == MULT
01158 && GET_CODE (XEXP (rhs, 1)) == CONST_INT)
01159 {
01160 coeff1 = INTVAL (XEXP (rhs, 1)), rhs = XEXP (rhs, 0);
01161 had_mult = 1;
01162 }
01163 else if (GET_CODE (rhs) == ASHIFT
01164 && GET_CODE (XEXP (rhs, 1)) == CONST_INT
01165 && INTVAL (XEXP (rhs, 1)) >= 0
01166 && INTVAL (XEXP (rhs, 1)) < HOST_BITS_PER_WIDE_INT)
01167 {
01168 coeff1 = ((HOST_WIDE_INT) 1) << INTVAL (XEXP (rhs, 1));
01169 rhs = XEXP (rhs, 0);
01170 }
01171
01172 if (rtx_equal_p (lhs, rhs))
01173 {
01174 tem = simplify_gen_binary (MULT, mode, lhs,
01175 GEN_INT (coeff0 - coeff1));
01176 return (GET_CODE (tem) == MULT && ! had_mult) ? 0 : tem;
01177 }
01178 }
01179
01180
01181 if (GET_CODE (op1) == NEG)
01182 return simplify_gen_binary (PLUS, mode, op0, XEXP (op1, 0));
01183
01184
01185
01186
01187
01188
01189
01190 if (INTEGRAL_MODE_P (mode)
01191 && (GET_CODE (op0) == PLUS || GET_CODE (op0) == MINUS
01192 || GET_CODE (op1) == PLUS || GET_CODE (op1) == MINUS
01193 || (GET_CODE (op0) == CONST
01194 && GET_CODE (XEXP (op0, 0)) == PLUS)
01195 || (GET_CODE (op1) == CONST
01196 && GET_CODE (XEXP (op1, 0)) == PLUS))
01197 && (tem = simplify_plus_minus (code, mode, op0, op1, 0)) != 0)
01198 return tem;
01199
01200
01201 if (GET_CODE (op1) == CONST_INT && GET_MODE (op0) != VOIDmode)
01202 return simplify_gen_binary (PLUS, mode,
01203 op0,
01204 neg_const_int (mode, op1));
01205
01206
01207 if (GET_CODE (op1) == AND)
01208 {
01209 if (rtx_equal_p (op0, XEXP (op1, 0)))
01210 return simplify_gen_binary (AND, mode, op0,
01211 gen_rtx_NOT (mode, XEXP (op1, 1)));
01212 if (rtx_equal_p (op0, XEXP (op1, 1)))
01213 return simplify_gen_binary (AND, mode, op0,
01214 gen_rtx_NOT (mode, XEXP (op1, 0)));
01215 }
01216 break;
01217
01218 case MULT:
01219 if (trueop1 == constm1_rtx)
01220 {
01221 tem = simplify_unary_operation (NEG, mode, op0, mode);
01222
01223 return tem ? tem : gen_rtx_NEG (mode, op0);
01224 }
01225
01226
01227
01228
01229
01230 if (!HONOR_NANS (mode)
01231 && !HONOR_SIGNED_ZEROS (mode)
01232 && trueop1 == CONST0_RTX (mode)
01233 && ! side_effects_p (op0))
01234 return op1;
01235
01236
01237
01238 if (!HONOR_SNANS (mode)
01239 && trueop1 == CONST1_RTX (mode))
01240 return op0;
01241
01242
01243
01244 if (GET_CODE (trueop1) == CONST_INT
01245 && (val = exact_log2 (INTVAL (trueop1))) >= 0
01246
01247
01248
01249 && (width <= HOST_BITS_PER_WIDE_INT
01250 || val != HOST_BITS_PER_WIDE_INT - 1)
01251 && ! rtx_equal_function_value_matters)
01252 return gen_rtx_ASHIFT (mode, op0, GEN_INT (val));
01253
01254
01255 if (GET_CODE (trueop1) == CONST_DOUBLE
01256 && GET_MODE_CLASS (GET_MODE (trueop1)) == MODE_FLOAT
01257 && GET_MODE (op0) == mode)
01258 {
01259 REAL_VALUE_TYPE d;
01260 REAL_VALUE_FROM_CONST_DOUBLE (d, trueop1);
01261
01262 if (REAL_VALUES_EQUAL (d, dconst2))
01263 return gen_rtx_PLUS (mode, op0, copy_rtx (op0));
01264
01265 if (REAL_VALUES_EQUAL (d, dconstm1))
01266 return gen_rtx_NEG (mode, op0);
01267 }
01268 break;
01269
01270 case IOR:
01271 if (trueop1 == const0_rtx)
01272 return op0;
01273 if (GET_CODE (trueop1) == CONST_INT
01274 && ((INTVAL (trueop1) & GET_MODE_MASK (mode))
01275 == GET_MODE_MASK (mode)))
01276 return op1;
01277 if (rtx_equal_p (trueop0, trueop1) && ! side_effects_p (op0))
01278 return op0;
01279
01280 if (((GET_CODE (op0) == NOT && rtx_equal_p (XEXP (op0, 0), op1))
01281 || (GET_CODE (op1) == NOT && rtx_equal_p (XEXP (op1, 0), op0)))
01282 && ! side_effects_p (op0)
01283 && GET_MODE_CLASS (mode) != MODE_CC)
01284 return constm1_rtx;
01285 break;
01286
01287 case XOR:
01288 if (trueop1 == const0_rtx)
01289 return op0;
01290 if (GET_CODE (trueop1) == CONST_INT
01291 && ((INTVAL (trueop1) & GET_MODE_MASK (mode))
01292 == GET_MODE_MASK (mode)))
01293 return gen_rtx_NOT (mode, op0);
01294 if (trueop0 == trueop1 && ! side_effects_p (op0)
01295 && GET_MODE_CLASS (mode) != MODE_CC)
01296 return const0_rtx;
01297 break;
01298
01299 case AND:
01300 if (trueop1 == const0_rtx && ! side_effects_p (op0))
01301 return const0_rtx;
01302 if (GET_CODE (trueop1) == CONST_INT
01303 && ((INTVAL (trueop1) & GET_MODE_MASK (mode))
01304 == GET_MODE_MASK (mode)))
01305 return op0;
01306 if (trueop0 == trueop1 && ! side_effects_p (op0)
01307 && GET_MODE_CLASS (mode) != MODE_CC)
01308 return op0;
01309
01310 if (((GET_CODE (op0) == NOT && rtx_equal_p (XEXP (op0, 0), op1))
01311 || (GET_CODE (op1) == NOT && rtx_equal_p (XEXP (op1, 0), op0)))
01312 && ! side_effects_p (op0)
01313 && GET_MODE_CLASS (mode) != MODE_CC)
01314 return const0_rtx;
01315 break;
01316
01317 case UDIV:
01318
01319
01320 if (GET_CODE (trueop1) == CONST_INT
01321 && (arg1 = exact_log2 (INTVAL (trueop1))) > 0)
01322 return gen_rtx_LSHIFTRT (mode, op0, GEN_INT (arg1));
01323
01324
01325
01326 case DIV:
01327 if (trueop1 == CONST1_RTX (mode))
01328 {
01329
01330
01331 rtx x = gen_lowpart_common (mode, op0);
01332 if (x)
01333 return x;
01334 else if (mode != GET_MODE (op0) && GET_MODE (op0) != VOIDmode)
01335 return gen_lowpart_SUBREG (mode, op0);
01336 else
01337 return op0;
01338 }
01339
01340
01341
01342
01343
01344 if (!HONOR_NANS (mode)
01345 && !HONOR_SIGNED_ZEROS (mode)
01346 && trueop0 == CONST0_RTX (mode)
01347 && ! side_effects_p (op1))
01348 return op0;
01349
01350
01351
01352 else if (GET_CODE (trueop1) == CONST_DOUBLE
01353 && GET_MODE_CLASS (GET_MODE (trueop1)) == MODE_FLOAT
01354 && trueop1 != CONST0_RTX (mode)
01355 && flag_unsafe_math_optimizations)
01356 {
01357 REAL_VALUE_TYPE d;
01358 REAL_VALUE_FROM_CONST_DOUBLE (d, trueop1);
01359
01360 if (! REAL_VALUES_EQUAL (d, dconst0))
01361 {
01362 REAL_ARITHMETIC (d, rtx_to_tree_code (DIV), dconst1, d);
01363 return gen_rtx_MULT (mode, op0,
01364 CONST_DOUBLE_FROM_REAL_VALUE (d, mode));
01365 }
01366 }
01367 break;
01368
01369 case UMOD:
01370
01371 if (GET_CODE (trueop1) == CONST_INT
01372 && exact_log2 (INTVAL (trueop1)) > 0)
01373 return gen_rtx_AND (mode, op0, GEN_INT (INTVAL (op1) - 1));
01374
01375
01376
01377 case MOD:
01378 if ((trueop0 == const0_rtx || trueop1 == const1_rtx)
01379 && ! side_effects_p (op0) && ! side_effects_p (op1))
01380 return const0_rtx;
01381 break;
01382
01383 case ROTATERT:
01384 case ROTATE:
01385
01386 if (GET_CODE (trueop0) == CONST_INT && width <= HOST_BITS_PER_WIDE_INT
01387 && (unsigned HOST_WIDE_INT) INTVAL (trueop0) == GET_MODE_MASK (mode)
01388 && ! side_effects_p (op1))
01389 return op0;
01390
01391
01392
01393 case ASHIFT:
01394 case ASHIFTRT:
01395 case LSHIFTRT:
01396 if (trueop1 == const0_rtx)
01397 return op0;
01398 if (trueop0 == const0_rtx && ! side_effects_p (op1))
01399 return op0;
01400 break;
01401
01402 case SMIN:
01403 if (width <= HOST_BITS_PER_WIDE_INT && GET_CODE (trueop1) == CONST_INT
01404 && INTVAL (trueop1) == (HOST_WIDE_INT) 1 << (width -1)
01405 && ! side_effects_p (op0))
01406 return op1;
01407 else if (rtx_equal_p (trueop0, trueop1) && ! side_effects_p (op0))
01408 return op0;
01409 break;
01410
01411 case SMAX:
01412 if (width <= HOST_BITS_PER_WIDE_INT && GET_CODE (trueop1) == CONST_INT
01413 && ((unsigned HOST_WIDE_INT) INTVAL (trueop1)
01414 == (unsigned HOST_WIDE_INT) GET_MODE_MASK (mode) >> 1)
01415 && ! side_effects_p (op0))
01416 return op1;
01417 else if (rtx_equal_p (trueop0, trueop1) && ! side_effects_p (op0))
01418 return op0;
01419 break;
01420
01421 case UMIN:
01422 if (trueop1 == const0_rtx && ! side_effects_p (op0))
01423 return op1;
01424 else if (rtx_equal_p (trueop0, trueop1) && ! side_effects_p (op0))
01425 return op0;
01426 break;
01427
01428 case UMAX:
01429 if (trueop1 == constm1_rtx && ! side_effects_p (op0))
01430 return op1;
01431 else if (rtx_equal_p (trueop0, trueop1) && ! side_effects_p (op0))
01432 return op0;
01433 break;
01434
01435 case SS_PLUS:
01436 case US_PLUS:
01437 case SS_MINUS:
01438 case US_MINUS:
01439
01440 return 0;
01441
01442 case VEC_SELECT:
01443 case VEC_CONCAT:
01444 return 0;
01445
01446 default:
01447 abort ();
01448 }
01449
01450 return 0;
01451 }
01452
01453
01454
01455
01456 arg0 = INTVAL (trueop0);
01457 arg1 = INTVAL (trueop1);
01458
01459 if (width < HOST_BITS_PER_WIDE_INT)
01460 {
01461 arg0 &= ((HOST_WIDE_INT) 1 << width) - 1;
01462 arg1 &= ((HOST_WIDE_INT) 1 << width) - 1;
01463
01464 arg0s = arg0;
01465 if (arg0s & ((HOST_WIDE_INT) 1 << (width - 1)))
01466 arg0s |= ((HOST_WIDE_INT) (-1) << width);
01467
01468 arg1s = arg1;
01469 if (arg1s & ((HOST_WIDE_INT) 1 << (width - 1)))
01470 arg1s |= ((HOST_WIDE_INT) (-1) << width);
01471 }
01472 else
01473 {
01474 arg0s = arg0;
01475 arg1s = arg1;
01476 }
01477
01478
01479
01480 switch (code)
01481 {
01482 case PLUS:
01483 val = arg0s + arg1s;
01484 break;
01485
01486 case MINUS:
01487 val = arg0s - arg1s;
01488 break;
01489
01490 case MULT:
01491 val = arg0s * arg1s;
01492 break;
01493
01494 case DIV:
01495 if (arg1s == 0
01496 || (arg0s == (HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT - 1)
01497 && arg1s == -1))
01498 return 0;
01499 val = arg0s / arg1s;
01500 break;
01501
01502 case MOD:
01503 if (arg1s == 0
01504 || (arg0s == (HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT - 1)
01505 && arg1s == -1))
01506 return 0;
01507 val = arg0s % arg1s;
01508 break;
01509
01510 case UDIV:
01511 if (arg1 == 0
01512 || (arg0s == (HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT - 1)
01513 && arg1s == -1))
01514 return 0;
01515 val = (unsigned HOST_WIDE_INT) arg0 / arg1;
01516 break;
01517
01518 case UMOD:
01519 if (arg1 == 0
01520 || (arg0s == (HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT - 1)
01521 && arg1s == -1))
01522 return 0;
01523 val = (unsigned HOST_WIDE_INT) arg0 % arg1;
01524 break;
01525
01526 case AND:
01527 val = arg0 & arg1;
01528 break;
01529
01530 case IOR:
01531 val = arg0 | arg1;
01532 break;
01533
01534 case XOR:
01535 val = arg0 ^ arg1;
01536 break;
01537
01538 case LSHIFTRT:
01539
01540
01541 if (arg1 < 0)
01542 return 0;
01543
01544 #ifdef SHIFT_COUNT_TRUNCATED
01545 if (SHIFT_COUNT_TRUNCATED)
01546 arg1 %= width;
01547 #endif
01548
01549 val = ((unsigned HOST_WIDE_INT) arg0) >> arg1;
01550 break;
01551
01552 case ASHIFT:
01553 if (arg1 < 0)
01554 return 0;
01555
01556 #ifdef SHIFT_COUNT_TRUNCATED
01557 if (SHIFT_COUNT_TRUNCATED)
01558 arg1 %= width;
01559 #endif
01560
01561 val = ((unsigned HOST_WIDE_INT) arg0) << arg1;
01562 break;
01563
01564 case ASHIFTRT:
01565 if (arg1 < 0)
01566 return 0;
01567
01568 #ifdef SHIFT_COUNT_TRUNCATED
01569 if (SHIFT_COUNT_TRUNCATED)
01570 arg1 %= width;
01571 #endif
01572
01573 val = arg0s >> arg1;
01574
01575
01576
01577 if (arg0s < 0 && arg1 > 0)
01578 val |= ((HOST_WIDE_INT) -1) << (HOST_BITS_PER_WIDE_INT - arg1);
01579
01580 break;
01581
01582 case ROTATERT:
01583 if (arg1 < 0)
01584 return 0;
01585
01586 arg1 %= width;
01587 val = ((((unsigned HOST_WIDE_INT) arg0) << (width - arg1))
01588 | (((unsigned HOST_WIDE_INT) arg0) >> arg1));
01589 break;
01590
01591 case ROTATE:
01592 if (arg1 < 0)
01593 return 0;
01594
01595 arg1 %= width;
01596 val = ((((unsigned HOST_WIDE_INT) arg0) << arg1)
01597 | (((unsigned HOST_WIDE_INT) arg0) >> (width - arg1)));
01598 break;
01599
01600 case COMPARE:
01601
01602 return 0;
01603
01604 case SMIN:
01605 val = arg0s <= arg1s ? arg0s : arg1s;
01606 break;
01607
01608 case UMIN:
01609 val = ((unsigned HOST_WIDE_INT) arg0
01610 <= (unsigned HOST_WIDE_INT) arg1 ? arg0 : arg1);
01611 break;
01612
01613 case SMAX:
01614 val = arg0s > arg1s ? arg0s : arg1s;
01615 break;
01616
01617 case UMAX:
01618 val = ((unsigned HOST_WIDE_INT) arg0
01619 > (unsigned HOST_WIDE_INT) arg1 ? arg0 : arg1);
01620 break;
01621
01622 default:
01623 abort ();
01624 }
01625
01626 val = trunc_int_for_mode (val, mode);
01627
01628 return GEN_INT (val);
01629 }
01630
01631
01632
01633
01634
01635
01636
01637
01638
01639
01640
01641
01642
01643 struct simplify_plus_minus_op_data
01644 {
01645 rtx op;
01646 int neg;
01647 };
01648
01649 static int
01650 simplify_plus_minus_op_data_cmp (p1, p2)
01651 const void *p1;
01652 const void *p2;
01653 {
01654 const struct simplify_plus_minus_op_data *d1 = p1;
01655 const struct simplify_plus_minus_op_data *d2 = p2;
01656
01657 return (commutative_operand_precedence (d2->op)
01658 - commutative_operand_precedence (d1->op));
01659 }
01660
01661 static rtx
01662 simplify_plus_minus (code, mode, op0, op1, force)
01663 enum rtx_code code;
01664 enum machine_mode mode;
01665 rtx op0, op1;
01666 int force;
01667 {
01668 struct simplify_plus_minus_op_data ops[8];
01669 rtx result, tem;
01670 int n_ops = 2, input_ops = 2, input_consts = 0, n_consts;
01671 int first, negate, changed;
01672 int i, j;
01673
01674 memset ((char *) ops, 0, sizeof ops);
01675
01676
01677
01678
01679
01680 ops[0].op = op0;
01681 ops[0].neg = 0;
01682 ops[1].op = op1;
01683 ops[1].neg = (code == MINUS);
01684
01685 do
01686 {
01687 changed = 0;
01688
01689 for (i = 0; i < n_ops; i++)
01690 {
01691 rtx this_op = ops[i].op;
01692 int this_neg = ops[i].neg;
01693 enum rtx_code this_code = GET_CODE (this_op);
01694
01695 switch (this_code)
01696 {
01697 case PLUS:
01698 case MINUS:
01699 if (n_ops == 7)
01700 return NULL_RTX;
01701
01702 ops[n_ops].op = XEXP (this_op, 1);
01703 ops[n_ops].neg = (this_code == MINUS) ^ this_neg;
01704 n_ops++;
01705
01706 ops[i].op = XEXP (this_op, 0);
01707 input_ops++;
01708 changed = 1;
01709 break;
01710
01711 case NEG:
01712 ops[i].op = XEXP (this_op, 0);
01713 ops[i].neg = ! this_neg;
01714 changed = 1;
01715 break;
01716
01717 case CONST:
01718 if (n_ops < 7
01719 && GET_CODE (XEXP (this_op, 0)) == PLUS
01720 && CONSTANT_P (XEXP (XEXP (this_op, 0), 0))
01721 && CONSTANT_P (XEXP (XEXP (this_op, 0), 1)))
01722 {
01723 ops[i].op = XEXP (XEXP (this_op, 0), 0);
01724 ops[n_ops].op = XEXP (XEXP (this_op, 0), 1);
01725 ops[n_ops].neg = this_neg;
01726 n_ops++;
01727 input_consts++;
01728 changed = 1;
01729 }
01730 break;
01731
01732 case NOT:
01733
01734 if (n_ops != 7)
01735 {
01736 ops[n_ops].op = constm1_rtx;
01737 ops[n_ops++].neg = this_neg;
01738 ops[i].op = XEXP (this_op, 0);
01739 ops[i].neg = !this_neg;
01740 changed = 1;
01741 }
01742 break;
01743
01744 case CONST_INT:
01745 if (this_neg)
01746 {
01747 ops[i].op = neg_const_int (mode, this_op);
01748 ops[i].neg = 0;
01749 changed = 1;
01750 }
01751 break;
01752
01753 default:
01754 break;
01755 }
01756 }
01757 }
01758 while (changed);
01759
01760
01761 if (n_ops <= 2 && !force)
01762 return NULL_RTX;
01763
01764
01765 for (i = 0; i < n_ops; i++)
01766 if (GET_CODE (ops[i].op) == CONST)
01767 input_consts++;
01768
01769
01770
01771
01772 first = 1;
01773 do
01774 {
01775 changed = first;
01776
01777 for (i = 0; i < n_ops - 1; i++)
01778 for (j = i + 1; j < n_ops; j++)
01779 {
01780 rtx lhs = ops[i].op, rhs = ops[j].op;
01781 int lneg = ops[i].neg, rneg = ops[j].neg;
01782
01783 if (lhs != 0 && rhs != 0
01784 && (! first || (CONSTANT_P (lhs) && CONSTANT_P (rhs))))
01785 {
01786 enum rtx_code ncode = PLUS;
01787
01788 if (lneg != rneg)
01789 {
01790 ncode = MINUS;
01791 if (lneg)
01792 tem = lhs, lhs = rhs, rhs = tem;
01793 }
01794 else if (swap_commutative_operands_p (lhs, rhs))
01795 tem = lhs, lhs = rhs, rhs = tem;
01796
01797 tem = simplify_binary_operation (ncode, mode, lhs, rhs);
01798
01799
01800
01801
01802
01803 if (tem
01804 && ! (GET_CODE (tem) == CONST
01805 && GET_CODE (XEXP (tem, 0)) == ncode
01806 && XEXP (XEXP (tem, 0), 0) == lhs
01807 && XEXP (XEXP (tem, 0), 1) == rhs)
01808
01809
01810
01811 && ! (first
01812 && GET_CODE (tem) == NOT
01813 && XEXP (tem, 0) == rhs))
01814 {
01815 lneg &= rneg;
01816 if (GET_CODE (tem) == NEG)
01817 tem = XEXP (tem, 0), lneg = !lneg;
01818 if (GET_CODE (tem) == CONST_INT && lneg)
01819 tem = neg_const_int (mode, tem), lneg = 0;
01820
01821 ops[i].op = tem;
01822 ops[i].neg = lneg;
01823 ops[j].op = NULL_RTX;
01824 changed = 1;
01825 }
01826 }
01827 }
01828
01829 first = 0;
01830 }
01831 while (changed);
01832
01833
01834 for (i = 0, j = 0; j < n_ops; j++)
01835 if (ops[j].op)
01836 ops[i++] = ops[j];
01837 n_ops = i;
01838
01839
01840 qsort (ops, n_ops, sizeof (*ops), simplify_plus_minus_op_data_cmp);
01841
01842
01843
01844
01845
01846
01847
01848 if (n_ops > 1
01849 && GET_CODE (ops[n_ops - 1].op) == CONST_INT
01850 && CONSTANT_P (ops[n_ops - 2].op))
01851 {
01852 rtx value = ops[n_ops - 1].op;
01853 if (ops[n_ops - 1].neg ^ ops[n_ops - 2].neg)
01854 value = neg_const_int (mode, value);
01855 ops[n_ops - 2].op = plus_constant (ops[n_ops - 2].op, INTVAL (value));
01856 n_ops--;
01857 }
01858
01859
01860 n_consts = 0;
01861 for (i = 0; i < n_ops; i++)
01862 if (GET_CODE (ops[i].op) == CONST)
01863 n_consts++;
01864
01865
01866
01867
01868
01869 if (!force
01870 && (n_ops + n_consts > input_ops
01871 || (n_ops + n_consts == input_ops && n_consts <= input_consts)))
01872 return NULL_RTX;
01873
01874
01875
01876
01877 negate = 0;
01878 for (i = 0; i < n_ops && ops[i].neg; i++)
01879 continue;
01880 if (i == n_ops)
01881 {
01882 for (i = 0; i < n_ops; i++)
01883 ops[i].neg = 0;
01884 negate = 1;
01885 }
01886 else if (i != 0)
01887 {
01888 tem = ops[0].op;
01889 ops[0] = ops[i];
01890 ops[i].op = tem;
01891 ops[i].neg = 1;
01892 }
01893
01894
01895 result = ops[0].op;
01896 for (i = 1; i < n_ops; i++)
01897 result = gen_rtx_fmt_ee (ops[i].neg ? MINUS : PLUS,
01898 mode, result, ops[i].op);
01899
01900 return negate ? gen_rtx_NEG (mode, result) : result;
01901 }
01902
01903
01904
01905
01906
01907
01908
01909
01910
01911 rtx
01912 simplify_relational_operation (code, mode, op0, op1)
01913 enum rtx_code code;
01914 enum machine_mode mode;
01915 rtx op0, op1;
01916 {
01917 int equal, op0lt, op0ltu, op1lt, op1ltu;
01918 rtx tem;
01919 rtx trueop0;
01920 rtx trueop1;
01921
01922 if (mode == VOIDmode
01923 && (GET_MODE (op0) != VOIDmode
01924 || GET_MODE (op1) != VOIDmode))
01925 abort ();
01926
01927
01928 if (GET_CODE (op0) == COMPARE && op1 == const0_rtx)
01929 op1 = XEXP (op0, 1), op0 = XEXP (op0, 0);
01930
01931 trueop0 = avoid_constant_pool_reference (op0);
01932 trueop1 = avoid_constant_pool_reference (op1);
01933
01934
01935
01936 if (GET_MODE_CLASS (GET_MODE (op0)) == MODE_CC
01937 #ifdef HAVE_cc0
01938 || op0 == cc0_rtx
01939 #endif
01940 )
01941 return 0;
01942
01943
01944 if (swap_commutative_operands_p (trueop0, trueop1))
01945 {
01946 tem = op0, op0 = op1, op1 = tem;
01947 tem = trueop0, trueop0 = trueop1, trueop1 = tem;
01948 code = swap_condition (code);
01949 }
01950
01951
01952
01953
01954
01955
01956
01957
01958
01959
01960
01961 if (INTEGRAL_MODE_P (mode) && trueop1 != const0_rtx
01962 && ! ((GET_CODE (op0) == REG || GET_CODE (trueop0) == CONST_INT)
01963 && (GET_CODE (op1) == REG || GET_CODE (trueop1) == CONST_INT))
01964 && 0 != (tem = simplify_binary_operation (MINUS, mode, op0, op1))
01965 && code != GTU && code != GEU && code != LTU && code != LEU)
01966 return simplify_relational_operation (signed_condition (code),
01967 mode, tem, const0_rtx);
01968
01969 if (flag_unsafe_math_optimizations && code == ORDERED)
01970 return const_true_rtx;
01971
01972 if (flag_unsafe_math_optimizations && code == UNORDERED)
01973 return const0_rtx;
01974
01975
01976
01977 if (!HONOR_NANS (GET_MODE (trueop0))
01978 && rtx_equal_p (trueop0, trueop1)
01979 && ! side_effects_p (trueop0))
01980 equal = 1, op0lt = 0, op0ltu = 0, op1lt = 0, op1ltu = 0;
01981
01982
01983
01984 else if (GET_CODE (trueop0) == CONST_DOUBLE
01985 && GET_CODE (trueop1) == CONST_DOUBLE
01986 && GET_MODE_CLASS (GET_MODE (trueop0)) == MODE_FLOAT)
01987 {
01988 REAL_VALUE_TYPE d0, d1;
01989
01990 REAL_VALUE_FROM_CONST_DOUBLE (d0, trueop0);
01991 REAL_VALUE_FROM_CONST_DOUBLE (d1, trueop1);
01992
01993
01994 if (REAL_VALUE_ISNAN (d0) || REAL_VALUE_ISNAN (d1))
01995 switch (code)
01996 {
01997 case UNEQ:
01998 case UNLT:
01999 case UNGT:
02000 case UNLE:
02001 case UNGE:
02002 case NE:
02003 case UNORDERED:
02004 return const_true_rtx;
02005 case EQ:
02006 case LT:
02007 case GT:
02008 case LE:
02009 case GE:
02010 case LTGT:
02011 case ORDERED:
02012 return const0_rtx;
02013 default:
02014 return 0;
02015 }
02016
02017 equal = REAL_VALUES_EQUAL (d0, d1);
02018 op0lt = op0ltu = REAL_VALUES_LESS (d0, d1);
02019 op1lt = op1ltu = REAL_VALUES_LESS (d1, d0);
02020 }
02021
02022
02023 else if ((GET_MODE_CLASS (mode) == MODE_INT || mode == VOIDmode)
02024 && (GET_CODE (trueop0) == CONST_DOUBLE
02025 || GET_CODE (trueop0) == CONST_INT)
02026 && (GET_CODE (trueop1) == CONST_DOUBLE
02027 || GET_CODE (trueop1) == CONST_INT))
02028 {
02029 int width = GET_MODE_BITSIZE (mode);
02030 HOST_WIDE_INT l0s, h0s, l1s, h1s;
02031 unsigned HOST_WIDE_INT l0u, h0u, l1u, h1u;
02032
02033
02034 if (GET_CODE (trueop0) == CONST_DOUBLE)
02035 {
02036 l0u = l0s = CONST_DOUBLE_LOW (trueop0);
02037 h0u = h0s = CONST_DOUBLE_HIGH (trueop0);
02038 }
02039 else
02040 {
02041 l0u = l0s = INTVAL (trueop0);
02042 h0u = h0s = HWI_SIGN_EXTEND (l0s);
02043 }
02044
02045 if (GET_CODE (trueop1) == CONST_DOUBLE)
02046 {
02047 l1u = l1s = CONST_DOUBLE_LOW (trueop1);
02048 h1u = h1s = CONST_DOUBLE_HIGH (trueop1);
02049 }
02050 else
02051 {
02052 l1u = l1s = INTVAL (trueop1);
02053 h1u = h1s = HWI_SIGN_EXTEND (l1s);
02054 }
02055
02056
02057
02058 if (width != 0 && width < HOST_BITS_PER_WIDE_INT)
02059 {
02060 l0u &= ((HOST_WIDE_INT) 1 << width) - 1;
02061 l1u &= ((HOST_WIDE_INT) 1 << width) - 1;
02062
02063 if (l0s & ((HOST_WIDE_INT) 1 << (width - 1)))
02064 l0s |= ((HOST_WIDE_INT) (-1) << width);
02065
02066 if (l1s & ((HOST_WIDE_INT) 1 << (width - 1)))
02067 l1s |= ((HOST_WIDE_INT) (-1) << width);
02068 }
02069 if (width != 0 && width <= HOST_BITS_PER_WIDE_INT)
02070 h0u = h1u = 0, h0s = HWI_SIGN_EXTEND (l0s), h1s = HWI_SIGN_EXTEND (l1s);
02071
02072 equal = (h0u == h1u && l0u == l1u);
02073 op0lt = (h0s < h1s || (h0s == h1s && l0u < l1u));
02074 op1lt = (h1s < h0s || (h1s == h0s && l1u < l0u));
02075 op0ltu = (h0u < h1u || (h0u == h1u && l0u < l1u));
02076 op1ltu = (h1u < h0u || (h1u == h0u && l1u < l0u));
02077 }
02078
02079
02080 else
02081 {
02082 switch (code)
02083 {
02084 case EQ:
02085
02086
02087 if (((NONZERO_BASE_PLUS_P (op0) && trueop1 == const0_rtx)
02088 || GET_CODE (trueop0) == LABEL_REF)
02089 #if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
02090
02091 && op0 != arg_pointer_rtx
02092 #endif
02093 )
02094 return const0_rtx;
02095 break;
02096
02097 case NE:
02098 if (((NONZERO_BASE_PLUS_P (op0) && trueop1 == const0_rtx)
02099 || GET_CODE (trueop0) == LABEL_REF)
02100 #if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
02101 && op0 != arg_pointer_rtx
02102 #endif
02103 )
02104 return const_true_rtx;
02105 break;
02106
02107 case GEU:
02108
02109 if (trueop1 == const0_rtx)
02110 return const_true_rtx;
02111 break;
02112
02113 case LTU:
02114 if (trueop1 == const0_rtx)
02115 return const0_rtx;
02116 break;
02117
02118 case LEU:
02119
02120
02121 if (GET_CODE (trueop1) == CONST_INT
02122 && (unsigned HOST_WIDE_INT) INTVAL (trueop1) == GET_MODE_MASK (mode)
02123 && INTEGRAL_MODE_P (mode))
02124 return const_true_rtx;
02125 break;
02126
02127 case GTU:
02128 if (GET_CODE (trueop1) == CONST_INT
02129 && (unsigned HOST_WIDE_INT) INTVAL (trueop1) == GET_MODE_MASK (mode)
02130 && INTEGRAL_MODE_P (mode))
02131 return const0_rtx;
02132 break;
02133
02134 case LT:
02135
02136 if (trueop1 == CONST0_RTX (mode) && !HONOR_SNANS (mode))
02137 {
02138 tem = GET_CODE (trueop0) == FLOAT_EXTEND ? XEXP (trueop0, 0)
02139 : trueop0;
02140 if (GET_CODE (tem) == ABS)
02141 return const0_rtx;
02142 }
02143 break;
02144
02145 case GE:
02146
02147 if (trueop1 == CONST0_RTX (mode) && !HONOR_NANS (mode))
02148 {
02149 tem = GET_CODE (trueop0) == FLOAT_EXTEND ? XEXP (trueop0, 0)
02150 : trueop0;
02151 if (GET_CODE (tem) == ABS)
02152 return const1_rtx;
02153 }
02154 break;
02155
02156 default:
02157 break;
02158 }
02159
02160 return 0;
02161 }
02162
02163
02164
02165 switch (code)
02166 {
02167 case EQ:
02168 case UNEQ:
02169 return equal ? const_true_rtx : const0_rtx;
02170 case NE:
02171 case LTGT:
02172 return ! equal ? const_true_rtx : const0_rtx;
02173 case LT:
02174 case UNLT:
02175 return op0lt ? const_true_rtx : const0_rtx;
02176 case GT:
02177 case UNGT:
02178 return op1lt ? const_true_rtx : const0_rtx;
02179 case LTU:
02180 return op0ltu ? const_true_rtx : const0_rtx;
02181 case GTU:
02182 return op1ltu ? const_true_rtx : const0_rtx;
02183 case LE:
02184 case UNLE:
02185 return equal || op0lt ? const_true_rtx : const0_rtx;
02186 case GE:
02187 case UNGE:
02188 return equal || op1lt ? const_true_rtx : const0_rtx;
02189 case LEU:
02190 return equal || op0ltu ? const_true_rtx : const0_rtx;
02191 case GEU:
02192 return equal || op1ltu ? const_true_rtx : const0_rtx;
02193 case ORDERED:
02194 return const_true_rtx;
02195 case UNORDERED:
02196 return const0_rtx;
02197 default:
02198 abort ();
02199 }
02200 }
02201
02202
02203
02204
02205
02206 rtx
02207 simplify_ternary_operation (code, mode, op0_mode, op0, op1, op2)
02208 enum rtx_code code;
02209 enum machine_mode mode, op0_mode;
02210 rtx op0, op1, op2;
02211 {
02212 unsigned int width = GET_MODE_BITSIZE (mode);
02213
02214
02215 if (width == 0)
02216 width = HOST_BITS_PER_WIDE_INT;
02217
02218 switch (code)
02219 {
02220 case SIGN_EXTRACT:
02221 case ZERO_EXTRACT:
02222 if (GET_CODE (op0) == CONST_INT
02223 && GET_CODE (op1) == CONST_INT
02224 && GET_CODE (op2) == CONST_INT
02225 && ((unsigned) INTVAL (op1) + (unsigned) INTVAL (op2) <= width)
02226 && width <= (unsigned) HOST_BITS_PER_WIDE_INT)
02227 {
02228
02229 HOST_WIDE_INT val = INTVAL (op0);
02230
02231 if (BITS_BIG_ENDIAN)
02232 val >>= (GET_MODE_BITSIZE (op0_mode)
02233 - INTVAL (op2) - INTVAL (op1));
02234 else
02235 val >>= INTVAL (op2);
02236
02237 if (HOST_BITS_PER_WIDE_INT != INTVAL (op1))
02238 {
02239
02240 val &= ((HOST_WIDE_INT) 1 << INTVAL (op1)) - 1;
02241
02242 if (code == SIGN_EXTRACT
02243 && (val & ((HOST_WIDE_INT) 1 << (INTVAL (op1) - 1))))
02244 val |= ~ (((HOST_WIDE_INT) 1 << INTVAL (op1)) - 1);
02245 }
02246
02247
02248
02249
02250
02251 if (width < HOST_BITS_PER_WIDE_INT
02252 && ((val & ((HOST_WIDE_INT) (-1) << (width - 1)))
02253 != ((HOST_WIDE_INT) (-1) << (width - 1))))
02254 val &= ((HOST_WIDE_INT) 1 << width) - 1;
02255
02256 return GEN_INT (val);
02257 }
02258 break;
02259
02260 case IF_THEN_ELSE:
02261 if (GET_CODE (op0) == CONST_INT)
02262 return op0 != const0_rtx ? op1 : op2;
02263
02264
02265 if (GET_CODE (op0) == NE && ! side_effects_p (op0)
02266 && !HONOR_NANS (mode)
02267 && rtx_equal_p (XEXP (op0, 0), op1)
02268 && rtx_equal_p (XEXP (op0, 1), op2))
02269 return op1;
02270 else if (GET_CODE (op0) == EQ && ! side_effects_p (op0)
02271 && !HONOR_NANS (mode)
02272 && rtx_equal_p (XEXP (op0, 1), op1)
02273 && rtx_equal_p (XEXP (op0, 0), op2))
02274 return op2;
02275 else if (GET_RTX_CLASS (GET_CODE (op0)) == '<' && ! side_effects_p (op0))
02276 {
02277 enum machine_mode cmp_mode = (GET_MODE (XEXP (op0, 0)) == VOIDmode
02278 ? GET_MODE (XEXP (op0, 1))
02279 : GET_MODE (XEXP (op0, 0)));
02280 rtx temp;
02281 if (cmp_mode == VOIDmode)
02282 cmp_mode = op0_mode;
02283 temp = simplify_relational_operation (GET_CODE (op0), cmp_mode,
02284 XEXP (op0, 0), XEXP (op0, 1));
02285
02286
02287 if (temp == const0_rtx)
02288 return op2;
02289 else if (temp == const1_rtx)
02290 return op1;
02291 else if (temp)
02292 op0 = temp;
02293
02294
02295 if (GET_CODE (op1) == CONST_INT && GET_CODE (op2) == CONST_INT)
02296 {
02297 HOST_WIDE_INT t = INTVAL (op1);
02298 HOST_WIDE_INT f = INTVAL (op2);
02299
02300 if (t == STORE_FLAG_VALUE && f == 0)
02301 code = GET_CODE (op0);
02302 else if (t == 0 && f == STORE_FLAG_VALUE)
02303 {
02304 enum rtx_code tmp;
02305 tmp = reversed_comparison_code (op0, NULL_RTX);
02306 if (tmp == UNKNOWN)
02307 break;
02308 code = tmp;
02309 }
02310 else
02311 break;
02312
02313 return gen_rtx_fmt_ee (code, mode, XEXP (op0, 0), XEXP (op0, 1));
02314 }
02315 }
02316 break;
02317 case VEC_MERGE:
02318 if (GET_MODE (op0) != mode
02319 || GET_MODE (op1) != mode
02320 || !VECTOR_MODE_P (mode))
02321 abort ();
02322 op0 = avoid_constant_pool_reference (op0);
02323 op1 = avoid_constant_pool_reference (op1);
02324 op2 = avoid_constant_pool_reference (op2);
02325 if (GET_CODE (op0) == CONST_VECTOR
02326 && GET_CODE (op1) == CONST_VECTOR
02327 && GET_CODE (op2) == CONST_INT)
02328 {
02329 int elt_size = GET_MODE_SIZE (GET_MODE_INNER (mode));
02330 unsigned n_elts = (GET_MODE_SIZE (mode) / elt_size);
02331 rtvec v = rtvec_alloc (n_elts);
02332 unsigned int i;
02333
02334 for (i = 0; i < n_elts; i++)
02335 RTVEC_ELT (v, i) = (INTVAL (op2) & (1 << i)
02336 ? CONST_VECTOR_ELT (op0, i)
02337 : CONST_VECTOR_ELT (op1, i));
02338 return gen_rtx_CONST_VECTOR (mode, v);
02339 }
02340 break;
02341
02342 default:
02343 abort ();
02344 }
02345
02346 return 0;
02347 }
02348
02349
02350
02351 rtx
02352 simplify_subreg (outermode, op, innermode, byte)
02353 rtx op;
02354 unsigned int byte;
02355 enum machine_mode outermode, innermode;
02356 {
02357
02358 if (innermode == VOIDmode || outermode == VOIDmode
02359 || innermode == BLKmode || outermode == BLKmode)
02360 abort ();
02361
02362 if (GET_MODE (op) != innermode
02363 && GET_MODE (op) != VOIDmode)
02364 abort ();
02365
02366 if (byte % GET_MODE_SIZE (outermode)
02367 || byte >= GET_MODE_SIZE (innermode))
02368 abort ();
02369
02370 if (outermode == innermode && !byte)
02371 return op;
02372
02373
02374 if (GET_CODE (op) == CONST_VECTOR)
02375 {
02376 int elt_size = GET_MODE_SIZE (GET_MODE_INNER (innermode));
02377 const unsigned int offset = byte / elt_size;
02378 rtx elt;
02379
02380 if (GET_MODE_INNER (innermode) == outermode)
02381 {
02382 elt = CONST_VECTOR_ELT (op, offset);
02383
02384
02385
02386
02387 return copy_rtx (elt);
02388 }
02389 else if (GET_MODE_INNER (innermode) == GET_MODE_INNER (outermode)
02390 && GET_MODE_SIZE (innermode) > GET_MODE_SIZE (outermode))
02391 {
02392 return (gen_rtx_CONST_VECTOR
02393 (outermode,
02394 gen_rtvec_v (GET_MODE_NUNITS (outermode),
02395 &CONST_VECTOR_ELT (op, offset))));
02396 }
02397 else if (GET_MODE_CLASS (outermode) == MODE_INT
02398 && (GET_MODE_SIZE (outermode) % elt_size == 0))
02399 {
02400
02401
02402
02403 HOST_WIDE_INT sum = 0, high = 0;
02404 unsigned n_elts = (GET_MODE_SIZE (outermode) / elt_size);
02405 unsigned i = BYTES_BIG_ENDIAN ? offset : offset + n_elts - 1;
02406 unsigned step = BYTES_BIG_ENDIAN ? 1 : -1;
02407 int shift = BITS_PER_UNIT * elt_size;
02408
02409 for (; n_elts--; i += step)
02410 {
02411 elt = CONST_VECTOR_ELT (op, i);
02412 if (GET_CODE (elt) == CONST_DOUBLE
02413 && GET_MODE_CLASS (GET_MODE (elt)) == MODE_FLOAT)
02414 {
02415 elt = gen_lowpart_common (int_mode_for_mode (GET_MODE (elt)),
02416 elt);
02417 if (! elt)
02418 return NULL_RTX;
02419 }
02420 if (GET_CODE (elt) != CONST_INT)
02421 return NULL_RTX;
02422
02423 if (high >> (HOST_BITS_PER_WIDE_INT - shift))
02424 return NULL_RTX;
02425 high = high << shift | sum >> (HOST_BITS_PER_WIDE_INT - shift);
02426 sum = (sum << shift) + INTVAL (elt);
02427 }
02428 if (GET_MODE_BITSIZE (outermode) <= HOST_BITS_PER_WIDE_INT)
02429 return GEN_INT (trunc_int_for_mode (sum, outermode));
02430 else if (GET_MODE_BITSIZE (outermode) == 2* HOST_BITS_PER_WIDE_INT)
02431 return immed_double_const (sum, high, outermode);
02432 else
02433 return NULL_RTX;
02434 }
02435 else if (GET_MODE_CLASS (outermode) == MODE_INT
02436 && (elt_size % GET_MODE_SIZE (outermode) == 0))
02437 {
02438 enum machine_mode new_mode
02439 = int_mode_for_mode (GET_MODE_INNER (innermode));
02440 int subbyte = byte % elt_size;
02441
02442 op = simplify_subreg (new_mode, op, innermode, byte - subbyte);
02443 if (! op)
02444 return NULL_RTX;
02445 return simplify_subreg (outermode, op, new_mode, subbyte);
02446 }
02447 else if (GET_MODE_CLASS (outermode) == MODE_INT)
02448
02449 return NULL_RTX;
02450 }
02451
02452
02453 if (CONSTANT_P (op))
02454 {
02455 int offset, part;
02456 unsigned HOST_WIDE_INT val = 0;
02457
02458 if (GET_MODE_CLASS (outermode) == MODE_VECTOR_INT
02459 || GET_MODE_CLASS (outermode) == MODE_VECTOR_FLOAT)
02460 {
02461
02462 enum machine_mode submode = GET_MODE_INNER (outermode);
02463 int subsize = GET_MODE_UNIT_SIZE (outermode);
02464 int i, elts = GET_MODE_NUNITS (outermode);
02465 rtvec v = rtvec_alloc (elts);
02466 rtx elt;
02467
02468 for (i = 0; i < elts; i++, byte += subsize)
02469 {
02470
02471
02472
02473 if (byte >= GET_MODE_UNIT_SIZE (innermode))
02474 elt = CONST0_RTX (submode);
02475 else
02476 elt = simplify_subreg (submode, op, innermode, byte);
02477 if (! elt)
02478 return NULL_RTX;
02479 RTVEC_ELT (v, i) = elt;
02480 }
02481 return gen_rtx_CONST_VECTOR (outermode, v);
02482 }
02483
02484
02485
02486
02487
02488
02489 if (subreg_lowpart_offset (outermode, innermode) == byte
02490 && GET_CODE (op) != CONST_VECTOR)
02491 {
02492 rtx new = gen_lowpart_if_possible (outermode, op);
02493 if (new)
02494 return new;
02495 }
02496
02497
02498 if (GET_MODE_SIZE (outermode) == UNITS_PER_WORD
02499 && GET_MODE_SIZE (innermode) > UNITS_PER_WORD
02500 && GET_MODE_CLASS (outermode) == MODE_INT)
02501 {
02502 rtx new = constant_subword (op,
02503 (byte / UNITS_PER_WORD),
02504 innermode);
02505 if (new)
02506 return new;
02507 }
02508
02509 if (GET_MODE_CLASS (outermode) != MODE_INT
02510 && GET_MODE_CLASS (outermode) != MODE_CC)
02511 {
02512 enum machine_mode new_mode = int_mode_for_mode (outermode);
02513
02514 if (new_mode != innermode || byte != 0)
02515 {
02516 op = simplify_subreg (new_mode, op, innermode, byte);
02517 if (! op)
02518 return NULL_RTX;
02519 return simplify_subreg (outermode, op, new_mode, 0);
02520 }
02521 }
02522
02523 offset = byte * BITS_PER_UNIT;
02524 switch (GET_CODE (op))
02525 {
02526 case CONST_DOUBLE:
02527 if (GET_MODE (op) != VOIDmode)
02528 break;
02529
02530
02531 if (GET_MODE_BITSIZE (outermode) >= HOST_BITS_PER_WIDE_INT)
02532 return NULL_RTX;
02533
02534 part = offset >= HOST_BITS_PER_WIDE_INT;
02535 if ((BITS_PER_WORD > HOST_BITS_PER_WIDE_INT
02536 && BYTES_BIG_ENDIAN)
02537 || (BITS_PER_WORD <= HOST_BITS_PER_WIDE_INT
02538 && WORDS_BIG_ENDIAN))
02539 part = !part;
02540 val = part ? CONST_DOUBLE_HIGH (op) : CONST_DOUBLE_LOW (op);
02541 offset %= HOST_BITS_PER_WIDE_INT;
02542
02543
02544
02545 innermode = mode_for_size (HOST_BITS_PER_WIDE_INT, MODE_INT, 0);
02546
02547
02548 case CONST_INT:
02549 if (GET_CODE (op) == CONST_INT)
02550 val = INTVAL (op);
02551
02552
02553 if (GET_MODE_CLASS (outermode) != MODE_INT)
02554 return NULL_RTX;
02555
02556 if (BYTES_BIG_ENDIAN || WORDS_BIG_ENDIAN)
02557 {
02558 if (WORDS_BIG_ENDIAN)
02559 offset = (GET_MODE_BITSIZE (innermode)
02560 - GET_MODE_BITSIZE (outermode) - offset);
02561 if (BYTES_BIG_ENDIAN != WORDS_BIG_ENDIAN
02562 && GET_MODE_SIZE (outermode) < UNITS_PER_WORD)
02563 offset = (offset + BITS_PER_WORD - GET_MODE_BITSIZE (outermode)
02564 - 2 * (offset % BITS_PER_WORD));
02565 }
02566
02567 if (offset >= HOST_BITS_PER_WIDE_INT)
02568 return ((HOST_WIDE_INT) val < 0) ? constm1_rtx : const0_rtx;
02569 else
02570 {
02571 val >>= offset;
02572 if (GET_MODE_BITSIZE (outermode) < HOST_BITS_PER_WIDE_INT)
02573 val = trunc_int_for_mode (val, outermode);
02574 return GEN_INT (val);
02575 }
02576 default:
02577 break;
02578 }
02579 }
02580
02581
02582
02583 if (GET_CODE (op) == SUBREG)
02584 {
02585 enum machine_mode innermostmode = GET_MODE (SUBREG_REG (op));
02586 int final_offset = byte + SUBREG_BYTE (op);
02587 rtx new;
02588
02589 if (outermode == innermostmode
02590 && byte == 0 && SUBREG_BYTE (op) == 0)
02591 return SUBREG_REG (op);
02592
02593
02594
02595
02596
02597 if (byte == 0 && GET_MODE_SIZE (innermode) < GET_MODE_SIZE (outermode))
02598 {
02599 int difference = (GET_MODE_SIZE (innermode) - GET_MODE_SIZE (outermode));
02600 if (WORDS_BIG_ENDIAN)
02601 final_offset += (difference / UNITS_PER_WORD) * UNITS_PER_WORD;
02602 if (BYTES_BIG_ENDIAN)
02603 final_offset += difference % UNITS_PER_WORD;
02604 }
02605 if (SUBREG_BYTE (op) == 0
02606 && GET_MODE_SIZE (innermostmode) < GET_MODE_SIZE (innermode))
02607 {
02608 int difference = (GET_MODE_SIZE (innermostmode) - GET_MODE_SIZE (innermode));
02609 if (WORDS_BIG_ENDIAN)
02610 final_offset += (difference / UNITS_PER_WORD) * UNITS_PER_WORD;
02611 if (BYTES_BIG_ENDIAN)
02612 final_offset += difference % UNITS_PER_WORD;
02613 }
02614
02615
02616 if (GET_MODE_SIZE (innermostmode) > GET_MODE_SIZE (outermode))
02617 {
02618
02619 if (final_offset < 0)
02620 return NULL_RTX;
02621
02622 if (final_offset % GET_MODE_SIZE (outermode)
02623 || (unsigned) final_offset >= GET_MODE_SIZE (innermostmode))
02624 return NULL_RTX;
02625 }
02626 else
02627 {
02628 int offset = 0;
02629 int difference = (GET_MODE_SIZE (innermostmode) - GET_MODE_SIZE (outermode));
02630
02631
02632
02633 if (WORDS_BIG_ENDIAN)
02634 offset += (difference / UNITS_PER_WORD) * UNITS_PER_WORD;
02635 if (BYTES_BIG_ENDIAN)
02636 offset += difference % UNITS_PER_WORD;
02637 if (offset == final_offset)
02638 final_offset = 0;
02639 else
02640 return NULL_RTX;
02641 }
02642
02643
02644 new = simplify_subreg (outermode, SUBREG_REG (op),
02645 GET_MODE (SUBREG_REG (op)),
02646 final_offset);
02647 if (new)
02648 return new;
02649 return gen_rtx_SUBREG (outermode, SUBREG_REG (op), final_offset);
02650 }
02651
02652
02653
02654
02655
02656
02657 if (REG_P (op)
02658 && (! REG_FUNCTION_VALUE_P (op)
02659 || ! rtx_equal_function_value_matters)
02660 && REGNO (op) < FIRST_PSEUDO_REGISTER
02661 #ifdef CANNOT_CHANGE_MODE_CLASS
02662 && ! (REG_CANNOT_CHANGE_MODE_P (REGNO (op), innermode, outermode)
02663 && GET_MODE_CLASS (innermode) != MODE_COMPLEX_INT
02664 && GET_MODE_CLASS (innermode) != MODE_COMPLEX_FLOAT)
02665 #endif
02666 && ((reload_completed && !frame_pointer_needed)
02667 || (REGNO (op) != FRAME_POINTER_REGNUM
02668 #if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM
02669 && REGNO (op) != HARD_FRAME_POINTER_REGNUM
02670 #endif
02671 ))
02672 #if FRAME_POINTER_REGNUM != ARG_POINTER_REGNUM
02673 && REGNO (op) != ARG_POINTER_REGNUM
02674 #endif
02675 && REGNO (op) != STACK_POINTER_REGNUM)
02676 {
02677 int final_regno = subreg_hard_regno (gen_rtx_SUBREG (outermode, op, byte),
02678 0);
02679
02680
02681
02682
02683 if (HARD_REGNO_MODE_OK (final_regno, outermode)
02684 || ! HARD_REGNO_MODE_OK (REGNO (op), innermode))
02685 {
02686 rtx x = gen_rtx_REG (outermode, final_regno);
02687
02688
02689
02690
02691
02692
02693 if (subreg_lowpart_offset (outermode, innermode) == byte)
02694 ORIGINAL_REGNO (x) = ORIGINAL_REGNO (op);
02695 return x;
02696 }
02697 }
02698
02699
02700
02701
02702
02703
02704 if (GET_CODE (op) == MEM
02705 && ! mode_dependent_address_p (XEXP (op, 0))
02706
02707
02708 && (! MEM_VOLATILE_P (op)
02709 || ! have_insn_for (SET, innermode))
02710 && GET_MODE_SIZE (outermode) <= GET_MODE_SIZE (GET_MODE (op)))
02711 return adjust_address_nv (op, outermode, byte);
02712
02713
02714
02715 if (GET_CODE (op) == CONCAT)
02716 {
02717 int is_realpart = byte < GET_MODE_UNIT_SIZE (innermode);
02718 rtx part = is_realpart ? XEXP (op, 0) : XEXP (op, 1);
02719 unsigned int final_offset;
02720 rtx res;
02721
02722 final_offset = byte % (GET_MODE_UNIT_SIZE (innermode));
02723 res = simplify_subreg (outermode, part, GET_MODE (part), final_offset);
02724 if (res)
02725 return res;
02726
02727 return gen_rtx_SUBREG (outermode, part, final_offset);
02728 }
02729
02730 return NULL_RTX;
02731 }
02732
02733
02734 rtx
02735 simplify_gen_subreg (outermode, op, innermode, byte)
02736 rtx op;
02737 unsigned int byte;
02738 enum machine_mode outermode, innermode;
02739 {
02740 rtx new;
02741
02742 if (innermode == VOIDmode || outermode == VOIDmode
02743 || innermode == BLKmode || outermode == BLKmode)
02744 abort ();
02745
02746 if (GET_MODE (op) != innermode
02747 && GET_MODE (op) != VOIDmode)
02748 abort ();
02749
02750 if (byte % GET_MODE_SIZE (outermode)
02751 || byte >= GET_MODE_SIZE (innermode))
02752 abort ();
02753
02754 if (GET_CODE (op) == QUEUED)
02755 return NULL_RTX;
02756
02757 new = simplify_subreg (outermode, op, innermode, byte);
02758 if (new)
02759 return new;
02760
02761 if (GET_CODE (op) == SUBREG || GET_MODE (op) == VOIDmode)
02762 return NULL_RTX;
02763
02764 return gen_rtx_SUBREG (outermode, op, byte);
02765 }
02766
02767
02768
02769
02770
02771
02772
02773
02774
02775
02776
02777
02778
02779
02780
02781
02782
02783
02784
02785
02786
02787
02788
02789
02790
02791
02792
02793
02794
02795
02796
02797
02798
02799
02800
02801
02802
02803
02804
02805
02806 rtx
02807 simplify_rtx (x)
02808 rtx x;
02809 {
02810 enum rtx_code code = GET_CODE (x);
02811 enum machine_mode mode = GET_MODE (x);
02812
02813 switch (GET_RTX_CLASS (code))
02814 {
02815 case '1':
02816 return simplify_unary_operation (code, mode,
02817 XEXP (x, 0), GET_MODE (XEXP (x, 0)));
02818 case 'c':
02819 if (swap_commutative_operands_p (XEXP (x, 0), XEXP (x, 1)))
02820 {
02821 rtx tem;
02822
02823 tem = XEXP (x, 0);
02824 XEXP (x, 0) = XEXP (x, 1);
02825 XEXP (x, 1) = tem;
02826 return simplify_binary_operation (code, mode,
02827 XEXP (x, 0), XEXP (x, 1));
02828 }
02829
02830 case '2':
02831 return simplify_binary_operation (code, mode, XEXP (x, 0), XEXP (x, 1));
02832
02833 case '3':
02834 case 'b':
02835 return simplify_ternary_operation (code, mode, GET_MODE (XEXP (x, 0)),
02836 XEXP (x, 0), XEXP (x, 1),
02837 XEXP (x, 2));
02838
02839 case '<':
02840 return simplify_relational_operation (code,
02841 ((GET_MODE (XEXP (x, 0))
02842 != VOIDmode)
02843 ? GET_MODE (XEXP (x, 0))
02844 : GET_MODE (XEXP (x, 1))),
02845 XEXP (x, 0), XEXP (x, 1));
02846 case 'x':
02847
02848 if (code == SUBREG)
02849 return simplify_gen_subreg (mode, SUBREG_REG (x),
02850 GET_MODE (SUBREG_REG (x)),
02851 SUBREG_BYTE (x));
02852 return NULL;
02853 default:
02854 return NULL;
02855 }
02856 }