/* If-conversion support.
- Copyright (C) 2000 Free Software Foundation, Inc.
+ Copyright (C) 2000, 2001 Free Software Foundation, Inc.
This file is part of GNU CC.
= GET_CODE (XEXP (SET_SRC (set), 2)) == LABEL_REF
&& XEXP (XEXP (SET_SRC (set), 2), 0) == JUMP_LABEL (if_info->jump);
+ /* If we're looking for a constant, try to make the conditional
+ have that constant in it. There are two reasons why it may
+ not have the constant we want:
+
+ 1. GCC may have needed to put the constant in a register, because
+ the target can't compare directly against that constant. For
+ this case, we look for a SET immediately before the comparison
+ that puts a constant in that register.
+
+ 2. GCC may have canonicalized the conditional, for example
+ replacing "if x < 4" with "if x <= 3". We can undo that (or
+ make equivalent types of changes) to get the constants we need
+ if they're off by one in the right direction. */
+
+ if (GET_CODE (target) == CONST_INT)
+ {
+ enum rtx_code code = GET_CODE (if_info->cond);
+ rtx op_a = XEXP (if_info->cond, 0);
+ rtx op_b = XEXP (if_info->cond, 1);
+ rtx prev_insn;
+
+ /* First, look to see if we put a constant in a register. */
+ prev_insn = PREV_INSN (if_info->cond_earliest);
+ if (prev_insn
+ && INSN_P (prev_insn)
+ && GET_CODE (PATTERN (prev_insn)) == SET)
+ {
+ rtx src = find_reg_equal_equiv_note (prev_insn);
+ if (!src)
+ src = SET_SRC (PATTERN (prev_insn));
+ if (GET_CODE (src) == CONST_INT)
+ {
+ if (rtx_equal_p (op_a, SET_DEST (PATTERN (prev_insn))))
+ {
+ op_a = src;
+ if_info->cond_earliest = prev_insn;
+ }
+ else if (rtx_equal_p (op_b, SET_DEST (PATTERN (prev_insn))))
+ {
+ op_b = src;
+ if_info->cond_earliest = prev_insn;
+ }
+
+ if (GET_CODE (op_a) == CONST_INT)
+ {
+ rtx tmp = op_a;
+ op_a = op_b;
+ op_b = tmp;
+ code = swap_condition (code);
+ }
+ }
+ }
+
+ /* Now, look to see if we can get the right constant by
+ adjusting the conditional. */
+ if (GET_CODE (op_b) == CONST_INT)
+ {
+ HOST_WIDE_INT desired_val = INTVAL (target);
+ HOST_WIDE_INT actual_val = INTVAL (op_b);
+
+ switch (code)
+ {
+ case LT:
+ if (actual_val == desired_val + 1)
+ {
+ code = LE;
+ op_b = GEN_INT (desired_val);
+ }
+ break;
+ case LE:
+ if (actual_val == desired_val - 1)
+ {
+ code = LT;
+ op_b = GEN_INT (desired_val);
+ }
+ break;
+ case GT:
+ if (actual_val == desired_val - 1)
+ {
+ code = GE;
+ op_b = GEN_INT (desired_val);
+ }
+ break;
+ case GE:
+ if (actual_val == desired_val + 1)
+ {
+ code = GT;
+ op_b = GEN_INT (desired_val);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ /* If we made any changes, generate a new conditional that is
+ equivalent to what we started with, but has the right
+ constants in it. */
+ if (code != GET_CODE (if_info->cond)
+ || op_a != XEXP (if_info->cond, 0)
+ || op_b != XEXP (if_info->cond, 1))
+ {
+ cond = gen_rtx_fmt_ee (code, GET_MODE (cond), op_a, op_b);
+ *earliest = if_info->cond_earliest;
+ return cond;
+ }
+ }
+
cond = canonicalize_condition (if_info->jump, cond, reverse,
earliest, target);
if (! cond || ! reg_mentioned_p (target, cond))