]> gcc.gnu.org Git - gcc.git/commitdiff
i386.h (enum reg_class): Add FLOAT_INT_REGS.
authorJan Hubicka <hubicka@freesoft.cz>
Fri, 19 Nov 1999 20:50:36 +0000 (21:50 +0100)
committerJan Hubicka <hubicka@gcc.gnu.org>
Fri, 19 Nov 1999 20:50:36 +0000 (20:50 +0000)
* 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

gcc/ChangeLog
gcc/config/i386/i386.h
gcc/config/i386/i386.md

index 663be335a8412559221f67365d3f96c681a4dd82..3e1552b3c36f188cc551cfb2b533c059bebb684e 100644 (file)
@@ -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.
index ee2b51f5a5112d86b6f2c29ad5b4f34c54247a33..e832a44952792c5284cc1cf5d361f825c7404ceb 100644 (file)
@@ -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}                                                     \
 }
 
index 8567cd54ed2a9a0e00fa5ffd16e8733f9a4c7e18..bd429b89bff67bffb08e950c42e7c39b25d1dbf9 100644 (file)
 
 (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"))]
   ""
   "*
 {
    (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)
 
     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")
   ""
   "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"))]
   ""
   "*
 {
   [(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)
   ""
   "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")])
 
   [(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)
     }
   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))]
This page took 0.086558 seconds and 5 git commands to generate.