(truncdfsf2): Rewrite to allow FLOAT_REGS in constraints for better register preferences.
authorJames Van Artsdalen <jrv@gnu.org>
Fri, 12 Mar 1993 09:34:38 +0000 (09:34 +0000)
committerJames Van Artsdalen <jrv@gnu.org>
Fri, 12 Mar 1993 09:34:38 +0000 (09:34 +0000)
(truncdfsf2): Rewrite to allow FLOAT_REGS in constraints
   for better register preferences.
(movM): If REG_WAS_0, make sure the reg hasn't changed since then.
(cmpM expanders): Don't allow both operands to be MEM.
Use VOIDmode for the COMPARE rtx instead of CCmode.
(cmpM recognizers): Likewise.
Remove constraints for constants from operand 0.
(cmpdf,cmpsf recognizers): When using VOIDmode as mode of the COMPARE rtx,
   require that the mode be exactly VOIDmode.

From-SVN: r3716

gcc/config/i386/i386.md

index 7073b251b8083381ef2cc67472c126335a96bc85..c701df61d577fcadd8bbe588cc44b2964c34f372 100644 (file)
@@ -69,7 +69,7 @@
 ;; actually generating RTL.  The bCOND or sCOND (emitted immediately
 ;; after the tstM or cmp) will actually emit the tstM or cmpM.
 
