i386.c (ix86_prepare_fp_compare_args): Do not force operand 0.0 into register in...
authorUros Bizjak <uros@kss-loka.si>
Wed, 8 Sep 2004 05:08:26 +0000 (07:08 +0200)
committerUros Bizjak <uros@gcc.gnu.org>
Wed, 8 Sep 2004 05:08:26 +0000 (07:08 +0200)
        * config/i386/i386.c (ix86_prepare_fp_compare_args): Do not
        force operand 0.0 into register in XFmode. Also do not force
        operand 0.0 into register if !TARGET_CMOVE.

        * config/i386/i386.md (*cmpfp_0): Delete. Remove comment.
        (*cmpfp_0_sf, cmpfp_0_df, cmpfp_0_xf): New patterns to
        implement ftst x87 instruction.
        (*fp_jcc_7): New insn pattern. Change corresponding split
        pattern to handle "general_operand" instead of
        "nonimmediate_operand".

----------------------------------------------------------------------

From-SVN: r87173

gcc/ChangeLog
gcc/config/i386/i386.c
gcc/config/i386/i386.md

index 17cdf17e52badfca1f8bf90a69299cd60722b4c2..a6f00a14c57645697ed56a3f321591c8ef02665c 100644 (file)
@@ -1,3 +1,15 @@
+2004-09-08  Uros Bizjak  <uros@kss-loka.si>
+
+       * config/i386/i386.c (ix86_prepare_fp_compare_args): Do not
+       force operand 0.0 into register in XFmode. Also do not force
+       operand 0.0 into register if !TARGET_CMOVE.
+       * config/i386/i386.md (*cmpfp_0): Delete. Remove comment.
+       (*cmpfp_0_sf, cmpfp_0_df, cmpfp_0_xf): New patterns to 
+       implement ftst x87 instruction.
+       (*fp_jcc_7): New insn pattern. Change corresponding split
+       pattern to handle "general_operand" instead of
+       "nonimmediate_operand".
+
 2004-09-08  Ben Elliston  <bje@au.ibm.com>
 
        * doc/rtl.texi (Insns): Document NOTE_INSN_FUNCTION_BEG.
index 4a8695275051342251b4ae48290c1966e9e7718e..3199b5756919542ac544dd7f6ce14ddd1fb8b349 100644 (file)
@@ -7941,12 +7941,15 @@ ix86_prepare_fp_compare_args (enum rtx_code code, rtx *pop0, rtx *pop1)
   int is_sse = SSE_REG_P (op0) | SSE_REG_P (op1);
 
   /* All of the unordered compare instructions only work on registers.
-     The same is true of the XFmode compare instructions.  The same is
-     true of the fcomi compare instructions.  */
+     The same is true of the fcomi compare instructions.  The same is
+     true of the XFmode compare instructions if not comparing with
+     zero (ftst insn is used in this case).  */
 
   if (!is_sse
       && (fpcmp_mode == CCFPUmode
-         || op_mode == XFmode
+         || (op_mode == XFmode
+             && ! (standard_80387_constant_p (op0) == 1
+                   || standard_80387_constant_p (op1) == 1))
          || ix86_use_fcomi_compare (code)))
     {
       op0 = force_reg (op_mode, op0);
@@ -7973,10 +7976,16 @@ ix86_prepare_fp_compare_args (enum rtx_code code, rtx *pop0, rtx *pop1)
 
       if (CONSTANT_P (op1))
        {
-         if (standard_80387_constant_p (op1))
-           op1 = force_reg (op_mode, op1);
-         else
+         int tmp = standard_80387_constant_p (op1);
+         if (tmp == 0)
            op1 = validize_mem (force_const_mem (op_mode, op1));
+         else if (tmp == 1)
+           {
+             if (TARGET_CMOVE)
+               op1 = force_reg (op_mode, op1);
+           }
+         else
+           op1 = force_reg (op_mode, op1);
        }
     }
 
index 3104e0aec2d11eab614731a83b64162c7b7d4dc2..f08c85a4d44eee29023b3d6842924d1c37a024af 100644 (file)
 ;; CCFPmode    compare with exceptions
 ;; CCFPUmode   compare with no exceptions
 
-;; %%% It is an unfortunate fact that ftst has no non-popping variant,
-;; and that fp moves clobber the condition codes, and that there is
-;; currently no way to describe this fact to reg-stack.  So there are
-;; no splitters yet for this.
-
-;; %%% YIKES!  This scheme does not retain a strong connection between 
-;; the real compare and the ultimate cc0 user, so CC_REVERSE does not
-;; work!  Only allow tos/mem with tos in op 0.
-;;
-;; Hmm, of course, this is what the actual _hardware_ does.  Perhaps
-;; things aren't as bad as they sound...
+(define_insn "*cmpfp_0_sf"
+  [(set (match_operand:HI 0 "register_operand" "=a")
+       (unspec:HI
+         [(compare:CCFP
+            (match_operand:SF 1 "register_operand" "f")
+            (match_operand:SF 2 "const0_operand" "X"))]
+       UNSPEC_FNSTSW))]
+  "TARGET_80387"
+{
+  if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
+    {
+      output_asm_insn ("ftst\;fnstsw\t%0", operands);
+      return TARGET_USE_FFREEP ? "ffreep\t%y1" : "fstp\t%y1";
+    }
+  else
+    return "ftst\;fnstsw\t%0";
+}
+  [(set_attr "type" "multi")
+   (set_attr "mode" "SF")])
 
