diff options
author | uros <uros@138bc75d-0d04-0410-961f-82ee72b054a4> | 2007-01-18 13:06:57 +0000 |
---|---|---|
committer | uros <uros@138bc75d-0d04-0410-961f-82ee72b054a4> | 2007-01-18 13:06:57 +0000 |
commit | 64d0b9960a866b1de5520d3e55fce12bcfbd6bf6 (patch) | |
tree | b09549c3db8a84ccbaeffdb31e9f328b4e85b663 /gcc/reg-stack.c | |
parent | 5bc9639859eb6ad2ec09d09aa2cb28fd029edcc1 (diff) | |
download | gcc-64d0b9960a866b1de5520d3e55fce12bcfbd6bf6.tar.gz |
* reg-stack.c (subst_stack_regs_pat) [UNSPEC_SINCOS_COS,
UNSPEC_XTRACT_FRACT]: Use generic code for instructions that
operate on the top of stack.
[UNSPEC_SINCOS_SIN, UNSPEC_XTRACT_EXP, UNSPEC_TAN]: Rewrite
register handling of instructions that output to the second
stack slot.
[UNSPEC_TAN_ONE, UNSPEC_TAN_TAN]: Remove.
(move_for_stack_reg): Special-case check for dead destination
stack slot for constant load of 1.0 inside UNSPEC_TAN.
* config/i386/i386.md (UNSPEC_TAN): New constant.
(UNSPEC_TAN_ONE, UNSPEC_TAN_TAN): Remove.
(fptanxf4_i387, fptan_extend<mode>xf4_i387): New patterns
to correctly model move of constant 1.0 to top stack slot.
(*tandf3_1, *tansf3_1, *tanxf3_1): Remove insn patterns.
(unnamed peephole2 pattern): Remove corresponding peephole2
pattern that optimizes tan insn and loading of constant 1.0.
(tanxf2): Use fptanxf4_i387.
(tan<mode>2): Rename from tansf2 and tandf2 and macroize insn
patterns using X87MODEF12 mode macro. Use fptan_extend<mode>xf4_i387
and truncate result to requested mode. Use SSE_FLOAT_MODE_P to
disable patterns for SSE math.
(sincos<mode>3): Use truncxf<mode>2_i387_noop for truncation.
(fyl2x_extend<mode>xf3_i387): Use X87MODEF12 for operand 1.
testsuite/ChangeLog:
* gcc.target/i386/387-8.c: Update comment about optimizing
inherent load of 1.0 of fptan instruction.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@120899 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/reg-stack.c')
-rw-r--r-- | gcc/reg-stack.c | 111 |
1 files changed, 50 insertions, 61 deletions
diff --git a/gcc/reg-stack.c b/gcc/reg-stack.c index 793c6b58ec4..0df425eebeb 100644 --- a/gcc/reg-stack.c +++ b/gcc/reg-stack.c @@ -1059,6 +1059,8 @@ move_for_stack_reg (rtx insn, stack regstack, rtx pat) } else { + rtx pat = PATTERN (insn); + gcc_assert (STACK_REG_P (dest)); /* Load from MEM, or possibly integer REG or constant, into the @@ -1066,8 +1068,16 @@ move_for_stack_reg (rtx insn, stack regstack, rtx pat) stack. The stack mapping is changed to reflect that DEST is now at top of stack. */ - /* The destination ought to be dead. */ - gcc_assert (get_hard_regnum (regstack, dest) < FIRST_STACK_REG); + /* The destination ought to be dead. However, there is a + special case with i387 UNSPEC_TAN, where destination is live + (an argument to fptan) but inherent load of 1.0 is modelled + as a load from a constant. */ + if (! (GET_CODE (pat) == PARALLEL + && XVECLEN (pat, 0) == 2 + && GET_CODE (XVECEXP (pat, 0, 1)) == SET + && GET_CODE (SET_SRC (XVECEXP (pat, 0, 1))) == UNSPEC + && XINT (SET_SRC (XVECEXP (pat, 0, 1)), 1) == UNSPEC_TAN)) + gcc_assert (get_hard_regnum (regstack, dest) < FIRST_STACK_REG); gcc_assert (regstack->top < REG_STACK_SIZE); @@ -1629,14 +1639,19 @@ subst_stack_regs_pat (rtx insn, stack regstack, rtx pat) case UNSPEC_FRNDINT_TRUNC: case UNSPEC_FRNDINT_MASK_PM: - /* These insns only operate on the top of the stack. */ + /* Above insns operate on the top of the stack. */ + + case UNSPEC_SINCOS_COS: + case UNSPEC_XTRACT_FRACT: + + /* Above insns operate on the top two stack slots, + first part of one input, double output insn. */ src1 = get_true_reg (&XVECEXP (pat_src, 0, 0)); emit_swap_insn (insn, regstack, *src1); - /* Input should never die, it is - replaced with output. */ + /* Input should never die, it is replaced with output. */ src1_note = find_regno_note (insn, REG_DEAD, REGNO (*src1)); gcc_assert (!src1_note); @@ -1646,6 +1661,36 @@ subst_stack_regs_pat (rtx insn, stack regstack, rtx pat) replace_reg (src1, FIRST_STACK_REG); break; + case UNSPEC_SINCOS_SIN: + case UNSPEC_XTRACT_EXP: + + /* These insns operate on the top two stack slots, + second part of one input, double output insn. */ + + regstack->top++; + /* FALLTHRU */ + + case UNSPEC_TAN: + + /* For UNSPEC_TAN, regstack->top is already increased + by inherent load of constant 1.0. */ + + /* Output value is generated in the second stack slot. + Move current value from second slot to the top. */ + regstack->reg[regstack->top] + = regstack->reg[regstack->top - 1]; + + gcc_assert (STACK_REG_P (*dest)); + + regstack->reg[regstack->top - 1] = REGNO (*dest); + SET_HARD_REG_BIT (regstack->reg_set, REGNO (*dest)); + replace_reg (dest, FIRST_STACK_REG + 1); + + src1 = get_true_reg (&XVECEXP (pat_src, 0, 0)); + + replace_reg (src1, FIRST_STACK_REG); + break; + case UNSPEC_FPATAN: case UNSPEC_FYL2X: case UNSPEC_FYL2XP1: @@ -1744,62 +1789,6 @@ subst_stack_regs_pat (rtx insn, stack regstack, rtx pat) replace_reg (src2, FIRST_STACK_REG + 1); break; - case UNSPEC_SINCOS_COS: - case UNSPEC_TAN_ONE: - case UNSPEC_XTRACT_FRACT: - /* These insns operate on the top two stack slots, - first part of one input, double output insn. */ - - src1 = get_true_reg (&XVECEXP (pat_src, 0, 0)); - - emit_swap_insn (insn, regstack, *src1); - - /* Input should never die, it is - replaced with output. */ - src1_note = find_regno_note (insn, REG_DEAD, REGNO (*src1)); - gcc_assert (!src1_note); - - /* Push the result back onto stack. Empty stack slot - will be filled in second part of insn. */ - if (STACK_REG_P (*dest)) - { - regstack->reg[regstack->top + 1] = REGNO (*dest); - SET_HARD_REG_BIT (regstack->reg_set, REGNO (*dest)); - replace_reg (dest, FIRST_STACK_REG); - } - - replace_reg (src1, FIRST_STACK_REG); - break; - - case UNSPEC_SINCOS_SIN: - case UNSPEC_TAN_TAN: - case UNSPEC_XTRACT_EXP: - /* These insns operate on the top two stack slots, - second part of one input, double output insn. */ - - src1 = get_true_reg (&XVECEXP (pat_src, 0, 0)); - - emit_swap_insn (insn, regstack, *src1); - - /* Input should never die, it is - replaced with output. */ - src1_note = find_regno_note (insn, REG_DEAD, REGNO (*src1)); - gcc_assert (!src1_note); - - /* Push the result back onto stack. Fill empty slot from - first part of insn and fix top of stack pointer. */ - if (STACK_REG_P (*dest)) - { - regstack->reg[regstack->top] = REGNO (*dest); - SET_HARD_REG_BIT (regstack->reg_set, REGNO (*dest)); - replace_reg (dest, FIRST_STACK_REG + 1); - - regstack->top++; - } - - replace_reg (src1, FIRST_STACK_REG); - break; - case UNSPEC_SAHF: /* (unspec [(unspec [(compare)] UNSPEC_FNSTSW)] UNSPEC_SAHF) The combination matches the PPRO fcomi instruction. */ |