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