-(define_insn "*cmpfp_0"
+(define_insn "*cmpfp_0_df"
   [(set (match_operand:HI 0 "register_operand" "=a")
        (unspec:HI
-         [(compare:CCFP (match_operand 1 "register_operand" "f")
-                        (match_operand 2 "const0_operand" "X"))]
-         UNSPEC_FNSTSW))]
-  "TARGET_80387
-   && FLOAT_MODE_P (GET_MODE (operands[1]))
-   && GET_MODE (operands[1]) == GET_MODE (operands[2])"
+         [(compare:CCFP
+            (match_operand:DF 1 "register_operand" "f")
+            (match_operand:DF 2 "const0_operand" "X"))]
+       UNSPEC_FNSTSW))]
+  "TARGET_80387"
 {
   if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
-    return "ftst\;fnstsw\t%0\;fstp\t%y0";
+    {
+      output_asm_insn ("ftst\;fnstsw\t%0", operands);
+      return TARGET_USE_FFREEP ? "ffreep\t%y1" : "fstp\t%y1";
+    }
   else
     return "ftst\;fnstsw\t%0";
 }
   [(set_attr "type" "multi")
-   (set (attr "mode")
-     (cond [(match_operand:SF 1 "" "")
-             (const_string "SF")
-           (match_operand:DF 1 "" "")
-             (const_string "DF")
-          ]
-          (const_string "XF")))])
+   (set_attr "mode" "DF")])
+
+(define_insn "*cmpfp_0_xf"
+  [(set (match_operand:HI 0 "register_operand" "=a")
+       (unspec:HI
+         [(compare:CCFP
+            (match_operand:XF 1 "register_operand" "f")
+            (match_operand:XF 2 "const0_operand" "X"))]
+       UNSPEC_FNSTSW))]
+  "TARGET_80387"
+{
+  if (find_regno_note (insn, REG_DEAD, REGNO (operands[1])))
+    {
+      output_asm_insn ("ftst\;fnstsw\t%0", operands);
+      return TARGET_USE_FFREEP ? "ffreep\t%y1" : "fstp\t%y1";
+    }
+  else
+    return "ftst\;fnstsw\t%0";
+}
+  [(set_attr "type" "multi")
+   (set_attr "mode" "XF")])
 
 ;; We may not use "#" to split and emit these, since the REG_DEAD notes
 ;; used to manage the reg stack popping would not be preserved.
    && ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))"
   "#")
 
+(define_insn "*fp_jcc_7"
+  [(set (pc)
+       (if_then_else (match_operator 0 "comparison_operator"
+                       [(match_operand 1 "register_operand" "f")
+                        (match_operand 2 "const_double_operand" "C")])
+         (label_ref (match_operand 3 "" ""))
+         (pc)))
+   (clobber (reg:CCFP FPSR_REG))
+   (clobber (reg:CCFP FLAGS_REG))
+   (clobber (match_scratch:HI 4 "=a"))]
+  "TARGET_80387
+   && FLOAT_MODE_P (GET_MODE (operands[1]))
+   && operands[2] == CONST0_RTX (GET_MODE (operands[1]))
+   && !ix86_use_fcomi_compare (GET_CODE (operands[0]))
+   && SELECT_CC_MODE (GET_CODE (operands[0]),
+                     operands[1], operands[2]) == CCFPmode
+   && ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))"
+  "#")
+
 (define_split
   [(set (pc)
        (if_then_else (match_operator 0 "comparison_operator"
   [(set (pc)
        (if_then_else (match_operator 0 "comparison_operator"
                        [(match_operand 1 "register_operand" "")
-                        (match_operand 2 "nonimmediate_operand" "")])
+                        (match_operand 2 "general_operand" "")])
          (match_operand 3 "" "")
          (match_operand 4 "" "")))
    (clobber (reg:CCFP FPSR_REG))
    (clobber (reg:CCFP FLAGS_REG))
    (clobber (match_scratch:HI 5 "=a"))]
   "reload_completed"
-  [(set (pc)
-       (if_then_else (match_dup 6)
-         (match_dup 3)
-         (match_dup 4)))]
+  [(const_int 0)]
 {
   ix86_split_fp_branch (GET_CODE (operands[0]), operands[1], operands[2],
                        operands[3], operands[4], operands[5]);