From: Jan Hubicka Date: Fri, 19 Nov 1999 20:50:36 +0000 (+0100) Subject: i386.h (enum reg_class): Add FLOAT_INT_REGS. X-Git-Tag: prereleases/libstdc++-2.92~9496 X-Git-Url: https://gcc.gnu.org/git/?a=commitdiff_plain;h=8fcaaa8099e6073951189584b1e482b0ff373ba1;p=gcc.git i386.h (enum reg_class): Add FLOAT_INT_REGS. * i386.h (enum reg_class): Add FLOAT_INT_REGS. (REG_CLASS_NAMES): Likewise. (REG_CLASS_CONTENTS): Define FLOAT_INT_REGS as union of FLOAT_REGS and GENERAL_REGS. * i386.md (pushsf): Do not preferre FLOAT_REGS over GENERAL_REGS. (movsf): Likewise; unify 4th and 5th alternative. (pushdf): Likewise. (movdf_1): Likewise; rename to movdf_integer. (pushxf): Likewise; rename to pushxf_integer; fix output template; remove redundant splitter. (movxf_1): Likewise; rename to movxf_integer; fix splitter's condition. (movdf_nointeger): New. (movxf_nointeger): New. (pushxf_nointeger): New. From-SVN: r30594 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 663be335a841..3e1552b3c36f 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,20 @@ Fri Nov 19 06:32:19 CET 1999 Jan Hubicka + * i386.h (enum reg_class): Add FLOAT_INT_REGS. + (REG_CLASS_NAMES): Likewise. + (REG_CLASS_CONTENTS): Define FLOAT_INT_REGS as union of FLOAT_REGS + and GENERAL_REGS. + * i386.md (pushsf): Do not preferre FLOAT_REGS over GENERAL_REGS. + (movsf): Likewise; unify 4th and 5th alternative. + (pushdf): Likewise. + (movdf_1): Likewise; rename to movdf_integer. + (pushxf): Likewise; rename to pushxf_integer; fix output template; + remove redundant splitter. + (movxf_1): Likewise; rename to movxf_integer; fix splitter's condition. + (movdf_nointeger): New. + (movxf_nointeger): New. + (pushxf_nointeger): New. + * i386.md (extend?f?f): Split to expander and pattern, refuse two memory operands in patterns. (fop*): Refuse two memory operands. diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h index ee2b51f5a511..e832a4495279 100644 --- a/gcc/config/i386/i386.h +++ b/gcc/config/i386/i386.h @@ -835,6 +835,7 @@ enum reg_class GENERAL_REGS, /* %eax %ebx %ecx %edx %esi %edi %ebp %esp */ FP_TOP_REG, FP_SECOND_REG, /* %st(0) %st(1) */ FLOAT_REGS, + FLOAT_INT_REGS, /* FLOAT_REGS and GENERAL_REGS. */ ALL_REGS, LIM_REG_CLASSES }; @@ -854,6 +855,7 @@ enum reg_class "GENERAL_REGS", \ "FP_TOP_REG", "FP_SECOND_REG", \ "FLOAT_REGS", \ + "FLOAT_INT_REGS", \ "ALL_REGS" } /* Define which registers fit in which classes. @@ -871,6 +873,7 @@ enum reg_class {0x100ff}, /* GENERAL_REGS */ \ {0x0100}, {0x0200}, /* FP_TOP_REG, FP_SECOND_REG */ \ {0xff00}, /* FLOAT_REGS */ \ + {0x1ffff}, /* FLOAT_INT_REGS */ \ {0x7ffff} \ } diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 8567cd54ed2a..bd429b89bff6 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -1697,7 +1697,7 @@ (define_insn "*pushsf" [(set (match_operand:SF 0 "push_operand" "=<,<") - (match_operand:SF 1 "general_operand" "f,Ffm*r"))] + (match_operand:SF 1 "general_operand" "f#r,rFm#f"))] "" "* { @@ -1731,9 +1731,9 @@ (set (mem:SF (reg:SI 7)) (match_dup 1))]) (define_insn "*movsf_1" - [(set (match_operand:SF 0 "nonimmediate_operand" "=f,m,f,*r,m,*r") - (match_operand:SF 1 "general_operand" "fm,f,G,*rm,F*r,GF"))] - "" + [(set (match_operand:SF 0 "nonimmediate_operand" "=f#r,m,f#r,r#f,m") + (match_operand:SF 1 "general_operand" "fm#r,f#r,G,rmF#f,Fr#f"))] + "GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM" "* { switch (which_alternative) @@ -1765,14 +1765,13 @@ case 3: case 4: - case 5: return \"mov{l}\\t{%1, %0|%0, %1}\"; default: abort(); } }" - [(set_attr "type" "fmov,fmov,fmov,imov,imov,imov")]) + [(set_attr "type" "fmov,fmov,fmov,imov,imov")]) (define_insn "swapsf" [(set (match_operand:SF 0 "register_operand" "+f") @@ -1795,9 +1794,14 @@ "" "ix86_expand_move (DFmode, operands); DONE;") +;; Size of pushdf is 3 (for sub) + 2 (for fstp) + memory operand size. +;; Size of pushdf using integer insturctions is 2+2*memory operand size +;; On the average, pushdf using integers can be still shorter. Allow this +;; pattern for optimize_size too. + (define_insn "*pushdf" [(set (match_operand:DF 0 "push_operand" "=<,<") - (match_operand:DF 1 "general_operand" "f,ofF*r"))] + (match_operand:DF 1 "general_operand" "f#r,rFo#f"))] "" "* { @@ -1838,10 +1842,59 @@ [(const_int 0)] "if (!ix86_split_long_move (operands)) abort (); DONE;") -(define_insn "*movdf_1" +;; Moving is usually shorter when only FP registers are used. This separate +;; movdf pattern avoids the use of integer registers for FP operations +;; when optimizing for size. + +(define_insn "*movdf_nointeger" [(set (match_operand:DF 0 "nonimmediate_operand" "=f,m,f,*r,o") (match_operand:DF 1 "general_operand" "fm,f,G,*roF,F*r"))] - "" + "(GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM) + && optimize_size" + "* +{ + switch (which_alternative) + { + case 0: + if (REG_P (operands[1]) + && find_regno_note (insn, REG_DEAD, REGNO (operands[1]))) + return \"fstp\\t%y0\"; + else if (STACK_TOP_P (operands[0])) + return \"fld%z1\\t%y1\"; + else + return \"fst\\t%y0\"; + + case 1: + if (find_regno_note (insn, REG_DEAD, REGNO (operands[1]))) + return \"fstp%z0\\t%y0\"; + else + return \"fst%z0\\t%y0\"; + + case 2: + switch (standard_80387_constant_p (operands[1])) + { + case 1: + return \"fldz\"; + case 2: + return \"fld1\"; + } + abort(); + + case 3: + case 4: + return \"#\"; + + default: + abort(); + } +}" + [(set_attr "type" "fmov,fmov,fmov,multi,multi")]) + +(define_insn "*movdf_integer" + [(set (match_operand:DF 0 "nonimmediate_operand" "=f#r,m,f#r,r#f,o") + (match_operand:DF 1 "general_operand" "fm#r,f#r,G,roF#f,Fr#f"))] + "(GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM) + && !optimize_size" "* { switch (which_alternative) @@ -1917,20 +1970,65 @@ "" "ix86_expand_move (XFmode, operands); DONE;") -(define_insn "*pushxf" +;; Size of pushdf is 3 (for sub) + 2 (for fstp) + memory operand size. +;; Size of pushdf using integer insturctions is 3+3*memory operand size +;; Pushing using integer instructions is longer except for constants +;; and direct memory references. +;; (assuming that any given constant is pushed only once, but this ought to be +;; handled elsewhere). + +(define_insn "*pushxf_nointeger" + [(set (match_operand:XF 0 "push_operand" "=<,<,<") + (match_operand:XF 1 "general_operand" "f,Fo,*r"))] + "optimize_size" + "* +{ + switch (which_alternative) + { + case 0: + /* %%% We loose REG_DEAD notes for controling pops if we split late. */ + operands[0] = gen_rtx_MEM (XFmode, stack_pointer_rtx); + operands[2] = stack_pointer_rtx; + operands[3] = GEN_INT (12); + if (find_regno_note (insn, REG_DEAD, REGNO (operands[1]))) + return \"sub{l}\\t{%3, %2|%2, %3}\;fstp%z0\\t%y0\"; + else + return \"sub{l}\\t{%3, %2|%2, %3}\;fst%z0\\t%y0\"; + + case 1: + case 2: + return \"#\"; + + default: + abort (); + } +}" + [(set_attr "type" "multi")]) + +(define_insn "*pushxf_integer" [(set (match_operand:XF 0 "push_operand" "=<,<") - (match_operand:XF 1 "register_operand" "f,oF*r"))] - "" + (match_operand:XF 1 "general_operand" "f#r,rFo#f"))] + "!optimize_size" "* { - /* %%% We loose REG_DEAD notes for controling pops if we split late. */ - operands[0] = gen_rtx_MEM (XFmode, stack_pointer_rtx); - operands[2] = stack_pointer_rtx; - operands[3] = GEN_INT (12); - if (find_regno_note (insn, REG_DEAD, REGNO (operands[1]))) - return \"sub{l}\\t{%3, %2|%2, %3}\;fstp%z0\\t%y0\"; - else - return \"sub{l}\\t{%3, %2|%2, %3}\;fst%z0\\t%y0\"; + switch (which_alternative) + { + case 0: + /* %%% We loose REG_DEAD notes for controling pops if we split late. */ + operands[0] = gen_rtx_MEM (XFmode, stack_pointer_rtx); + operands[2] = stack_pointer_rtx; + operands[3] = GEN_INT (12); + if (find_regno_note (insn, REG_DEAD, REGNO (operands[1]))) + return \"sub{l}\\t{%3, %2|%2, %3}\;fstp%z0\\t%y0\"; + else + return \"sub{l}\\t{%3, %2|%2, %3}\;fst%z0\\t%y0\"; + + case 1: + return \"#\"; + + default: + abort (); + } }" [(set_attr "type" "multi")]) @@ -1949,30 +2047,55 @@ [(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int -12))) (set (mem:XF (reg:SI 7)) (match_dup 1))]) -(define_split - [(set (match_operand:DF 0 "push_operand" "") - (match_operand:DF 1 "memory_operand" ""))] - "reload_completed" - [(set (mem:SI (pre_dec:SI (reg:SI 7))) (match_dup 2)) - (set (mem:SI (pre_dec:SI (reg:SI 7))) (match_dup 1)) - (set (mem:SI (pre_dec:SI (reg:SI 7))) (match_dup 0))] - " +;; Do not use integer registers when optimizing for size +(define_insn "*movxf_nointeger" + [(set (match_operand:XF 0 "nonimmediate_operand" "=f,m,f,*r,o") + (match_operand:XF 1 "general_operand" "fm,f,G,*roF,F*r"))] + "(GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM) + && optimize_size" + "* { - operands[0] = change_address (operands[1], SImode, NULL_RTX); - operands[1] = adj_offsettable_operand (operands[0], 4); - operands[2] = adj_offsettable_operand (operands[0], 8); - /* Compensate for the fact that we're changing stack offsets in - the middle of this operation. */ - if (reg_mentioned_p (stack_pointer_rtx, operands[1])) - operands[1] = adj_offsettable_operand (operands[1], 4); - if (reg_mentioned_p (stack_pointer_rtx, operands[0])) - operands[0] = adj_offsettable_operand (operands[0], 8); -}") + switch (which_alternative) + { + case 0: + if (REG_P (operands[1]) + && find_regno_note (insn, REG_DEAD, REGNO (operands[1]))) + return \"fstp\\t%y0\"; + else if (STACK_TOP_P (operands[0])) + return \"fld%z1\\t%y1\"; + else + return \"fst\\t%y0\"; -(define_insn "*movxf_1" - [(set (match_operand:XF 0 "nonimmediate_operand" "=f,m,f,*r,o") - (match_operand:XF 1 "general_operand" "fm,f,G,*roF,*r"))] - "" + case 1: + /* There is no non-popping store to memory for XFmode. So if + we need one, follow the store with a load. */ + if (! find_regno_note (insn, REG_DEAD, REGNO (operands[1]))) + return \"fstp%z0\\t%y0\;fld%z0\\t%y0\"; + else + return \"fstp%z0\\t%y0\"; + + case 2: + switch (standard_80387_constant_p (operands[1])) + { + case 1: + return \"fldz\"; + case 2: + return \"fld1\"; + } + break; + + case 3: case 4: + return \"#\"; + } + abort(); +}" + [(set_attr "type" "fmov,fmov,fmov,multi,multi")]) + +(define_insn "*movxf_integer" + [(set (match_operand:XF 0 "nonimmediate_operand" "=f#r,m,f#r,r#f,o") + (match_operand:XF 1 "general_operand" "fm#r,f#r,G,roF#f,Fr#f"))] + "(GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM) + && !optimize_size" "* { switch (which_alternative) @@ -2009,14 +2132,19 @@ } abort(); }" - [(set_attr "type" "fmov")]) + [(set_attr "type" "fmov,fmov,fmov,multi,multi")]) (define_split [(set (match_operand:XF 0 "nonimmediate_operand" "") (match_operand:XF 1 "general_operand" ""))] "reload_completed - && ((REG_P (operands[0]) && ! FP_REGNO_P (REGNO (operands[0]))) - || (REG_P (operands[1]) && ! FP_REGNO_P (REGNO (operands[1]))))" + && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM) + && ! (FP_REG_P (operands[0]) || + (GET_CODE (operands[0]) == SUBREG + && FP_REG_P (SUBREG_REG (operands[0])))) + && ! (FP_REG_P (operands[1]) || + (GET_CODE (operands[1]) == SUBREG + && FP_REG_P (SUBREG_REG (operands[1]))))" [(set (match_dup 2) (match_dup 5)) (set (match_dup 3) (match_dup 6)) (set (match_dup 4) (match_dup 7))]