From f964bd29f1d8a34990937c5a13e4356257e43a80 Mon Sep 17 00:00:00 2001 From: Uros Bizjak Date: Thu, 29 Apr 2004 09:19:25 +0200 Subject: [PATCH] reg-stack.c (swap_to_top): New function. 2004-04-23 Uros Bizjak * reg-stack.c (swap_to_top): New function. (subst_stack_regs_pat): UNSPEC_FPATAN, UNSPEC_FYL2X: Use\ swap_to_top(). (subst_stack_regs_pat): UNSPEC_FSCALE: Remove. (subst_stack_regs_pat): Handle UNSPEC_FSCALE_FRACT and UNSPEC_FSCALE_EXP. * config/i386/i386.md (UNSPEC_FSCALE): Remove. (*fscale_sfxf3, *fscale_dfxf3, *fscale_xf3): Remove insn pattern. (UNSPEC_FSCALE_FRACT, UNSPEC_FSCALE_EXP): New unspecs to represent x87's fscale insn. (*fscalexf4: Define new insn pattern to implement x87 fscale insn. (exp?f2, exp10?f2, exp2?f2): Use *fscalexf4 and float_truncate patterns. From-SVN: r81278 --- gcc/ChangeLog | 17 +++++ gcc/config/i386/i386.md | 159 ++++++++++++++++++++++------------------ gcc/reg-stack.c | 145 ++++++++++++++++++++++++++---------- 3 files changed, 213 insertions(+), 108 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f6c618edfb9..3916f83518c 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,20 @@ +2004-04-29 Uros Bizjak + + * reg-stack.c (swap_to_top): New function. + (subst_stack_regs_pat): UNSPEC_FPATAN, UNSPEC_FYL2X: Use + swap_to_top(). + (subst_stack_regs_pat): UNSPEC_FSCALE: Remove. + (subst_stack_regs_pat): Handle UNSPEC_FSCALE_FRACT and + UNSPEC_FSCALE_EXP. + + * config/i386/i386.md (UNSPEC_FSCALE): Remove. + (*fscale_sfxf3, *fscale_dfxf3, *fscale_xf3): Remove insn pattern. + (UNSPEC_FSCALE_FRACT, UNSPEC_FSCALE_EXP): New unspecs to represent + x87's fscale insn. + (*fscalexf4: Define new insn pattern to implement x87 fscale insn. + (exp?f2, exp10?f2, exp2?f2): Use *fscalexf4 and float_truncate + patterns. + 2004-04-28 Serge Belyshev <1319@bot.ru> PR 14944 diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index c0a3ff4cfe5..fbb39c1cd7a 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -117,7 +117,6 @@ ; x87 Floating point (UNSPEC_FPATAN 65) (UNSPEC_FYL2X 66) - (UNSPEC_FSCALE 67) (UNSPEC_FRNDINT 68) (UNSPEC_F2XM1 69) @@ -128,6 +127,8 @@ (UNSPEC_TAN_TAN 83) (UNSPEC_XTRACT_FRACT 84) (UNSPEC_XTRACT_EXP 85) + (UNSPEC_FSCALE_FRACT 86) + (UNSPEC_FSCALE_EXP 87) ; REP instruction (UNSPEC_REP 75) @@ -15669,42 +15670,6 @@ operands[3] = gen_reg_rtx (XFmode); }) -(define_insn "*fscale_sfxf3" - [(set (match_operand:SF 0 "register_operand" "=f") - (unspec:SF [(match_operand:XF 2 "register_operand" "0") - (match_operand:XF 1 "register_operand" "u")] - UNSPEC_FSCALE)) - (clobber (match_scratch:SF 3 "=1"))] - "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 - && flag_unsafe_math_optimizations" - "fscale\;fstp\t%y1" - [(set_attr "type" "fpspc") - (set_attr "mode" "SF")]) - -(define_insn "*fscale_dfxf3" - [(set (match_operand:DF 0 "register_operand" "=f") - (unspec:DF [(match_operand:XF 2 "register_operand" "0") - (match_operand:XF 1 "register_operand" "u")] - UNSPEC_FSCALE)) - (clobber (match_scratch:DF 3 "=1"))] - "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 - && flag_unsafe_math_optimizations" - "fscale\;fstp\t%y1" - [(set_attr "type" "fpspc") - (set_attr "mode" "DF")]) - -(define_insn "*fscale_xf3" - [(set (match_operand:XF 0 "register_operand" "=f") - (unspec:XF [(match_operand:XF 2 "register_operand" "0") - (match_operand:XF 1 "register_operand" "u")] - UNSPEC_FSCALE)) - (clobber (match_scratch:XF 3 "=1"))] - "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 - && flag_unsafe_math_optimizations" - "fscale\;fstp\t%y1" - [(set_attr "type" "fpspc") - (set_attr "mode" "XF")]) - (define_insn "*frndintxf2" [(set (match_operand:XF 0 "register_operand" "=f") (unspec:XF [(match_operand:XF 1 "register_operand" "0")] @@ -15725,6 +15690,20 @@ [(set_attr "type" "fpspc") (set_attr "mode" "XF")]) +(define_insn "*fscalexf4" + [(set (match_operand:XF 0 "register_operand" "=f") + (unspec:XF [(match_operand:XF 2 "register_operand" "0") + (match_operand:XF 3 "register_operand" "1")] + UNSPEC_FSCALE_FRACT)) + (set (match_operand:XF 1 "register_operand" "=u") + (unspec:XF [(match_dup 2) (match_dup 3)] + UNSPEC_FSCALE_EXP))] + "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 + && flag_unsafe_math_optimizations" + "fscale" + [(set_attr "type" "fpspc") + (set_attr "mode" "DF")]) + (define_expand "expsf2" [(set (match_dup 2) (float_extend:XF (match_operand:SF 1 "register_operand" ""))) @@ -15733,16 +15712,21 @@ (set (match_dup 6) (minus:XF (match_dup 4) (match_dup 5))) (set (match_dup 7) (unspec:XF [(match_dup 6)] UNSPEC_F2XM1)) (set (match_dup 9) (plus:XF (match_dup 7) (match_dup 8))) - (parallel [(set (match_operand:SF 0 "register_operand" "") - (unspec:SF [(match_dup 9) (match_dup 5)] UNSPEC_FSCALE)) - (clobber (match_scratch:SF 5 ""))])] + (parallel [(set (match_dup 10) + (unspec:XF [(match_dup 9) (match_dup 5)] + UNSPEC_FSCALE_FRACT)) + (set (match_dup 11) + (unspec:XF [(match_dup 9) (match_dup 5)] + UNSPEC_FSCALE_EXP))]) + (set (match_operand:SF 0 "register_operand" "") + (float_truncate:SF (match_dup 10)))] "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 && flag_unsafe_math_optimizations" { rtx temp; int i; - for (i=2; i<10; i++) + for (i=2; i<12; i++) operands[i] = gen_reg_rtx (XFmode); temp = standard_80387_constant_rtx (5); /* fldl2e */ emit_move_insn (operands[3], temp); @@ -15755,19 +15739,23 @@ (set (match_dup 4) (mult:XF (match_dup 2) (match_dup 3))) (set (match_dup 5) (unspec:XF [(match_dup 4)] UNSPEC_FRNDINT)) (set (match_dup 6) (minus:XF (match_dup 4) (match_dup 5))) - (set (match_dup 7) (unspec:XF [(match_dup 6)] UNSPEC_F2XM1)) (set (match_dup 9) (plus:XF (match_dup 7) (match_dup 8))) - (parallel [(set (match_operand:DF 0 "register_operand" "") - (unspec:DF [(match_dup 9) (match_dup 5)] UNSPEC_FSCALE)) - (clobber (match_scratch:DF 5 ""))])] + (parallel [(set (match_dup 10) + (unspec:XF [(match_dup 9) (match_dup 5)] + UNSPEC_FSCALE_FRACT)) + (set (match_dup 11) + (unspec:XF [(match_dup 9) (match_dup 5)] + UNSPEC_FSCALE_EXP))]) + (set (match_operand:DF 0 "register_operand" "") + (float_truncate:DF (match_dup 10)))] "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 && flag_unsafe_math_optimizations" { rtx temp; int i; - for (i=2; i<10; i++) + for (i=2; i<12; i++) operands[i] = gen_reg_rtx (XFmode); temp = standard_80387_constant_rtx (5); /* fldl2e */ emit_move_insn (operands[3], temp); @@ -15782,15 +15770,18 @@ (set (match_dup 6) (unspec:XF [(match_dup 5)] UNSPEC_F2XM1)) (set (match_dup 8) (plus:XF (match_dup 6) (match_dup 7))) (parallel [(set (match_operand:XF 0 "register_operand" "") - (unspec:XF [(match_dup 8) (match_dup 4)] UNSPEC_FSCALE)) - (clobber (match_scratch:XF 5 ""))])] + (unspec:XF [(match_dup 8) (match_dup 4)] + UNSPEC_FSCALE_FRACT)) + (set (match_dup 9) + (unspec:XF [(match_dup 8) (match_dup 4)] + UNSPEC_FSCALE_EXP))])] "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 && flag_unsafe_math_optimizations" { rtx temp; int i; - for (i=2; i<9; i++) + for (i=2; i<10; i++) operands[i] = gen_reg_rtx (XFmode); temp = standard_80387_constant_rtx (5); /* fldl2e */ emit_move_insn (operands[2], temp); @@ -15805,16 +15796,21 @@ (set (match_dup 6) (minus:XF (match_dup 4) (match_dup 5))) (set (match_dup 7) (unspec:XF [(match_dup 6)] UNSPEC_F2XM1)) (set (match_dup 9) (plus:XF (match_dup 7) (match_dup 8))) - (parallel [(set (match_operand:SF 0 "register_operand" "") - (unspec:SF [(match_dup 9) (match_dup 5)] UNSPEC_FSCALE)) - (clobber (match_scratch:SF 5 ""))])] + (parallel [(set (match_dup 10) + (unspec:XF [(match_dup 9) (match_dup 5)] + UNSPEC_FSCALE_FRACT)) + (set (match_dup 11) + (unspec:XF [(match_dup 9) (match_dup 5)] + UNSPEC_FSCALE_EXP))]) + (set (match_operand:SF 0 "register_operand" "") + (float_truncate:SF (match_dup 10)))] "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 && flag_unsafe_math_optimizations" { rtx temp; int i; - for (i=2; i<10; i++) + for (i=2; i<12; i++) operands[i] = gen_reg_rtx (XFmode); temp = standard_80387_constant_rtx (6); /* fldl2t */ emit_move_insn (operands[3], temp); @@ -15829,16 +15825,21 @@ (set (match_dup 6) (minus:XF (match_dup 4) (match_dup 5))) (set (match_dup 7) (unspec:XF [(match_dup 6)] UNSPEC_F2XM1)) (set (match_dup 9) (plus:XF (match_dup 7) (match_dup 8))) - (parallel [(set (match_operand:DF 0 "register_operand" "") - (unspec:DF [(match_dup 9) (match_dup 5)] UNSPEC_FSCALE)) - (clobber (match_scratch:DF 5 ""))])] + (parallel [(set (match_dup 10) + (unspec:XF [(match_dup 9) (match_dup 5)] + UNSPEC_FSCALE_FRACT)) + (set (match_dup 11) + (unspec:XF [(match_dup 9) (match_dup 5)] + UNSPEC_FSCALE_EXP))]) + (set (match_operand:DF 0 "register_operand" "") + (float_truncate:DF (match_dup 10)))] "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 && flag_unsafe_math_optimizations" { rtx temp; int i; - for (i=2; i<10; i++) + for (i=2; i<12; i++) operands[i] = gen_reg_rtx (XFmode); temp = standard_80387_constant_rtx (6); /* fldl2t */ emit_move_insn (operands[3], temp); @@ -15853,15 +15854,18 @@ (set (match_dup 6) (unspec:XF [(match_dup 5)] UNSPEC_F2XM1)) (set (match_dup 8) (plus:XF (match_dup 6) (match_dup 7))) (parallel [(set (match_operand:XF 0 "register_operand" "") - (unspec:XF [(match_dup 8) (match_dup 4)] UNSPEC_FSCALE)) - (clobber (match_scratch:XF 5 ""))])] + (unspec:XF [(match_dup 8) (match_dup 4)] + UNSPEC_FSCALE_FRACT)) + (set (match_dup 9) + (unspec:XF [(match_dup 8) (match_dup 4)] + UNSPEC_FSCALE_EXP))])] "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 && flag_unsafe_math_optimizations" { rtx temp; int i; - for (i=2; i<9; i++) + for (i=2; i<10; i++) operands[i] = gen_reg_rtx (XFmode); temp = standard_80387_constant_rtx (6); /* fldl2t */ emit_move_insn (operands[2], temp); @@ -15875,15 +15879,20 @@ (set (match_dup 4) (minus:XF (match_dup 2) (match_dup 3))) (set (match_dup 5) (unspec:XF [(match_dup 4)] UNSPEC_F2XM1)) (set (match_dup 7) (plus:XF (match_dup 5) (match_dup 6))) - (parallel [(set (match_operand:SF 0 "register_operand" "") - (unspec:SF [(match_dup 7) (match_dup 3)] UNSPEC_FSCALE)) - (clobber (match_scratch:SF 3 ""))])] + (parallel [(set (match_dup 8) + (unspec:XF [(match_dup 7) (match_dup 3)] + UNSPEC_FSCALE_FRACT)) + (set (match_dup 9) + (unspec:XF [(match_dup 7) (match_dup 3)] + UNSPEC_FSCALE_EXP))]) + (set (match_operand:SF 0 "register_operand" "") + (float_truncate:SF (match_dup 8)))] "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 && flag_unsafe_math_optimizations" { int i; - for (i=2; i<8; i++) + for (i=2; i<10; i++) operands[i] = gen_reg_rtx (XFmode); emit_move_insn (operands[6], CONST1_RTX (XFmode)); /* fld1 */ }) @@ -15895,15 +15904,20 @@ (set (match_dup 4) (minus:XF (match_dup 2) (match_dup 3))) (set (match_dup 5) (unspec:XF [(match_dup 4)] UNSPEC_F2XM1)) (set (match_dup 7) (plus:XF (match_dup 5) (match_dup 6))) - (parallel [(set (match_operand:DF 0 "register_operand" "") - (unspec:DF [(match_dup 7) (match_dup 3)] UNSPEC_FSCALE)) - (clobber (match_scratch:DF 3 ""))])] + (parallel [(set (match_dup 8) + (unspec:XF [(match_dup 7) (match_dup 3)] + UNSPEC_FSCALE_FRACT)) + (set (match_dup 9) + (unspec:XF [(match_dup 7) (match_dup 3)] + UNSPEC_FSCALE_EXP))]) + (set (match_operand:DF 0 "register_operand" "") + (float_truncate:DF (match_dup 8)))] "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 && flag_unsafe_math_optimizations" { int i; - for (i=2; i<8; i++) + for (i=2; i<10; i++) operands[i] = gen_reg_rtx (XFmode); emit_move_insn (operands[6], CONST1_RTX (XFmode)); /* fld1 */ }) @@ -15915,14 +15929,17 @@ (set (match_dup 5) (unspec:XF [(match_dup 4)] UNSPEC_F2XM1)) (set (match_dup 7) (plus:XF (match_dup 5) (match_dup 6))) (parallel [(set (match_operand:XF 0 "register_operand" "") - (unspec:XF [(match_dup 7) (match_dup 3)] UNSPEC_FSCALE)) - (clobber (match_scratch:XF 3 ""))])] + (unspec:XF [(match_dup 7) (match_dup 3)] + UNSPEC_FSCALE_FRACT)) + (set (match_dup 8) + (unspec:XF [(match_dup 7) (match_dup 3)] + UNSPEC_FSCALE_EXP))])] "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 && flag_unsafe_math_optimizations" { int i; - for (i=2; i<8; i++) + for (i=2; i<9; i++) operands[i] = gen_reg_rtx (XFmode); emit_move_insn (operands[6], CONST1_RTX (XFmode)); /* fld1 */ }) diff --git a/gcc/reg-stack.c b/gcc/reg-stack.c index c3279d0206f..2836e63d7ed 100644 --- a/gcc/reg-stack.c +++ b/gcc/reg-stack.c @@ -249,6 +249,7 @@ static void remove_regno_note (rtx, enum reg_note, unsigned int); static int get_hard_regnum (stack, rtx); static rtx emit_pop_insn (rtx, stack, rtx, enum emit_where); static void emit_swap_insn (rtx, stack, rtx); +static void swap_to_top(rtx, stack, rtx, rtx); static bool move_for_stack_reg (rtx, stack, rtx); static int swap_rtx_condition_1 (rtx); static int swap_rtx_condition (rtx); @@ -1034,6 +1035,54 @@ emit_swap_insn (rtx insn, stack regstack, rtx reg) emit_insn_before (swap_rtx, insn); } +/* Emit an insns before INSN to swap virtual register SRC1 with + the top of stack and virtual register SRC2 with second stack + slot. REGSTACK is the stack state before the swaps, and + is updated to reflect the swaps. A swap insn is represented as a + PARALLEL of two patterns: each pattern moves one reg to the other. + + If SRC1 and/or SRC2 are already at the right place, no swap insn + is emitted. */ + +static void +swap_to_top (rtx insn, stack regstack, rtx src1, rtx src2) +{ + struct stack_def temp_stack; + int regno, j, k, temp; + + temp_stack = *regstack; + + /* Place operand 1 at the top of stack. */ + regno = get_hard_regnum (&temp_stack, src1); + if (regno < 0) + abort (); + if (regno != FIRST_STACK_REG) + { + k = temp_stack.top - (regno - FIRST_STACK_REG); + j = temp_stack.top; + + temp = temp_stack.reg[k]; + temp_stack.reg[k] = temp_stack.reg[j]; + temp_stack.reg[j] = temp; + } + + /* Place operand 2 next on the stack. */ + regno = get_hard_regnum (&temp_stack, src2); + if (regno < 0) + abort (); + if (regno != FIRST_STACK_REG + 1) + { + k = temp_stack.top - (regno - FIRST_STACK_REG); + j = temp_stack.top - 1; + + temp = temp_stack.reg[k]; + temp_stack.reg[k] = temp_stack.reg[j]; + temp_stack.reg[j] = temp; + } + + change_stack (insn, regstack, &temp_stack, EMIT_BEFORE); +} + /* Handle a move to or from a stack register in PAT, which is in INSN. REGSTACK is the current stack. Return whether a control flow insn was deleted in the process. */ @@ -1701,7 +1750,6 @@ subst_stack_regs_pat (rtx insn, stack regstack, rtx pat) case UNSPEC_FPATAN: case UNSPEC_FYL2X: - case UNSPEC_FSCALE: /* These insns operate on the top two stack slots. */ src1 = get_true_reg (&XVECEXP (pat_src, 0, 0)); @@ -1710,42 +1758,7 @@ subst_stack_regs_pat (rtx insn, stack regstack, rtx pat) src1_note = find_regno_note (insn, REG_DEAD, REGNO (*src1)); src2_note = find_regno_note (insn, REG_DEAD, REGNO (*src2)); - { - struct stack_def temp_stack; - int regno, j, k, temp; - - temp_stack = *regstack; - - /* Place operand 1 at the top of stack. */ - regno = get_hard_regnum (&temp_stack, *src1); - if (regno < 0) - abort (); - if (regno != FIRST_STACK_REG) - { - k = temp_stack.top - (regno - FIRST_STACK_REG); - j = temp_stack.top; - - temp = temp_stack.reg[k]; - temp_stack.reg[k] = temp_stack.reg[j]; - temp_stack.reg[j] = temp; - } - - /* Place operand 2 next on the stack. */ - regno = get_hard_regnum (&temp_stack, *src2); - if (regno < 0) - abort (); - if (regno != FIRST_STACK_REG + 1) - { - k = temp_stack.top - (regno - FIRST_STACK_REG); - j = temp_stack.top - 1; - - temp = temp_stack.reg[k]; - temp_stack.reg[k] = temp_stack.reg[j]; - temp_stack.reg[j] = temp; - } - - change_stack (insn, regstack, &temp_stack, EMIT_BEFORE); - } + swap_to_top (insn, regstack, *src1, *src2); replace_reg (src1, FIRST_STACK_REG); replace_reg (src2, FIRST_STACK_REG + 1); @@ -1768,6 +1781,64 @@ subst_stack_regs_pat (rtx insn, stack regstack, rtx pat) replace_reg (dest, FIRST_STACK_REG); break; + case UNSPEC_FSCALE_FRACT: + /* These insns operate on the top two stack slots. + first part of double input, double output insn. */ + + src1 = get_true_reg (&XVECEXP (pat_src, 0, 0)); + src2 = get_true_reg (&XVECEXP (pat_src, 0, 1)); + + src1_note = find_regno_note (insn, REG_DEAD, REGNO (*src1)); + src2_note = find_regno_note (insn, REG_DEAD, REGNO (*src2)); + + /* Inputs should never die, they are + replaced with outputs. */ + if ((src1_note) || (src2_note)) + abort(); + + swap_to_top (insn, regstack, *src1, *src2); + + /* 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] = REGNO (*dest); + SET_HARD_REG_BIT (regstack->reg_set, REGNO (*dest)); + replace_reg (dest, FIRST_STACK_REG); + } + + replace_reg (src1, FIRST_STACK_REG); + replace_reg (src2, FIRST_STACK_REG + 1); + break; + + case UNSPEC_FSCALE_EXP: + /* These insns operate on the top two stack slots./ + second part of double input, double output insn. */ + + src1 = get_true_reg (&XVECEXP (pat_src, 0, 0)); + src2 = get_true_reg (&XVECEXP (pat_src, 0, 1)); + + src1_note = find_regno_note (insn, REG_DEAD, REGNO (*src1)); + src2_note = find_regno_note (insn, REG_DEAD, REGNO (*src2)); + + /* Inputs should never die, they are + replaced with outputs. */ + if ((src1_note) || (src2_note)) + abort(); + + swap_to_top (insn, regstack, *src1, *src2); + + /* 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 - 1] = REGNO (*dest); + SET_HARD_REG_BIT (regstack->reg_set, REGNO (*dest)); + replace_reg (dest, FIRST_STACK_REG + 1); + } + + replace_reg (src1, FIRST_STACK_REG); + replace_reg (src2, FIRST_STACK_REG + 1); + break; + case UNSPEC_SINCOS_COS: case UNSPEC_TAN_ONE: case UNSPEC_XTRACT_FRACT: -- 2.30.2