-(define_insn "tstsi_cc"
+(define_insn "tstsi_1"
   [(set (cc0)
        (match_operand:SI 0 "nonimmediate_operand" "rm"))]
   ""
   ""
   "
 {
-  i386_compare_gen = gen_tstsi_cc;
+  i386_compare_gen = gen_tstsi_1;
   i386_compare_op0 = operands[0];
   DONE;
 }")
 
-(define_insn "tsthi_cc"
+(define_insn "tsthi_1"
   [(set (cc0)
        (match_operand:HI 0 "nonimmediate_operand" "rm"))]
   ""
   ""
   "
 {
-  i386_compare_gen = gen_tsthi_cc;
+  i386_compare_gen = gen_tsthi_1;
   i386_compare_op0 = operands[0];
   DONE;
 }")
 
-(define_insn "tstqi_cc"
+(define_insn "tstqi_1"
   [(set (cc0)
        (match_operand:QI 0 "nonimmediate_operand" "qm"))]
   ""
   ""
   "
 {
-  i386_compare_gen = gen_tstqi_cc;
+  i386_compare_gen = gen_tstqi_1;
   i386_compare_op0 = operands[0];
   DONE;
 }")
 ;;- compare instructions.  See comments above tstM patterns about
 ;;  expansion of these insns.
 
-(define_insn "cmpsi_cc"
+(define_insn "cmpsi_1"
   [(set (cc0)
-       (compare:CC (match_operand:SI 0 "nonimmediate_operand" "mr,ri")
-                   (match_operand:SI 1 "general_operand" "ri,mr")))]
-  ""
+       (compare (match_operand:SI 0 "nonimmediate_operand" "mr,r")
+                (match_operand:SI 1 "general_operand" "ri,mr")))]
+  "GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM"
   "*
 {
   if (CONSTANT_P (operands[0]) || GET_CODE (operands[1]) == MEM)
 
 (define_expand "cmpsi"
   [(set (cc0)
-       (compare:CC (match_operand:SI 0 "nonimmediate_operand" "")
-                   (match_operand:SI 1 "general_operand" "")))]
+       (compare (match_operand:SI 0 "nonimmediate_operand" "")
+                (match_operand:SI 1 "general_operand" "")))]
   ""
   "
 {
-  i386_compare_gen = gen_cmpsi_cc;
+  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
+    operands[0] = force_reg (SImode, operands[0]);
+
+  i386_compare_gen = gen_cmpsi_1;
   i386_compare_op0 = operands[0];
   i386_compare_op1 = operands[1];
   DONE;
 }")
 
-(define_insn "cmphi_cc"
+(define_insn "cmphi_1"
   [(set (cc0)
-       (compare:CC (match_operand:HI 0 "nonimmediate_operand" "mr,ri")
-                   (match_operand:HI 1 "general_operand" "ri,mr")))]
-  ""
+       (compare (match_operand:HI 0 "nonimmediate_operand" "mr,r")
+                (match_operand:HI 1 "general_operand" "ri,mr")))]
+  "GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM"
   "*
 {
   if (CONSTANT_P (operands[0]) || GET_CODE (operands[1]) == MEM)
 
 (define_expand "cmphi"
   [(set (cc0)
-       (compare:CC (match_operand:HI 0 "nonimmediate_operand" "")
-                   (match_operand:HI 1 "general_operand" "")))]
+       (compare (match_operand:HI 0 "nonimmediate_operand" "")
+                (match_operand:HI 1 "general_operand" "")))]
   ""
   "
 {
-  i386_compare_gen = gen_cmphi_cc;
+  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
+    operands[0] = force_reg (HImode, operands[0]);
+
+  i386_compare_gen = gen_cmphi_1;
   i386_compare_op0 = operands[0];
   i386_compare_op1 = operands[1];
   DONE;
 }")
 
-(define_insn "cmpqi_cc"
+(define_insn "cmpqi_1"
   [(set (cc0)
-       (compare:CC (match_operand:QI 0 "nonimmediate_operand" "qn,mq")
-                   (match_operand:QI 1 "general_operand" "qm,nq")))]
-  ""
+       (compare (match_operand:QI 0 "nonimmediate_operand" "q,mq")
+                (match_operand:QI 1 "general_operand" "qm,nq")))]
+  "GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM"
   "*
 {
   if (CONSTANT_P (operands[0]) || GET_CODE (operands[1]) == MEM)
 
 (define_expand "cmpqi"
   [(set (cc0)
-       (compare:CC (match_operand:QI 0 "nonimmediate_operand" "")
-                   (match_operand:QI 1 "general_operand" "")))]
+       (compare (match_operand:QI 0 "nonimmediate_operand" "")
+                (match_operand:QI 1 "general_operand" "")))]
   ""
   "
 {
-  i386_compare_gen = gen_cmpqi_cc;
+  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
+    operands[0] = force_reg (QImode, operands[0]);
+
+  i386_compare_gen = gen_cmpqi_1;
   i386_compare_op0 = operands[0];
   i386_compare_op1 = operands[1];
   DONE;
 ;; SFmode, there is the normal insn, and an insn where the second operand
 ;; is converted to the desired mode.
 
-(define_insn "cmpdf_cc"
+(define_insn ""
   [(set (cc0)
-       (compare:CC (match_operand:DF 0 "nonimmediate_operand" "f,fm")
-                   (match_operand:DF 1 "nonimmediate_operand" "fm,f")))
-   (clobber (match_scratch:HI 2 "=a,a"))]
+       (match_operator 2 "VOIDmode_compare_op"
+                       [(match_operand:DF 0 "nonimmediate_operand" "f,fm")
+                        (match_operand:DF 1 "nonimmediate_operand" "fm,f")]))
+   (clobber (match_scratch:HI 3 "=a,a"))]
   "TARGET_80387
    && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
   "* return (char *) output_float_compare (insn, operands);")
 
 (define_insn ""
   [(set (cc0)
-       (compare:CC (match_operand:DF 0 "register_operand" "f")
-                   (float:DF
-                    (match_operand:SI 1 "nonimmediate_operand" "rm"))))
-   (clobber (match_scratch:HI 2 "=a"))]
-  "TARGET_80387"
-  "* return (char *) output_float_compare (insn, operands);")
-
-(define_insn ""
-  [(set (cc0)
-       (compare:CC (float:DF
-                    (match_operand:SI 0 "nonimmediate_operand" "rm"))
-                   (match_operand:DF 1 "register_operand" "f")))
-   (clobber (match_scratch:HI 2 "=a"))]
+       (match_operator 2 "VOIDmode_compare_op"
+                       [(match_operand:DF 0 "register_operand" "f")
+                        (float:DF
+                         (match_operand:SI 1 "nonimmediate_operand" "rm"))]))
+   (clobber (match_scratch:HI 3 "=a"))]
   "TARGET_80387"
   "* return (char *) output_float_compare (insn, operands);")
 
 (define_insn ""
   [(set (cc0)
-       (compare:CC (match_operand:DF 0 "register_operand" "f")
-                   (float_extend:DF
-                    (match_operand:SF 1 "nonimmediate_operand" "fm"))))
-   (clobber (match_scratch:HI 2 "=a"))]
+       (match_operator 2 "VOIDmode_compare_op"
+                       [(float:DF
+                         (match_operand:SI 0 "nonimmediate_operand" "rm"))
+                        (match_operand:DF 1 "register_operand" "f")]))
+   (clobber (match_scratch:HI 3 "=a"))]
   "TARGET_80387"
   "* return (char *) output_float_compare (insn, operands);")
 
 (define_insn ""
   [(set (cc0)
-       (compare:CC (float_extend:DF
-                    (match_operand:SF 0 "nonimmediate_operand" "fm"))
-                   (match_operand:DF 1 "register_operand" "f")))
-   (clobber (match_scratch:HI 2 "=a"))]
+       (match_operator 2 "VOIDmode_compare_op"
+                       [(match_operand:DF 0 "register_operand" "f")
+                        (float_extend:DF
+                         (match_operand:SF 1 "nonimmediate_operand" "fm"))]))
+   (clobber (match_scratch:HI 3 "=a"))]
   "TARGET_80387"
   "* return (char *) output_float_compare (insn, operands);")
 
 (define_insn ""
   [(set (cc0)
-       (compare:CCFPEQ (match_operand:DF 0 "register_operand" "f")
-                       (match_operand:DF 1 "register_operand" "f")))
-   (clobber (match_scratch:HI 2 "=a"))]
+       (match_operator 2 "VOIDmode_compare_op"
+                       [(float_extend:DF
+                         (match_operand:SF 0 "nonimmediate_operand" "fm"))
+                        (match_operand:DF 1 "register_operand" "f")]))
+   (clobber (match_scratch:HI 3 "=a"))]
   "TARGET_80387"
   "* return (char *) output_float_compare (insn, operands);")
 
 (define_insn ""
   [(set (cc0)
        (compare:CCFPEQ (match_operand:DF 0 "register_operand" "f")
-                       (float_extend:DF
-                        (match_operand:SF 1 "register_operand" "f"))))
-   (clobber (match_scratch:HI 2 "=a"))]
-  "TARGET_80387"
-  "* return (char *) output_float_compare (insn, operands);")
-
-(define_insn ""
-  [(set (cc0)
-       (compare:CCFPEQ (float_extend:DF
-                        (match_operand:SF 0 "register_operand" "f"))
                        (match_operand:DF 1 "register_operand" "f")))
    (clobber (match_scratch:HI 2 "=a"))]
   "TARGET_80387"
   "* return (char *) output_float_compare (insn, operands);")
 
