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