diff options
author | Stan Cox <coxs@gnu.org> | 1996-11-08 22:03:06 +0000 |
---|---|---|
committer | Stan Cox <coxs@gnu.org> | 1996-11-08 22:03:06 +0000 |
commit | 4e97601f107e6597ef2da0fadf5624137a1d50f5 (patch) | |
tree | 6b482f73b67b8d343cb6bc404ced2a98f4bb7e88 /gcc/reg-stack.c | |
parent | 7a976aea15ceb44578d5e0e883e4dbb74e60078a (diff) | |
download | gcc-4e97601f107e6597ef2da0fadf5624137a1d50f5.zip gcc-4e97601f107e6597ef2da0fadf5624137a1d50f5.tar.gz gcc-4e97601f107e6597ef2da0fadf5624137a1d50f5.tar.bz2 |
(compare_for_stack_reg, subst_stack_regs_pat):
From-SVN: r13113
Diffstat (limited to 'gcc/reg-stack.c')
-rw-r--r-- | gcc/reg-stack.c | 66 |
1 files changed, 66 insertions, 0 deletions
diff --git a/gcc/reg-stack.c b/gcc/reg-stack.c index 10c1d76..ea72b3a 100644 --- a/gcc/reg-stack.c +++ b/gcc/reg-stack.c @@ -2017,9 +2017,26 @@ compare_for_stack_reg (insn, regstack, pat) { rtx *src1, *src2; rtx src1_note, src2_note; + rtx cc0_user; src1 = get_true_reg (&XEXP (SET_SRC (pat), 0)); src2 = get_true_reg (&XEXP (SET_SRC (pat), 1)); + cc0_user = next_cc0_user (insn); + + /* If the insn that uses cc0 is a conditional move, then the destination + must be the top of stack */ + if (GET_CODE (PATTERN (cc0_user)) == SET + && SET_DEST (PATTERN (cc0_user)) != pc_rtx + && GET_CODE (SET_SRC (PATTERN (cc0_user))) == IF_THEN_ELSE) + { + rtx *dest, src_note; + + dest = get_true_reg (&SET_DEST (PATTERN (cc0_user))); + if (REGNO (*dest) != regstack->reg[regstack->top]) + { + emit_swap_insn (insn, regstack, *dest); + } + } /* ??? If fxch turns out to be cheaper than fstp, give priority to registers that die in this insn - move those to stack top first. */ @@ -2336,6 +2353,55 @@ subst_stack_regs_pat (insn, regstack, pat) } break; + case IF_THEN_ELSE: + /* This insn requires the top of stack to be the destination. */ + + src1 = get_true_reg (&XEXP (SET_SRC (pat), 1)); + src2 = get_true_reg (&XEXP (SET_SRC (pat), 2)); + + src1_note = find_regno_note (insn, REG_DEAD, REGNO (*src1)); + src2_note = find_regno_note (insn, REG_DEAD, REGNO (*src2)); + + { + rtx src_note [] = {0, src1_note, src2_note}; + int i; + + if (STACK_REG_P (*src1)) + replace_reg (src1, get_hard_regnum (regstack, *src1)); + if (STACK_REG_P (*src2)) + replace_reg (src2, get_hard_regnum (regstack, *src2)); + + for (i = 1; i <= 2; i++) + if (src_note [i]) + { + int regno = get_hard_regnum (regstack, XEXP (src_note [i], 0)); + + /* If the register that dies is not at the top of stack, then + move the top of stack to the dead reg */ + if (REGNO (XEXP (src_note[i], 0)) + != regstack->reg[regstack->top]) + { + remove_regno_note (insn, REG_DEAD, + REGNO (XEXP (src_note [i], 0))); + emit_pop_insn (insn, regstack, XEXP (src_note[i], 0), + emit_insn_after); + } + else + { + CLEAR_HARD_REG_BIT (regstack->reg_set, + REGNO (XEXP (src_note[i], 0))); + replace_reg (&XEXP (src_note[i], 0), FIRST_STACK_REG); + regstack->top--; + } + + } + + SET_HARD_REG_BIT (regstack->reg_set, REGNO (*dest)); + replace_reg (dest, FIRST_STACK_REG); + } + + break; + default: abort (); } |