summaryrefslogtreecommitdiff
path: root/gcc/reg-stack.c
diff options
context:
space:
mode:
authoruros <uros@138bc75d-0d04-0410-961f-82ee72b054a4>2007-01-18 13:06:57 +0000
committeruros <uros@138bc75d-0d04-0410-961f-82ee72b054a4>2007-01-18 13:06:57 +0000
commit64d0b9960a866b1de5520d3e55fce12bcfbd6bf6 (patch)
treeb09549c3db8a84ccbaeffdb31e9f328b4e85b663 /gcc/reg-stack.c
parent5bc9639859eb6ad2ec09d09aa2cb28fd029edcc1 (diff)
downloadgcc-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.c111
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. */