00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "config.h"
00023 #include "system.h"
00024 #include "coretypes.h"
00025 #include "tm.h"
00026 #include "rtl.h"
00027 #include "tree.h"
00028 #include "flags.h"
00029 #include "function.h"
00030 #include "insn-config.h"
00031 #include "insn-attr.h"
00032
00033 #include "expr.h"
00034 #include "optabs.h"
00035 #include "langhooks.h"
00036 #include "ggc.h"
00037
00038 static bool prefer_and_bit_test (enum machine_mode, int);
00039 static void do_jump_by_parts_greater (tree, int, rtx, rtx);
00040 static void do_jump_by_parts_equality (tree, rtx, rtx);
00041 static void do_compare_and_jump (tree, enum rtx_code, enum rtx_code, rtx,
00042 rtx);
00043
00044
00045
00046
00047 void
00048 init_pending_stack_adjust (void)
00049 {
00050 pending_stack_adjust = 0;
00051 }
00052
00053
00054
00055
00056 void
00057 discard_pending_stack_adjust (void)
00058 {
00059 stack_pointer_delta -= pending_stack_adjust;
00060 pending_stack_adjust = 0;
00061 }
00062
00063
00064
00065
00066
00067
00068
00069 void
00070 clear_pending_stack_adjust (void)
00071 {
00072 if (optimize > 0
00073 && (! flag_omit_frame_pointer || current_function_calls_alloca)
00074 && EXIT_IGNORE_STACK
00075 && ! (DECL_INLINE (current_function_decl) && ! flag_no_inline))
00076 discard_pending_stack_adjust ();
00077 }
00078
00079
00080
00081 void
00082 do_pending_stack_adjust (void)
00083 {
00084 if (inhibit_defer_pop == 0)
00085 {
00086 if (pending_stack_adjust != 0)
00087 adjust_stack (GEN_INT (pending_stack_adjust));
00088 pending_stack_adjust = 0;
00089 }
00090 }
00091
00092
00093
00094
00095
00096
00097
00098 void
00099 jumpifnot (tree exp, rtx label)
00100 {
00101 do_jump (exp, label, NULL_RTX);
00102 }
00103
00104
00105
00106 void
00107 jumpif (tree exp, rtx label)
00108 {
00109 do_jump (exp, NULL_RTX, label);
00110 }
00111
00112
00113
00114 static GTY(()) rtx and_reg;
00115 static GTY(()) rtx and_test;
00116 static GTY(()) rtx shift_test;
00117
00118
00119
00120
00121
00122 static bool
00123 prefer_and_bit_test (enum machine_mode mode, int bitnum)
00124 {
00125 if (and_test == 0)
00126 {
00127
00128
00129 and_reg = gen_rtx_REG (mode, FIRST_PSEUDO_REGISTER);
00130 and_test = gen_rtx_AND (mode, and_reg, NULL);
00131 shift_test = gen_rtx_AND (mode, gen_rtx_ASHIFTRT (mode, and_reg, NULL),
00132 const1_rtx);
00133 }
00134 else
00135 {
00136
00137 PUT_MODE (and_reg, mode);
00138 PUT_MODE (and_test, mode);
00139 PUT_MODE (shift_test, mode);
00140 PUT_MODE (XEXP (shift_test, 0), mode);
00141 }
00142
00143
00144 XEXP (and_test, 1) = GEN_INT ((unsigned HOST_WIDE_INT) 1 << bitnum);
00145 XEXP (XEXP (shift_test, 0), 1) = GEN_INT (bitnum);
00146
00147 return (rtx_cost (and_test, IF_THEN_ELSE)
00148 <= rtx_cost (shift_test, IF_THEN_ELSE));
00149 }
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160 void
00161 do_jump (tree exp, rtx if_false_label, rtx if_true_label)
00162 {
00163 enum tree_code code = TREE_CODE (exp);
00164 rtx temp;
00165 int i;
00166 tree type;
00167 enum machine_mode mode;
00168 rtx drop_through_label = 0;
00169
00170 switch (code)
00171 {
00172 case ERROR_MARK:
00173 break;
00174
00175 case INTEGER_CST:
00176 temp = integer_zerop (exp) ? if_false_label : if_true_label;
00177 if (temp)
00178 emit_jump (temp);
00179 break;
00180
00181 #if 0
00182
00183 case ADDR_EXPR:
00184
00185 if (if_true_label)
00186 emit_jump (if_true_label);
00187 break;
00188 #endif
00189
00190 case NOP_EXPR:
00191 if (TREE_CODE (TREE_OPERAND (exp, 0)) == COMPONENT_REF
00192 || TREE_CODE (TREE_OPERAND (exp, 0)) == BIT_FIELD_REF
00193 || TREE_CODE (TREE_OPERAND (exp, 0)) == ARRAY_REF
00194 || TREE_CODE (TREE_OPERAND (exp, 0)) == ARRAY_RANGE_REF)
00195 goto normal;
00196 case CONVERT_EXPR:
00197
00198
00199 if ((TYPE_PRECISION (TREE_TYPE (exp))
00200 < TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (exp, 0)))))
00201 goto normal;
00202 case NON_LVALUE_EXPR:
00203 case ABS_EXPR:
00204 case NEGATE_EXPR:
00205 case LROTATE_EXPR:
00206 case RROTATE_EXPR:
00207
00208 do_jump (TREE_OPERAND (exp, 0), if_false_label, if_true_label);
00209 break;
00210
00211 case BIT_AND_EXPR:
00212
00213
00214
00215 if (integer_onep (TREE_OPERAND (exp, 1)))
00216 {
00217 tree exp0 = TREE_OPERAND (exp, 0);
00218 rtx set_label, clr_label;
00219
00220
00221 while ((TREE_CODE (exp0) == NOP_EXPR
00222 || TREE_CODE (exp0) == CONVERT_EXPR
00223 || TREE_CODE (exp0) == NON_LVALUE_EXPR)
00224 && TREE_OPERAND (exp0, 0) != error_mark_node
00225 && TYPE_PRECISION (TREE_TYPE (exp0))
00226 <= TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (exp0, 0))))
00227 exp0 = TREE_OPERAND (exp0, 0);
00228
00229
00230 if (TREE_CODE (exp0) == BIT_XOR_EXPR
00231 && integer_onep (TREE_OPERAND (exp0, 1)))
00232 {
00233 exp0 = TREE_OPERAND (exp0, 0);
00234 clr_label = if_true_label;
00235 set_label = if_false_label;
00236 }
00237 else
00238 {
00239 clr_label = if_false_label;
00240 set_label = if_true_label;
00241 }
00242
00243 if (TREE_CODE (exp0) == RSHIFT_EXPR)
00244 {
00245 tree arg = TREE_OPERAND (exp0, 0);
00246 tree shift = TREE_OPERAND (exp0, 1);
00247 tree argtype = TREE_TYPE (arg);
00248 if (TREE_CODE (shift) == INTEGER_CST
00249 && compare_tree_int (shift, 0) >= 0
00250 && compare_tree_int (shift, HOST_BITS_PER_WIDE_INT) < 0
00251 && prefer_and_bit_test (TYPE_MODE (argtype),
00252 TREE_INT_CST_LOW (shift)))
00253 {
00254 HOST_WIDE_INT mask = (HOST_WIDE_INT) 1
00255 << TREE_INT_CST_LOW (shift);
00256 do_jump (build2 (BIT_AND_EXPR, argtype, arg,
00257 build_int_cst_type (argtype, mask)),
00258 clr_label, set_label);
00259 break;
00260 }
00261 }
00262 }
00263
00264
00265
00266
00267
00268
00269
00270
00271 if (! SLOW_BYTE_ACCESS
00272 && TREE_CODE (TREE_OPERAND (exp, 1)) == INTEGER_CST
00273 && TYPE_PRECISION (TREE_TYPE (exp)) <= HOST_BITS_PER_WIDE_INT
00274 && (i = tree_floor_log2 (TREE_OPERAND (exp, 1))) >= 0
00275 && (mode = mode_for_size (i + 1, MODE_INT, 0)) != BLKmode
00276 && (type = lang_hooks.types.type_for_mode (mode, 1)) != 0
00277 && TYPE_PRECISION (type) < TYPE_PRECISION (TREE_TYPE (exp))
00278 && (cmp_optab->handlers[(int) TYPE_MODE (type)].insn_code
00279 != CODE_FOR_nothing))
00280 {
00281 do_jump (fold_convert (type, exp), if_false_label, if_true_label);
00282 break;
00283 }
00284 goto normal;
00285
00286 case TRUTH_NOT_EXPR:
00287 do_jump (TREE_OPERAND (exp, 0), if_true_label, if_false_label);
00288 break;
00289
00290 case COND_EXPR:
00291 {
00292 rtx label1 = gen_label_rtx ();
00293 if (!if_true_label || !if_false_label)
00294 {
00295 drop_through_label = gen_label_rtx ();
00296 if (!if_true_label)
00297 if_true_label = drop_through_label;
00298 if (!if_false_label)
00299 if_false_label = drop_through_label;
00300 }
00301
00302 do_pending_stack_adjust ();
00303 do_jump (TREE_OPERAND (exp, 0), label1, NULL_RTX);
00304 do_jump (TREE_OPERAND (exp, 1), if_false_label, if_true_label);
00305 emit_label (label1);
00306 do_jump (TREE_OPERAND (exp, 2), if_false_label, if_true_label);
00307 break;
00308 }
00309
00310 case TRUTH_ANDIF_EXPR:
00311 case TRUTH_ORIF_EXPR:
00312 case COMPOUND_EXPR:
00313
00314 gcc_unreachable ();
00315
00316 case COMPONENT_REF:
00317 case BIT_FIELD_REF:
00318 case ARRAY_REF:
00319 case ARRAY_RANGE_REF:
00320 {
00321 HOST_WIDE_INT bitsize, bitpos;
00322 int unsignedp;
00323 enum machine_mode mode;
00324 tree type;
00325 tree offset;
00326 int volatilep = 0;
00327
00328
00329
00330 get_inner_reference (exp, &bitsize, &bitpos, &offset, &mode,
00331 &unsignedp, &volatilep, false);
00332
00333 type = lang_hooks.types.type_for_size (bitsize, unsignedp);
00334 if (! SLOW_BYTE_ACCESS
00335 && type != 0 && bitsize >= 0
00336 && TYPE_PRECISION (type) < TYPE_PRECISION (TREE_TYPE (exp))
00337 && (cmp_optab->handlers[(int) TYPE_MODE (type)].insn_code
00338 != CODE_FOR_nothing))
00339 {
00340 do_jump (fold_convert (type, exp), if_false_label, if_true_label);
00341 break;
00342 }
00343 goto normal;
00344 }
00345
00346 case EQ_EXPR:
00347 {
00348 tree inner_type = TREE_TYPE (TREE_OPERAND (exp, 0));
00349
00350 gcc_assert (GET_MODE_CLASS (TYPE_MODE (inner_type))
00351 != MODE_COMPLEX_FLOAT);
00352 gcc_assert (GET_MODE_CLASS (TYPE_MODE (inner_type))
00353 != MODE_COMPLEX_INT);
00354
00355 if (integer_zerop (TREE_OPERAND (exp, 1)))
00356 do_jump (TREE_OPERAND (exp, 0), if_true_label, if_false_label);
00357 else if (GET_MODE_CLASS (TYPE_MODE (inner_type)) == MODE_INT
00358 && !can_compare_p (EQ, TYPE_MODE (inner_type), ccp_jump))
00359 do_jump_by_parts_equality (exp, if_false_label, if_true_label);
00360 else
00361 do_compare_and_jump (exp, EQ, EQ, if_false_label, if_true_label);
00362 break;
00363 }
00364
00365 case MINUS_EXPR:
00366
00367 exp = build2 (NE_EXPR, TREE_TYPE (exp),
00368 TREE_OPERAND (exp, 0),
00369 TREE_OPERAND (exp, 1));
00370
00371 case NE_EXPR:
00372 {
00373 tree inner_type = TREE_TYPE (TREE_OPERAND (exp, 0));
00374
00375 gcc_assert (GET_MODE_CLASS (TYPE_MODE (inner_type))
00376 != MODE_COMPLEX_FLOAT);
00377 gcc_assert (GET_MODE_CLASS (TYPE_MODE (inner_type))
00378 != MODE_COMPLEX_INT);
00379
00380 if (integer_zerop (TREE_OPERAND (exp, 1)))
00381 do_jump (TREE_OPERAND (exp, 0), if_false_label, if_true_label);
00382 else if (GET_MODE_CLASS (TYPE_MODE (inner_type)) == MODE_INT
00383 && !can_compare_p (NE, TYPE_MODE (inner_type), ccp_jump))
00384 do_jump_by_parts_equality (exp, if_true_label, if_false_label);
00385 else
00386 do_compare_and_jump (exp, NE, NE, if_false_label, if_true_label);
00387 break;
00388 }
00389
00390 case LT_EXPR:
00391 mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)));
00392 if (GET_MODE_CLASS (mode) == MODE_INT
00393 && ! can_compare_p (LT, mode, ccp_jump))
00394 do_jump_by_parts_greater (exp, 1, if_false_label, if_true_label);
00395 else
00396 do_compare_and_jump (exp, LT, LTU, if_false_label, if_true_label);
00397 break;
00398
00399 case LE_EXPR:
00400 mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)));
00401 if (GET_MODE_CLASS (mode) == MODE_INT
00402 && ! can_compare_p (LE, mode, ccp_jump))
00403 do_jump_by_parts_greater (exp, 0, if_true_label, if_false_label);
00404 else
00405 do_compare_and_jump (exp, LE, LEU, if_false_label, if_true_label);
00406 break;
00407
00408 case GT_EXPR:
00409 mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)));
00410 if (GET_MODE_CLASS (mode) == MODE_INT
00411 && ! can_compare_p (GT, mode, ccp_jump))
00412 do_jump_by_parts_greater (exp, 0, if_false_label, if_true_label);
00413 else
00414 do_compare_and_jump (exp, GT, GTU, if_false_label, if_true_label);
00415 break;
00416
00417 case GE_EXPR:
00418 mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)));
00419 if (GET_MODE_CLASS (mode) == MODE_INT
00420 && ! can_compare_p (GE, mode, ccp_jump))
00421 do_jump_by_parts_greater (exp, 1, if_true_label, if_false_label);
00422 else
00423 do_compare_and_jump (exp, GE, GEU, if_false_label, if_true_label);
00424 break;
00425
00426 case UNORDERED_EXPR:
00427 case ORDERED_EXPR:
00428 {
00429 enum rtx_code cmp, rcmp;
00430 int do_rev;
00431
00432 if (code == UNORDERED_EXPR)
00433 cmp = UNORDERED, rcmp = ORDERED;
00434 else
00435 cmp = ORDERED, rcmp = UNORDERED;
00436 mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)));
00437
00438 do_rev = 0;
00439 if (! can_compare_p (cmp, mode, ccp_jump)
00440 && (can_compare_p (rcmp, mode, ccp_jump)
00441
00442
00443 || rcmp == UNORDERED))
00444 do_rev = 1;
00445
00446 if (! do_rev)
00447 do_compare_and_jump (exp, cmp, cmp, if_false_label, if_true_label);
00448 else
00449 do_compare_and_jump (exp, rcmp, rcmp, if_true_label, if_false_label);
00450 }
00451 break;
00452
00453 {
00454 enum rtx_code rcode1;
00455 enum tree_code tcode1, tcode2;
00456
00457 case UNLT_EXPR:
00458 rcode1 = UNLT;
00459 tcode1 = UNORDERED_EXPR;
00460 tcode2 = LT_EXPR;
00461 goto unordered_bcc;
00462 case UNLE_EXPR:
00463 rcode1 = UNLE;
00464 tcode1 = UNORDERED_EXPR;
00465 tcode2 = LE_EXPR;
00466 goto unordered_bcc;
00467 case UNGT_EXPR:
00468 rcode1 = UNGT;
00469 tcode1 = UNORDERED_EXPR;
00470 tcode2 = GT_EXPR;
00471 goto unordered_bcc;
00472 case UNGE_EXPR:
00473 rcode1 = UNGE;
00474 tcode1 = UNORDERED_EXPR;
00475 tcode2 = GE_EXPR;
00476 goto unordered_bcc;
00477 case UNEQ_EXPR:
00478 rcode1 = UNEQ;
00479 tcode1 = UNORDERED_EXPR;
00480 tcode2 = EQ_EXPR;
00481 goto unordered_bcc;
00482 case LTGT_EXPR:
00483
00484
00485 rcode1 = LTGT;
00486 tcode1 = LT_EXPR;
00487 tcode2 = GT_EXPR;
00488 goto unordered_bcc;
00489
00490 unordered_bcc:
00491 mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)));
00492 if (can_compare_p (rcode1, mode, ccp_jump))
00493 do_compare_and_jump (exp, rcode1, rcode1, if_false_label,
00494 if_true_label);
00495 else
00496 {
00497 tree op0 = save_expr (TREE_OPERAND (exp, 0));
00498 tree op1 = save_expr (TREE_OPERAND (exp, 1));
00499 tree cmp0, cmp1;
00500
00501
00502
00503 if (if_true_label == 0)
00504 drop_through_label = if_true_label = gen_label_rtx ();
00505
00506 cmp0 = fold_build2 (tcode1, TREE_TYPE (exp), op0, op1);
00507 cmp1 = fold_build2 (tcode2, TREE_TYPE (exp), op0, op1);
00508 do_jump (cmp0, 0, if_true_label);
00509 do_jump (cmp1, if_false_label, if_true_label);
00510 }
00511 }
00512 break;
00513
00514 case TRUTH_AND_EXPR:
00515
00516
00517
00518 if (BRANCH_COST >= 4 || TREE_SIDE_EFFECTS (TREE_OPERAND (exp, 1)))
00519 goto normal;
00520
00521 if (if_false_label == NULL_RTX)
00522 {
00523 drop_through_label = gen_label_rtx ();
00524 do_jump (TREE_OPERAND (exp, 0), drop_through_label, NULL_RTX);
00525 do_jump (TREE_OPERAND (exp, 1), NULL_RTX, if_true_label);
00526 }
00527 else
00528 {
00529 do_jump (TREE_OPERAND (exp, 0), if_false_label, NULL_RTX);
00530 do_jump (TREE_OPERAND (exp, 1), if_false_label, if_true_label);
00531 }
00532 break;
00533
00534 case TRUTH_OR_EXPR:
00535
00536
00537
00538 if (BRANCH_COST >= 4 || TREE_SIDE_EFFECTS (TREE_OPERAND (exp, 1)))
00539 goto normal;
00540
00541 if (if_true_label == NULL_RTX)
00542 {
00543 drop_through_label = gen_label_rtx ();
00544 do_jump (TREE_OPERAND (exp, 0), NULL_RTX, drop_through_label);
00545 do_jump (TREE_OPERAND (exp, 1), if_false_label, NULL_RTX);
00546 }
00547 else
00548 {
00549 do_jump (TREE_OPERAND (exp, 0), NULL_RTX, if_true_label);
00550 do_jump (TREE_OPERAND (exp, 1), if_false_label, if_true_label);
00551 }
00552 break;
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562 case CALL_EXPR:
00563
00564 {
00565 tree fndecl = get_callee_fndecl (exp);
00566 tree arglist = TREE_OPERAND (exp, 1);
00567
00568 if (fndecl
00569 && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
00570 && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_EXPECT
00571 && arglist != NULL_TREE
00572 && TREE_CHAIN (arglist) != NULL_TREE)
00573 {
00574 rtx seq = expand_builtin_expect_jump (exp, if_false_label,
00575 if_true_label);
00576
00577 if (seq != NULL_RTX)
00578 {
00579 emit_insn (seq);
00580 return;
00581 }
00582 }
00583 }
00584
00585
00586 default:
00587 normal:
00588 temp = expand_normal (exp);
00589 do_pending_stack_adjust ();
00590
00591 if (GET_CODE (temp) == SUBREG)
00592 {
00593
00594 if (SUBREG_PROMOTED_VAR_P (temp)
00595 && REG_P (XEXP (temp, 0)))
00596 temp = XEXP (temp, 0);
00597 else
00598 temp = copy_to_reg (temp);
00599 }
00600 do_compare_rtx_and_jump (temp, CONST0_RTX (GET_MODE (temp)),
00601 NE, TYPE_UNSIGNED (TREE_TYPE (exp)),
00602 GET_MODE (temp), NULL_RTX,
00603 if_false_label, if_true_label);
00604 }
00605
00606 if (drop_through_label)
00607 {
00608 do_pending_stack_adjust ();
00609 emit_label (drop_through_label);
00610 }
00611 }
00612
00613
00614
00615
00616
00617 static void
00618 do_jump_by_parts_greater_rtx (enum machine_mode mode, int unsignedp, rtx op0,
00619 rtx op1, rtx if_false_label, rtx if_true_label)
00620 {
00621 int nwords = (GET_MODE_SIZE (mode) / UNITS_PER_WORD);
00622 rtx drop_through_label = 0;
00623 int i;
00624
00625 if (! if_true_label || ! if_false_label)
00626 drop_through_label = gen_label_rtx ();
00627 if (! if_true_label)
00628 if_true_label = drop_through_label;
00629 if (! if_false_label)
00630 if_false_label = drop_through_label;
00631
00632
00633 for (i = 0; i < nwords; i++)
00634 {
00635 rtx op0_word, op1_word;
00636
00637 if (WORDS_BIG_ENDIAN)
00638 {
00639 op0_word = operand_subword_force (op0, i, mode);
00640 op1_word = operand_subword_force (op1, i, mode);
00641 }
00642 else
00643 {
00644 op0_word = operand_subword_force (op0, nwords - 1 - i, mode);
00645 op1_word = operand_subword_force (op1, nwords - 1 - i, mode);
00646 }
00647
00648
00649 do_compare_rtx_and_jump (op0_word, op1_word, GT,
00650 (unsignedp || i > 0), word_mode, NULL_RTX,
00651 NULL_RTX, if_true_label);
00652
00653
00654 do_compare_rtx_and_jump (op0_word, op1_word, NE, unsignedp, word_mode,
00655 NULL_RTX, NULL_RTX, if_false_label);
00656 }
00657
00658 if (if_false_label)
00659 emit_jump (if_false_label);
00660 if (drop_through_label)
00661 emit_label (drop_through_label);
00662 }
00663
00664
00665
00666
00667
00668
00669 static void
00670 do_jump_by_parts_greater (tree exp, int swap, rtx if_false_label,
00671 rtx if_true_label)
00672 {
00673 rtx op0 = expand_normal (TREE_OPERAND (exp, swap));
00674 rtx op1 = expand_normal (TREE_OPERAND (exp, !swap));
00675 enum machine_mode mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)));
00676 int unsignedp = TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (exp, 0)));
00677
00678 do_jump_by_parts_greater_rtx (mode, unsignedp, op0, op1, if_false_label,
00679 if_true_label);
00680 }
00681
00682
00683
00684
00685
00686
00687 static void
00688 do_jump_by_parts_zero_rtx (enum machine_mode mode, rtx op0,
00689 rtx if_false_label, rtx if_true_label)
00690 {
00691 int nwords = GET_MODE_SIZE (mode) / UNITS_PER_WORD;
00692 rtx part;
00693 int i;
00694 rtx drop_through_label = 0;
00695
00696
00697
00698
00699
00700
00701 part = gen_reg_rtx (word_mode);
00702 emit_move_insn (part, operand_subword_force (op0, 0, GET_MODE (op0)));
00703 for (i = 1; i < nwords && part != 0; i++)
00704 part = expand_binop (word_mode, ior_optab, part,
00705 operand_subword_force (op0, i, GET_MODE (op0)),
00706 part, 1, OPTAB_WIDEN);
00707
00708 if (part != 0)
00709 {
00710 do_compare_rtx_and_jump (part, const0_rtx, EQ, 1, word_mode,
00711 NULL_RTX, if_false_label, if_true_label);
00712
00713 return;
00714 }
00715
00716
00717 if (! if_false_label)
00718 drop_through_label = if_false_label = gen_label_rtx ();
00719
00720 for (i = 0; i < nwords; i++)
00721 do_compare_rtx_and_jump (operand_subword_force (op0, i, GET_MODE (op0)),
00722 const0_rtx, EQ, 1, word_mode, NULL_RTX,
00723 if_false_label, NULL_RTX);
00724
00725 if (if_true_label)
00726 emit_jump (if_true_label);
00727
00728 if (drop_through_label)
00729 emit_label (drop_through_label);
00730 }
00731
00732
00733
00734
00735
00736
00737 static void
00738 do_jump_by_parts_equality_rtx (enum machine_mode mode, rtx op0, rtx op1,
00739 rtx if_false_label, rtx if_true_label)
00740 {
00741 int nwords = (GET_MODE_SIZE (mode) / UNITS_PER_WORD);
00742 rtx drop_through_label = 0;
00743 int i;
00744
00745 if (op1 == const0_rtx)
00746 {
00747 do_jump_by_parts_zero_rtx (mode, op0, if_false_label, if_true_label);
00748 return;
00749 }
00750 else if (op0 == const0_rtx)
00751 {
00752 do_jump_by_parts_zero_rtx (mode, op1, if_false_label, if_true_label);
00753 return;
00754 }
00755
00756 if (! if_false_label)
00757 drop_through_label = if_false_label = gen_label_rtx ();
00758
00759 for (i = 0; i < nwords; i++)
00760 do_compare_rtx_and_jump (operand_subword_force (op0, i, mode),
00761 operand_subword_force (op1, i, mode),
00762 EQ, 0, word_mode, NULL_RTX,
00763 if_false_label, NULL_RTX);
00764
00765 if (if_true_label)
00766 emit_jump (if_true_label);
00767 if (drop_through_label)
00768 emit_label (drop_through_label);
00769 }
00770
00771
00772
00773
00774 static void
00775 do_jump_by_parts_equality (tree exp, rtx if_false_label, rtx if_true_label)
00776 {
00777 rtx op0 = expand_normal (TREE_OPERAND (exp, 0));
00778 rtx op1 = expand_normal (TREE_OPERAND (exp, 1));
00779 enum machine_mode mode = TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp, 0)));
00780 do_jump_by_parts_equality_rtx (mode, op0, op1, if_false_label,
00781 if_true_label);
00782 }
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796 rtx
00797 compare_from_rtx (rtx op0, rtx op1, enum rtx_code code, int unsignedp,
00798 enum machine_mode mode, rtx size)
00799 {
00800 rtx tem;
00801
00802
00803
00804
00805 if (swap_commutative_operands_p (op0, op1))
00806 {
00807 tem = op0;
00808 op0 = op1;
00809 op1 = tem;
00810 code = swap_condition (code);
00811 }
00812
00813 do_pending_stack_adjust ();
00814
00815 code = unsignedp ? unsigned_condition (code) : code;
00816 tem = simplify_relational_operation (code, VOIDmode, mode, op0, op1);
00817 if (tem)
00818 {
00819 if (CONSTANT_P (tem))
00820 return tem;
00821
00822 if (COMPARISON_P (tem))
00823 {
00824 code = GET_CODE (tem);
00825 op0 = XEXP (tem, 0);
00826 op1 = XEXP (tem, 1);
00827 mode = GET_MODE (op0);
00828 unsignedp = (code == GTU || code == LTU
00829 || code == GEU || code == LEU);
00830 }
00831 }
00832
00833 emit_cmp_insn (op0, op1, code, size, mode, unsignedp);
00834
00835 #if HAVE_cc0
00836 return gen_rtx_fmt_ee (code, VOIDmode, cc0_rtx, const0_rtx);
00837 #else
00838 return gen_rtx_fmt_ee (code, VOIDmode, op0, op1);
00839 #endif
00840 }
00841
00842
00843
00844
00845
00846
00847
00848 void
00849 do_compare_rtx_and_jump (rtx op0, rtx op1, enum rtx_code code, int unsignedp,
00850 enum machine_mode mode, rtx size, rtx if_false_label,
00851 rtx if_true_label)
00852 {
00853 rtx tem;
00854 int dummy_true_label = 0;
00855
00856
00857
00858 if (! if_true_label && ! FLOAT_MODE_P (mode))
00859 {
00860 if_true_label = if_false_label;
00861 if_false_label = 0;
00862 code = reverse_condition (code);
00863 }
00864
00865
00866
00867
00868 if (swap_commutative_operands_p (op0, op1))
00869 {
00870 tem = op0;
00871 op0 = op1;
00872 op1 = tem;
00873 code = swap_condition (code);
00874 }
00875
00876 do_pending_stack_adjust ();
00877
00878 code = unsignedp ? unsigned_condition (code) : code;
00879 if (0 != (tem = simplify_relational_operation (code, mode, VOIDmode,
00880 op0, op1)))
00881 {
00882 if (CONSTANT_P (tem))
00883 {
00884 rtx label = (tem == const0_rtx || tem == CONST0_RTX (mode))
00885 ? if_false_label : if_true_label;
00886 if (label)
00887 emit_jump (label);
00888 return;
00889 }
00890
00891 code = GET_CODE (tem);
00892 mode = GET_MODE (tem);
00893 op0 = XEXP (tem, 0);
00894 op1 = XEXP (tem, 1);
00895 unsignedp = (code == GTU || code == LTU || code == GEU || code == LEU);
00896 }
00897
00898
00899 if (! if_true_label)
00900 {
00901 dummy_true_label = 1;
00902 if_true_label = gen_label_rtx ();
00903 }
00904
00905 if (GET_MODE_CLASS (mode) == MODE_INT
00906 && ! can_compare_p (code, mode, ccp_jump))
00907 {
00908 switch (code)
00909 {
00910 case LTU:
00911 do_jump_by_parts_greater_rtx (mode, 1, op1, op0,
00912 if_false_label, if_true_label);
00913 break;
00914
00915 case LEU:
00916 do_jump_by_parts_greater_rtx (mode, 1, op0, op1,
00917 if_true_label, if_false_label);
00918 break;
00919
00920 case GTU:
00921 do_jump_by_parts_greater_rtx (mode, 1, op0, op1,
00922 if_false_label, if_true_label);
00923 break;
00924
00925 case GEU:
00926 do_jump_by_parts_greater_rtx (mode, 1, op1, op0,
00927 if_true_label, if_false_label);
00928 break;
00929
00930 case LT:
00931 do_jump_by_parts_greater_rtx (mode, 0, op1, op0,
00932 if_false_label, if_true_label);
00933 break;
00934
00935 case LE:
00936 do_jump_by_parts_greater_rtx (mode, 0, op0, op1,
00937 if_true_label, if_false_label);
00938 break;
00939
00940 case GT:
00941 do_jump_by_parts_greater_rtx (mode, 0, op0, op1,
00942 if_false_label, if_true_label);
00943 break;
00944
00945 case GE:
00946 do_jump_by_parts_greater_rtx (mode, 0, op1, op0,
00947 if_true_label, if_false_label);
00948 break;
00949
00950 case EQ:
00951 do_jump_by_parts_equality_rtx (mode, op0, op1, if_false_label,
00952 if_true_label);
00953 break;
00954
00955 case NE:
00956 do_jump_by_parts_equality_rtx (mode, op0, op1, if_true_label,
00957 if_false_label);
00958 break;
00959
00960 default:
00961 gcc_unreachable ();
00962 }
00963 }
00964 else
00965 emit_cmp_and_jump_insns (op0, op1, code, size, mode, unsignedp,
00966 if_true_label);
00967
00968 if (if_false_label)
00969 emit_jump (if_false_label);
00970 if (dummy_true_label)
00971 emit_label (if_true_label);
00972 }
00973
00974
00975
00976
00977
00978
00979
00980
00981
00982
00983
00984 static void
00985 do_compare_and_jump (tree exp, enum rtx_code signed_code,
00986 enum rtx_code unsigned_code, rtx if_false_label,
00987 rtx if_true_label)
00988 {
00989 rtx op0, op1;
00990 tree type;
00991 enum machine_mode mode;
00992 int unsignedp;
00993 enum rtx_code code;
00994
00995
00996 op0 = expand_normal (TREE_OPERAND (exp, 0));
00997 if (TREE_CODE (TREE_OPERAND (exp, 0)) == ERROR_MARK)
00998 return;
00999
01000 op1 = expand_normal (TREE_OPERAND (exp, 1));
01001 if (TREE_CODE (TREE_OPERAND (exp, 1)) == ERROR_MARK)
01002 return;
01003
01004 type = TREE_TYPE (TREE_OPERAND (exp, 0));
01005 mode = TYPE_MODE (type);
01006 if (TREE_CODE (TREE_OPERAND (exp, 0)) == INTEGER_CST
01007 && (TREE_CODE (TREE_OPERAND (exp, 1)) != INTEGER_CST
01008 || (GET_MODE_BITSIZE (mode)
01009 > GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (TREE_OPERAND (exp,
01010 1)))))))
01011 {
01012
01013
01014 type = TREE_TYPE (TREE_OPERAND (exp, 1));
01015 mode = TYPE_MODE (type);
01016 }
01017 unsignedp = TYPE_UNSIGNED (type);
01018 code = unsignedp ? unsigned_code : signed_code;
01019
01020 #ifdef HAVE_canonicalize_funcptr_for_compare
01021
01022
01023
01024
01025
01026 if (HAVE_canonicalize_funcptr_for_compare
01027 && TREE_CODE (TREE_TYPE (TREE_OPERAND (exp, 0))) == POINTER_TYPE
01028 && TREE_CODE (TREE_TYPE (TREE_TYPE (TREE_OPERAND (exp, 0))))
01029 == FUNCTION_TYPE
01030 && TREE_CODE (TREE_TYPE (TREE_OPERAND (exp, 1))) == POINTER_TYPE
01031 && TREE_CODE (TREE_TYPE (TREE_TYPE (TREE_OPERAND (exp, 1))))
01032 == FUNCTION_TYPE)
01033 {
01034 rtx new_op0 = gen_reg_rtx (mode);
01035 rtx new_op1 = gen_reg_rtx (mode);
01036
01037 emit_insn (gen_canonicalize_funcptr_for_compare (new_op0, op0));
01038 op0 = new_op0;
01039
01040 emit_insn (gen_canonicalize_funcptr_for_compare (new_op1, op1));
01041 op1 = new_op1;
01042 }
01043 #endif
01044
01045 do_compare_rtx_and_jump (op0, op1, code, unsignedp, mode,
01046 ((mode == BLKmode)
01047 ? expr_size (TREE_OPERAND (exp, 0)) : NULL_RTX),
01048 if_false_label, if_true_label);
01049 }
01050
01051 #include "gt-dojump.h"