-(define_insn "cmpsf_cc"
+;; These two insns will never be generated by combine due to the mode of
+;; the COMPARE.
+;(define_insn ""
+;  [(set (cc0)
+;      (compare:CCFPEQ (match_operand:DF 0 "register_operand" "f")
+;                      (float_extend:DF
+;                       (match_operand:SF 1 "register_operand" "f"))))
+;   (clobber (match_scratch:HI 2 "=a"))]
+;  "TARGET_80387"
+;  "* return (char *) output_float_compare (insn, operands);")
+;
+;(define_insn ""
+;  [(set (cc0)
+;      (compare:CCFPEQ (float_extend:DF
+;                       (match_operand:SF 0 "register_operand" "f"))
+;                      (match_operand:DF 1 "register_operand" "f")))
+;   (clobber (match_scratch:HI 2 "=a"))]
+;  "TARGET_80387"
+;  "* return (char *) output_float_compare (insn, operands);")
+
+(define_insn "cmpsf_cc_1"
   [(set (cc0)
-       (compare:CC (match_operand:SF 0 "nonimmediate_operand" "f,fm")
-                   (match_operand:SF 1 "nonimmediate_operand" "fm,f")))
-   (clobber (match_scratch:HI 2 "=a,a"))]
+       (match_operator 2 "VOIDmode_compare_op"
+                       [(match_operand:SF 0 "nonimmediate_operand" "f,fm")
+                        (match_operand:SF 1 "nonimmediate_operand" "fm,f")]))
+   (clobber (match_scratch:HI 3 "=a,a"))]
   "TARGET_80387
    && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
   "* return (char *) output_float_compare (insn, operands);")
 
 (define_insn ""
   [(set (cc0)
-       (compare:CC (match_operand:SF 0 "register_operand" "f")
-                   (float:SF
-                    (match_operand:SI 1 "nonimmediate_operand" "rm"))))
-   (clobber (match_scratch:HI 2 "=a"))]
+       (match_operator 2 "VOIDmode_compare_op"
+                       [(match_operand:SF 0 "register_operand" "f")
+                        (float:SF
+                         (match_operand:SI 1 "nonimmediate_operand" "rm"))]))
+   (clobber (match_scratch:HI 3 "=a"))]
   "TARGET_80387"
   "* return (char *) output_float_compare (insn, operands);")
 
 (define_insn ""
   [(set (cc0)
-       (compare:CC (float:SF
-                    (match_operand:SI 0 "nonimmediate_operand" "rm"))
-                   (match_operand:SF 1 "register_operand" "f")))
-   (clobber (match_scratch:HI 2 "=a"))]
+       (match_operator 2 "VOIDmode_compare_op"
+                       [(float:SF
+                         (match_operand:SI 0 "nonimmediate_operand" "rm"))
+                        (match_operand:SF 1 "register_operand" "f")]))
+   (clobber (match_scratch:HI 3 "=a"))]
   "TARGET_80387"
   "* return (char *) output_float_compare (insn, operands);")
 
 
 (define_expand "cmpdf"
   [(set (cc0)
-       (compare:CC (match_operand:DF 0 "register_operand" "")
-                   (match_operand:DF 1 "nonimmediate_operand" "")))]
+       (compare (match_operand:DF 0 "register_operand" "")
+                (match_operand:DF 1 "nonimmediate_operand" "")))]
   "TARGET_80387"
   "
 {
 
 (define_expand "cmpsf"
   [(set (cc0)
-       (compare:CC (match_operand:SF 0 "register_operand" "")
-                   (match_operand:SF 1 "nonimmediate_operand" "")))]
+       (compare (match_operand:SF 0 "register_operand" "")
+                (match_operand:SF 1 "nonimmediate_operand" "")))]
   "TARGET_80387"
   "
 {
   DONE;
 }")
 
