aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJan Hubicka <hubicka@freesoft.cz>1999-11-19 21:50:36 +0100
committerJan Hubicka <hubicka@gcc.gnu.org>1999-11-19 20:50:36 +0000
commit8fcaaa8099e6073951189584b1e482b0ff373ba1 (patch)
treef03313c0d43159024dfdfe2c450a61c59e8730d1 /gcc
parentf97d9ec3779fba07c222b4241da011afb1664a24 (diff)
downloadgcc-8fcaaa8099e6073951189584b1e482b0ff373ba1.zip
gcc-8fcaaa8099e6073951189584b1e482b0ff373ba1.tar.gz
gcc-8fcaaa8099e6073951189584b1e482b0ff373ba1.tar.bz2
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog15
-rw-r--r--gcc/config/i386/i386.h3
-rw-r--r--gcc/config/i386/i386.md218
3 files changed, 191 insertions, 45 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 663be33..3e1552b 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,20 @@
Fri Nov 19 06:32:19 CET 1999 Jan Hubicka <hubicka@freesoft.cz>
+ * 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 ee2b51f..e832a44 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 8567cd5..bd429b8 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))]