case IF_THEN_ELSE:
/* This insn requires the top of stack to be the destination. */
+ src1 = get_true_reg (&XEXP (pat_src, 1));
+ src2 = get_true_reg (&XEXP (pat_src, 2));
+
+ src1_note = find_regno_note (insn, REG_DEAD, REGNO (*src1));
+ src2_note = find_regno_note (insn, REG_DEAD, REGNO (*src2));
+
/* If the comparison operator is an FP comparison operator,
it is handled correctly by compare_for_stack_reg () who
will move the destination to the top of stack. But if the
have to handle it here. */
if (get_hard_regnum (regstack, *dest) >= FIRST_STACK_REG
&& REGNO (*dest) != regstack->reg[regstack->top])
- emit_swap_insn (insn, regstack, *dest);
-
- src1 = get_true_reg (&XEXP (pat_src, 1));
- src2 = get_true_reg (&XEXP (pat_src, 2));
-
- src1_note = find_regno_note (insn, REG_DEAD, REGNO (*src1));
- src2_note = find_regno_note (insn, REG_DEAD, REGNO (*src2));
+ {
+ /* In case one of operands is the top of stack and the operands
+ dies, it is safe to make it the destination operand by reversing
+ the direction of cmove and avoid fxch. */
+ if ((REGNO (*src1) == regstack->reg[regstack->top]
+ && src1_note)
+ || (REGNO (*src2) == regstack->reg[regstack->top]
+ && src2_note))
+ {
+ int idx1 = (get_hard_regnum (regstack, *src1)
+ - FIRST_STACK_REG);
+ int idx2 = (get_hard_regnum (regstack, *src2)
+ - FIRST_STACK_REG);
+
+ /* Make reg-stack believe that the operands are already
+ swapped on the stack */
+ regstack->reg[regstack->top - idx1] = REGNO (*src2);
+ regstack->reg[regstack->top - idx2] = REGNO (*src1);
+
+ /* Reverse condition to compensate the operand swap.
+ i386 do have comparison always reversible. */
+ PUT_CODE (XEXP (pat_src, 0),
+ reversed_comparison_code (XEXP (pat_src, 0), insn));
+ }
+ else
+ emit_swap_insn (insn, regstack, *dest);
+ }
{
rtx src_note [3];
EMIT_AFTER);
}
else
- {
- CLEAR_HARD_REG_BIT (regstack->reg_set, regno);
- replace_reg (&XEXP (src_note[i], 0), FIRST_STACK_REG);
- regstack->top--;
- }
+ /* Top of stack never dies, as it is the
+ destination. */
+ abort ();
}
}