+(define_expand "cmpdf_cc"
+  [(parallel [(set (cc0)
+                  (compare (match_operand:DF 0 "register_operand" "")
+                           (match_operand:DF 1 "register_operand" "")))
+             (clobber (match_scratch:HI 2 ""))])]
+  "TARGET_80387"
+  "")
+
 (define_expand "cmpdf_ccfpeq"
   [(parallel [(set (cc0)
                   (compare:CCFPEQ (match_operand:DF 0 "register_operand" "")
     operands[1] = copy_to_mode_reg (DFmode, operands[1]);
 }")
 
+(define_expand "cmpsf_cc"
+  [(parallel [(set (cc0)
+                  (compare (match_operand:SF 0 "register_operand" "")
+                           (match_operand:SF 1 "register_operand" "")))
+             (clobber (match_scratch:HI 2 ""))])]
+  "TARGET_80387"
+  "")
+
 (define_expand "cmpsf_ccfpeq"
   [(parallel [(set (cc0)
                   (compare:CCFPEQ (match_operand:SF 0 "register_operand" "")
   if (operands[1] == const1_rtx
       && (link = find_reg_note (insn, REG_WAS_0, 0))
       /* Make sure the insn that stored the 0 is still present.  */
-      && ! XEXP (link, 0)->volatil
+      && ! INSN_DELETED_P (XEXP (link, 0))
       && GET_CODE (XEXP (link, 0)) != NOTE
       /* Make sure cross jumping didn't happen here.  */
-      && no_labels_between_p (XEXP (link, 0), insn))
+      && no_labels_between_p (XEXP (link, 0), insn)
+      /* Make sure the reg hasn't been clobbered.  */
+      && ! reg_set_between_p (operands[0], XEXP (link, 0), insn))
     /* Fastest way to change a 0 to a 1.  */
     return AS1 (inc%L0,%0);
 
   if (REG_P (operands[0]) && operands[1] == const1_rtx 
       && (link = find_reg_note (insn, REG_WAS_0, 0))
       /* Make sure the insn that stored the 0 is still present.  */
-      && ! XEXP (link, 0)->volatil
+      && ! INSN_DELETED_P (XEXP (link, 0))
       && GET_CODE (XEXP (link, 0)) != NOTE
       /* Make sure cross jumping didn't happen here.  */
-      && no_labels_between_p (XEXP (link, 0), insn))
+      && no_labels_between_p (XEXP (link, 0), insn)
+      /* Make sure the reg hasn't been clobbered.  */
+      && ! reg_set_between_p (operands[0], XEXP (link, 0), insn))
     /* Fastest way to change a 0 to a 1.  */
     return AS1 (inc%L0,%k0);
 
   if (operands[1] == const1_rtx
       && (link = find_reg_note (insn, REG_WAS_0, 0))
       /* Make sure the insn that stored the 0 is still present.  */
-      && ! XEXP (link, 0)->volatil
+      && ! INSN_DELETED_P (XEXP (link, 0))
       && GET_CODE (XEXP (link, 0)) != NOTE
       /* Make sure cross jumping didn't happen here.  */
-      && no_labels_between_p (XEXP (link, 0), insn))
+      && no_labels_between_p (XEXP (link, 0), insn)
+      /* Make sure the reg hasn't been clobbered.  */
+      && ! reg_set_between_p (operands[0], XEXP (link, 0), insn))
     /* Fastest way to change a 0 to a 1.  */
     return AS1 (inc%W0,%0);
 
   if (operands[1] == const1_rtx
       && (link = find_reg_note (insn, REG_WAS_0, 0))
       /* Make sure the insn that stored the 0 is still present.  */
-      && ! XEXP (link, 0)->volatil
+      && ! INSN_DELETED_P (XEXP (link, 0))
       && GET_CODE (XEXP (link, 0)) != NOTE
       /* Make sure cross jumping didn't happen here.  */
-      && no_labels_between_p (XEXP (link, 0), insn))
+      && no_labels_between_p (XEXP (link, 0), insn)
+      /* Make sure the reg hasn't been clobbered.  */
+      && ! reg_set_between_p (operands[0], XEXP (link, 0), insn))
     /* Fastest way to change a 0 to a 1.  */
     return AS1 (inc%B0,%0);
 
   if (operands[1] == const1_rtx
       && (link = find_reg_note (insn, REG_WAS_0, 0))
       /* Make sure the insn that stored the 0 is still present.  */
-      && ! XEXP (link, 0)->volatil
+      && ! INSN_DELETED_P (XEXP (link, 0))
       && GET_CODE (XEXP (link, 0)) != NOTE
       /* Make sure cross jumping didn't happen here.  */
-      && no_labels_between_p (XEXP (link, 0), insn))
+      && no_labels_between_p (XEXP (link, 0), insn)
+      /* Make sure the reg hasn't been clobbered.  */
+      && ! reg_set_between_p (operands[0], XEXP (link, 0), insn))
     /* Fastest way to change a 0 to a 1.  */
     return AS1 (inc%B0,%0);
 
   return AS1 (push%L1,%1);
 }")
 
-;; The constraints used to be:
-;; op 0 "=f,fm,!*rf,!*rm"
-;; op 1 "fmG,f,*rfm,*rfF"
+;; Allow MEM-MEM moves before reload.  The reload class for such a
+;; move will be ALL_REGS.  PREFERRED_RELOAD_CLASS will narrow this to
+;; GENERAL_REGS.  For the purposes of regclass, prefer FLOAT_REGS.
 
 (define_insn "movsf"
   [(set (match_operand:SF 0 "general_operand" "=*rf,*rfm,f,!*rm")
     return AS1 (fxch,%0);
 }")
 
-;; The constraints used to be:
-;; op 0 "=f,fm,!*rf,!*rm"
-;; op 1 "fmG,f,*rfm,*rfF"
+;; Allow MEM-MEM moves before reload.  The reload class for such a
+;; move will be ALL_REGS.  PREFERRED_RELOAD_CLASS will narrow this to
+;; GENERAL_REGS.  For the purposes of regclass, prefer FLOAT_REGS.
 
 (define_insn "movdf"
   [(set (match_operand:DF 0 "general_operand" "=*rf,*rfm,f,!*rm")
 ;; insn.
 
 (define_insn "truncdfsf2"
-  [(set (match_operand:SF 0 "general_operand" "=m,!*r")
+  [(set (match_operand:SF 0 "nonimmediate_operand" "=f,m")
        (float_truncate:SF
-        (match_operand:DF 1 "register_operand" "f,f")))]
+        (match_operand:DF 1 "register_operand" "0,f")))]
   "TARGET_80387"
   "*
 {
   int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
 
-  if (NON_STACK_REG_P (operands[0]))
-    {
-      output_to_reg (operands[0], stack_top_dies);
-      RET;
-    }
-  else if (GET_CODE (operands[0]) == MEM)
+  if (GET_CODE (operands[0]) == MEM)
     {
       if (stack_top_dies)
        return AS1 (fstp%z0,%0);
       else
         return AS1 (fst%z0,%0);
     }
+  else if (STACK_TOP_P (operands[0]))
+    {
+      rtx xops[4];
+
+      xops[0] = AT_SP (SFmode);
+      xops[1] = stack_pointer_rtx;
+      xops[2] = GEN_INT (GET_MODE_SIZE (SFmode));
+      xops[3] = operands[0];
+
+      output_asm_insn (AS2 (sub%L1,%2,%1), xops);
+      output_asm_insn (AS1 (fstp%z0,%y0), xops);
+      output_asm_insn (AS1 (fld%z0,%y0), xops);
+      output_asm_insn (AS2 (add%L1,%2,%1), xops);
+      RET;
+    }
   else
     abort ();
 }")