rtx compare_from_rtx (rtx op0, rtx op1, enum rtx_code code, int unsignedp, enum machine_mode mode, rtx size) { enum rtx_code ucode; rtx tem; /* If one operand is constant, make it the second one. Only do this if the other operand is not constant as well. */ if (swap_commutative_operands_p (op0, op1)) { tem = op0; op0 = op1; op1 = tem; code = swap_condition (code); } if (flag_force_mem) { op0 = force_not_mem (op0); op1 = force_not_mem (op1); } do_pending_stack_adjust (); ucode = unsignedp ? unsigned_condition (code) : code; if ((tem = simplify_relational_operation (ucode, mode, op0, op1)) != 0) return tem; #if 0 /* There's no need to do this now that combine.c can eliminate lots of sign extensions. This can be less efficient in certain cases on other machines. */ /* If this is a signed equality comparison, we can do it as an unsigned comparison since zero-extension is cheaper than sign extension and comparisons with zero are done as unsigned. This is the case even on machines that can do fast sign extension, since zero-extension is easier to combine with other operations than sign-extension is. If we are comparing against a constant, we must convert it to what it would look like unsigned. */ if ((code == EQ || code == NE) && ! unsignedp && GET_MODE_BITSIZE (GET_MODE (op0)) <= HOST_BITS_PER_WIDE_INT) { if (GET_CODE (op1) == CONST_INT && (INTVAL (op1) & GET_MODE_MASK (GET_MODE (op0))) != INTVAL (op1)) op1 = GEN_INT (INTVAL (op1) & GET_MODE_MASK (GET_MODE (op0))); unsignedp = 1; } #endif emit_cmp_insn (op0, op1, code, size, mode, unsignedp); #if HAVE_cc0 return gen_rtx_fmt_ee (code, VOIDmode, cc0_rtx, const0_rtx); #else return gen_rtx_fmt_ee (code, VOIDmode, op0, op1); #endif }
rtx compare_from_rtx (rtx op0, rtx op1, enum rtx_code code, int unsignedp, enum machine_mode mode, rtx size) { rtx tem; /* If one operand is constant, make it the second one. Only do this if the other operand is not constant as well. */ if (swap_commutative_operands_p (op0, op1)) { tem = op0; op0 = op1; op1 = tem; code = swap_condition (code); } do_pending_stack_adjust (); code = unsignedp ? unsigned_condition (code) : code; tem = simplify_relational_operation (code, VOIDmode, mode, op0, op1); if (tem) { if (CONSTANT_P (tem)) return tem; if (COMPARISON_P (tem)) { code = GET_CODE (tem); op0 = XEXP (tem, 0); op1 = XEXP (tem, 1); mode = GET_MODE (op0); unsignedp = (code == GTU || code == LTU || code == GEU || code == LEU); } } emit_cmp_insn (op0, op1, code, size, mode, unsignedp); #if HAVE_cc0 return gen_rtx_fmt_ee (code, VOIDmode, cc0_rtx, const0_rtx); #else return gen_rtx_fmt_ee (code, VOIDmode, op0, op1); #endif }
void do_compare_rtx_and_jump (rtx op0, rtx op1, enum rtx_code code, int unsignedp, enum machine_mode mode, rtx size, rtx if_false_label, rtx if_true_label, int prob) { rtx tem; rtx dummy_label = NULL_RTX; rtx last; /* Reverse the comparison if that is safe and we want to jump if it is false. Also convert to the reverse comparison if the target can implement it. */ if ((! if_true_label || ! can_compare_p (code, mode, ccp_jump)) && (! FLOAT_MODE_P (mode) || code == ORDERED || code == UNORDERED || (! HONOR_NANS (mode) && (code == LTGT || code == UNEQ)) || (! HONOR_SNANS (mode) && (code == EQ || code == NE)))) { enum rtx_code rcode; if (FLOAT_MODE_P (mode)) rcode = reverse_condition_maybe_unordered (code); else rcode = reverse_condition (code); /* Canonicalize to UNORDERED for the libcall. */ if (can_compare_p (rcode, mode, ccp_jump) || (code == ORDERED && ! can_compare_p (ORDERED, mode, ccp_jump))) { tem = if_true_label; if_true_label = if_false_label; if_false_label = tem; code = rcode; prob = inv (prob); } } /* If one operand is constant, make it the second one. Only do this if the other operand is not constant as well. */ if (swap_commutative_operands_p (op0, op1)) { tem = op0; op0 = op1; op1 = tem; code = swap_condition (code); } do_pending_stack_adjust (); code = unsignedp ? unsigned_condition (code) : code; if (0 != (tem = simplify_relational_operation (code, mode, VOIDmode, op0, op1))) { if (CONSTANT_P (tem)) { rtx label = (tem == const0_rtx || tem == CONST0_RTX (mode)) ? if_false_label : if_true_label; if (label) emit_jump (label); return; } code = GET_CODE (tem); mode = GET_MODE (tem); op0 = XEXP (tem, 0); op1 = XEXP (tem, 1); unsignedp = (code == GTU || code == LTU || code == GEU || code == LEU); } if (! if_true_label) dummy_label = if_true_label = gen_label_rtx (); if (GET_MODE_CLASS (mode) == MODE_INT && ! can_compare_p (code, mode, ccp_jump)) { switch (code) { case LTU: do_jump_by_parts_greater_rtx (mode, 1, op1, op0, if_false_label, if_true_label, prob); break; case LEU: do_jump_by_parts_greater_rtx (mode, 1, op0, op1, if_true_label, if_false_label, inv (prob)); break; case GTU: do_jump_by_parts_greater_rtx (mode, 1, op0, op1, if_false_label, if_true_label, prob); break; case GEU: do_jump_by_parts_greater_rtx (mode, 1, op1, op0, if_true_label, if_false_label, inv (prob)); break; case LT: do_jump_by_parts_greater_rtx (mode, 0, op1, op0, if_false_label, if_true_label, prob); break; case LE: do_jump_by_parts_greater_rtx (mode, 0, op0, op1, if_true_label, if_false_label, inv (prob)); break; case GT: do_jump_by_parts_greater_rtx (mode, 0, op0, op1, if_false_label, if_true_label, prob); break; case GE: do_jump_by_parts_greater_rtx (mode, 0, op1, op0, if_true_label, if_false_label, inv (prob)); break; case EQ: do_jump_by_parts_equality_rtx (mode, op0, op1, if_false_label, if_true_label, prob); break; case NE: do_jump_by_parts_equality_rtx (mode, op0, op1, if_true_label, if_false_label, inv (prob)); break; default: gcc_unreachable (); } } else { if (GET_MODE_CLASS (mode) == MODE_FLOAT && ! can_compare_p (code, mode, ccp_jump) && can_compare_p (swap_condition (code), mode, ccp_jump)) { rtx tmp; code = swap_condition (code); tmp = op0; op0 = op1; op1 = tmp; } else if (GET_MODE_CLASS (mode) == MODE_FLOAT && ! can_compare_p (code, mode, ccp_jump) /* Never split ORDERED and UNORDERED. These must be implemented. */ && (code != ORDERED && code != UNORDERED) /* Split a floating-point comparison if we can jump on other conditions... */ && (have_insn_for (COMPARE, mode) /* ... or if there is no libcall for it. */ || code_to_optab[code] == NULL)) { enum rtx_code first_code; bool and_them = split_comparison (code, mode, &first_code, &code); /* If there are no NaNs, the first comparison should always fall through. */ if (!HONOR_NANS (mode)) gcc_assert (first_code == (and_them ? ORDERED : UNORDERED)); else { if (and_them) { rtx dest_label; /* If we only jump if true, just bypass the second jump. */ if (! if_false_label) { if (! dummy_label) dummy_label = gen_label_rtx (); dest_label = dummy_label; } else dest_label = if_false_label; do_compare_rtx_and_jump (op0, op1, first_code, unsignedp, mode, size, dest_label, NULL_RTX, prob); } else do_compare_rtx_and_jump (op0, op1, first_code, unsignedp, mode, size, NULL_RTX, if_true_label, prob); } } last = get_last_insn (); emit_cmp_and_jump_insns (op0, op1, code, size, mode, unsignedp, if_true_label); if (prob != -1 && profile_status != PROFILE_ABSENT) { for (last = NEXT_INSN (last); last && NEXT_INSN (last); last = NEXT_INSN (last)) if (JUMP_P (last)) break; if (!last || !JUMP_P (last) || NEXT_INSN (last) || !any_condjump_p (last)) { if (dump_file) fprintf (dump_file, "Failed to add probability note\n"); } else { gcc_assert (!find_reg_note (last, REG_BR_PROB, 0)); add_reg_note (last, REG_BR_PROB, GEN_INT (prob)); } } } if (if_false_label) emit_jump (if_false_label); if (dummy_label) emit_label (dummy_label); }
void do_compare_rtx_and_jump (rtx op0, rtx op1, enum rtx_code code, int unsignedp, enum machine_mode mode, rtx size, rtx if_false_label, rtx if_true_label) { rtx tem; int dummy_true_label = 0; /* Reverse the comparison if that is safe and we want to jump if it is false. */ if (! if_true_label && ! FLOAT_MODE_P (mode)) { if_true_label = if_false_label; if_false_label = 0; code = reverse_condition (code); } /* If one operand is constant, make it the second one. Only do this if the other operand is not constant as well. */ if (swap_commutative_operands_p (op0, op1)) { tem = op0; op0 = op1; op1 = tem; code = swap_condition (code); } do_pending_stack_adjust (); code = unsignedp ? unsigned_condition (code) : code; if (0 != (tem = simplify_relational_operation (code, mode, VOIDmode, op0, op1))) { if (CONSTANT_P (tem)) { rtx label = (tem == const0_rtx || tem == CONST0_RTX (mode)) ? if_false_label : if_true_label; if (label) emit_jump (label); return; } code = GET_CODE (tem); mode = GET_MODE (tem); op0 = XEXP (tem, 0); op1 = XEXP (tem, 1); unsignedp = (code == GTU || code == LTU || code == GEU || code == LEU); } if (! if_true_label) { dummy_true_label = 1; if_true_label = gen_label_rtx (); } if (GET_MODE_CLASS (mode) == MODE_INT && ! can_compare_p (code, mode, ccp_jump)) { switch (code) { case LTU: do_jump_by_parts_greater_rtx (mode, 1, op1, op0, if_false_label, if_true_label); break; case LEU: do_jump_by_parts_greater_rtx (mode, 1, op0, op1, if_true_label, if_false_label); break; case GTU: do_jump_by_parts_greater_rtx (mode, 1, op0, op1, if_false_label, if_true_label); break; case GEU: do_jump_by_parts_greater_rtx (mode, 1, op1, op0, if_true_label, if_false_label); break; case LT: do_jump_by_parts_greater_rtx (mode, 0, op1, op0, if_false_label, if_true_label); break; case LE: do_jump_by_parts_greater_rtx (mode, 0, op0, op1, if_true_label, if_false_label); break; case GT: do_jump_by_parts_greater_rtx (mode, 0, op0, op1, if_false_label, if_true_label); break; case GE: do_jump_by_parts_greater_rtx (mode, 0, op1, op0, if_true_label, if_false_label); break; case EQ: do_jump_by_parts_equality_rtx (mode, op0, op1, if_false_label, if_true_label); break; case NE: do_jump_by_parts_equality_rtx (mode, op0, op1, if_true_label, if_false_label); break; default: gcc_unreachable (); } } else emit_cmp_and_jump_insns (op0, op1, code, size, mode, unsignedp, if_true_label); if (if_false_label) emit_jump (if_false_label); if (dummy_true_label) emit_label (if_true_label); }
void do_compare_rtx_and_jump (rtx op0, rtx op1, enum rtx_code code, int unsignedp, enum machine_mode mode, rtx size, rtx if_false_label, rtx if_true_label) { enum rtx_code ucode; rtx tem; int dummy_true_label = 0; /* Reverse the comparison if that is safe and we want to jump if it is false. */ if (! if_true_label && ! FLOAT_MODE_P (mode)) { if_true_label = if_false_label; if_false_label = 0; code = reverse_condition (code); } /* If one operand is constant, make it the second one. Only do this if the other operand is not constant as well. */ if (swap_commutative_operands_p (op0, op1)) { tem = op0; op0 = op1; op1 = tem; code = swap_condition (code); } if (flag_force_mem) { op0 = force_not_mem (op0); op1 = force_not_mem (op1); } do_pending_stack_adjust (); ucode = unsignedp ? unsigned_condition (code) : code; if ((tem = simplify_relational_operation (ucode, mode, op0, op1)) != 0) { if (tem == const_true_rtx) { if (if_true_label) emit_jump (if_true_label); } else { if (if_false_label) emit_jump (if_false_label); } return; } #if 0 /* There's no need to do this now that combine.c can eliminate lots of sign extensions. This can be less efficient in certain cases on other machines. */ /* If this is a signed equality comparison, we can do it as an unsigned comparison since zero-extension is cheaper than sign extension and comparisons with zero are done as unsigned. This is the case even on machines that can do fast sign extension, since zero-extension is easier to combine with other operations than sign-extension is. If we are comparing against a constant, we must convert it to what it would look like unsigned. */ if ((code == EQ || code == NE) && ! unsignedp && GET_MODE_BITSIZE (GET_MODE (op0)) <= HOST_BITS_PER_WIDE_INT) { if (GET_CODE (op1) == CONST_INT && (INTVAL (op1) & GET_MODE_MASK (GET_MODE (op0))) != INTVAL (op1)) op1 = GEN_INT (INTVAL (op1) & GET_MODE_MASK (GET_MODE (op0))); unsignedp = 1; } #endif if (! if_true_label) { dummy_true_label = 1; if_true_label = gen_label_rtx (); } emit_cmp_and_jump_insns (op0, op1, code, size, mode, unsignedp, if_true_label); if (if_false_label) emit_jump (if_false_label); if (dummy_true_label) emit_label (if_true_label); }
void do_compare_rtx_and_jump (rtx op0, rtx op1, enum rtx_code code, int unsignedp, machine_mode mode, rtx size, rtx_code_label *if_false_label, rtx_code_label *if_true_label, int prob) { rtx tem; rtx_code_label *dummy_label = NULL; /* Reverse the comparison if that is safe and we want to jump if it is false. Also convert to the reverse comparison if the target can implement it. */ if ((! if_true_label || ! can_compare_p (code, mode, ccp_jump)) && (! FLOAT_MODE_P (mode) || code == ORDERED || code == UNORDERED || (! HONOR_NANS (mode) && (code == LTGT || code == UNEQ)) || (! HONOR_SNANS (mode) && (code == EQ || code == NE)))) { enum rtx_code rcode; if (FLOAT_MODE_P (mode)) rcode = reverse_condition_maybe_unordered (code); else rcode = reverse_condition (code); /* Canonicalize to UNORDERED for the libcall. */ if (can_compare_p (rcode, mode, ccp_jump) || (code == ORDERED && ! can_compare_p (ORDERED, mode, ccp_jump))) { std::swap (if_true_label, if_false_label); code = rcode; prob = inv (prob); } } /* If one operand is constant, make it the second one. Only do this if the other operand is not constant as well. */ if (swap_commutative_operands_p (op0, op1)) { std::swap (op0, op1); code = swap_condition (code); } do_pending_stack_adjust (); code = unsignedp ? unsigned_condition (code) : code; if (0 != (tem = simplify_relational_operation (code, mode, VOIDmode, op0, op1))) { if (CONSTANT_P (tem)) { rtx_code_label *label = (tem == const0_rtx || tem == CONST0_RTX (mode)) ? if_false_label : if_true_label; if (label) emit_jump (label); return; } code = GET_CODE (tem); mode = GET_MODE (tem); op0 = XEXP (tem, 0); op1 = XEXP (tem, 1); unsignedp = (code == GTU || code == LTU || code == GEU || code == LEU); } if (! if_true_label) dummy_label = if_true_label = gen_label_rtx (); if (GET_MODE_CLASS (mode) == MODE_INT && ! can_compare_p (code, mode, ccp_jump)) { switch (code) { case LTU: do_jump_by_parts_greater_rtx (mode, 1, op1, op0, if_false_label, if_true_label, prob); break; case LEU: do_jump_by_parts_greater_rtx (mode, 1, op0, op1, if_true_label, if_false_label, inv (prob)); break; case GTU: do_jump_by_parts_greater_rtx (mode, 1, op0, op1, if_false_label, if_true_label, prob); break; case GEU: do_jump_by_parts_greater_rtx (mode, 1, op1, op0, if_true_label, if_false_label, inv (prob)); break; case LT: do_jump_by_parts_greater_rtx (mode, 0, op1, op0, if_false_label, if_true_label, prob); break; case LE: do_jump_by_parts_greater_rtx (mode, 0, op0, op1, if_true_label, if_false_label, inv (prob)); break; case GT: do_jump_by_parts_greater_rtx (mode, 0, op0, op1, if_false_label, if_true_label, prob); break; case GE: do_jump_by_parts_greater_rtx (mode, 0, op1, op0, if_true_label, if_false_label, inv (prob)); break; case EQ: do_jump_by_parts_equality_rtx (mode, op0, op1, if_false_label, if_true_label, prob); break; case NE: do_jump_by_parts_equality_rtx (mode, op0, op1, if_true_label, if_false_label, inv (prob)); break; default: gcc_unreachable (); } } else { if (SCALAR_FLOAT_MODE_P (mode) && ! can_compare_p (code, mode, ccp_jump) && can_compare_p (swap_condition (code), mode, ccp_jump)) { code = swap_condition (code); std::swap (op0, op1); } else if (SCALAR_FLOAT_MODE_P (mode) && ! can_compare_p (code, mode, ccp_jump) /* Never split ORDERED and UNORDERED. These must be implemented. */ && (code != ORDERED && code != UNORDERED) /* Split a floating-point comparison if we can jump on other conditions... */ && (have_insn_for (COMPARE, mode) /* ... or if there is no libcall for it. */ || code_to_optab (code) == unknown_optab)) { enum rtx_code first_code; bool and_them = split_comparison (code, mode, &first_code, &code); /* If there are no NaNs, the first comparison should always fall through. */ if (!HONOR_NANS (mode)) gcc_assert (first_code == (and_them ? ORDERED : UNORDERED)); else { int first_prob = prob; if (first_code == UNORDERED) first_prob = REG_BR_PROB_BASE / 100; else if (first_code == ORDERED) first_prob = REG_BR_PROB_BASE - REG_BR_PROB_BASE / 100; if (and_them) { rtx_code_label *dest_label; /* If we only jump if true, just bypass the second jump. */ if (! if_false_label) { if (! dummy_label) dummy_label = gen_label_rtx (); dest_label = dummy_label; } else dest_label = if_false_label; do_compare_rtx_and_jump (op0, op1, first_code, unsignedp, mode, size, dest_label, NULL, first_prob); } else do_compare_rtx_and_jump (op0, op1, first_code, unsignedp, mode, size, NULL, if_true_label, first_prob); } } emit_cmp_and_jump_insns (op0, op1, code, size, mode, unsignedp, if_true_label, prob); } if (if_false_label) emit_jump (if_false_label); if (dummy_label) emit_label (dummy_label); }
void do_compare_rtx_and_jump (rtx op0, rtx op1, enum rtx_code code, int unsignedp, enum machine_mode mode, rtx size, rtx if_false_label, rtx if_true_label) { rtx tem; int dummy_true_label = 0; /* Reverse the comparison if that is safe and we want to jump if it is false. */ if (! if_true_label && ! FLOAT_MODE_P (mode)) { if_true_label = if_false_label; if_false_label = 0; code = reverse_condition (code); } /* If one operand is constant, make it the second one. Only do this if the other operand is not constant as well. */ if (swap_commutative_operands_p (op0, op1)) { tem = op0; op0 = op1; op1 = tem; code = swap_condition (code); } do_pending_stack_adjust (); code = unsignedp ? unsigned_condition (code) : code; if (0 != (tem = simplify_relational_operation (code, mode, VOIDmode, op0, op1))) { if (CONSTANT_P (tem)) { rtx label = (tem == const0_rtx || tem == CONST0_RTX (mode)) ? if_false_label : if_true_label; if (label) emit_jump (label); return; } code = GET_CODE (tem); mode = GET_MODE (tem); op0 = XEXP (tem, 0); op1 = XEXP (tem, 1); unsignedp = (code == GTU || code == LTU || code == GEU || code == LEU); } if (! if_true_label) { dummy_true_label = 1; if_true_label = gen_label_rtx (); } emit_cmp_and_jump_insns (op0, op1, code, size, mode, unsignedp, if_true_label); if (if_false_label) emit_jump (if_false_label); if (dummy_true_label) emit_label (if_true_label); }