i386-protos.h (ix86_split_fp_branch): New rtx argument.
authorUros Bizjak <uros@kss-loka.si>
Wed, 8 Dec 2004 06:50:58 +0000 (07:50 +0100)
committerUros Bizjak <uros@gcc.gnu.org>
Wed, 8 Dec 2004 06:50:58 +0000 (07:50 +0100)
        * config/i386/i386-protos.h (ix86_split_fp_branch): New rtx
        argument.

        * config/i386/i386.c (output_fp_compare): Fix is_sse condition.
        Use EFLAGS_P only when fcomi insn should be used. Fix handling
        of eflags_p variable. Change alt table accordingly. For non-fcomi
        compare insn always use trailing fnstsw insn. Fix intmode
        calculation for ficom insn.
        (ix86_split_fp_branch): Add "rtx pushed" as new parameter. Call
        ix86_free_from_memory when "pushed" is specified.
        (ix86_expand_branch): Change call to ix86_split_fp_branch.

        * config/i386/i386.md (*cmpfp_0_sf, *cmpfp_0_df, *cmpfp_0_xf):
        Change eflags_p parameter in call to output_fp_compare.
        (*cmpfp_2_sf, *cmpfp_2_df, *cmpfp_2_xf): Remove.
        (*cmpfp_2_sf_1, *cmpfp_2_df_1, *cmpfp_2_xf_1): Rename to
        *cmpfp_2_sf, *cmpfp_2_df, *cmpfp_2_xf.  Change eflags_p
        parameter in call to output_fp_compare.
        (*cmpfp_2_u): Remove.
        (*cmpfp_2_u_1): Rename to *cmpfp_2_u. Change eflags_p parameter
        in call to output_fp_compare.
        (*ficom_1): Remove insn definition and corresponding define_split.
        (*cmpfp_si): New insn definition.
        (*fp_jcc_8): New insn definition. Add new splitters for
        "memory_operand" and "register_operand".
        (define_split): Add new parameter in call to ix86_split_fp_branch.

        config/i386/predicates.md (float_operator): New predicate.

From-SVN: r91856

gcc/ChangeLog
gcc/config/i386/i386-protos.h
gcc/config/i386/i386.c
gcc/config/i386/i386.md
gcc/config/i386/predicates.md

index 9c032694b1ed209fbd0f50726d4f944de79cbb79..7b526cc1fa4a3c05a8def47ba44d99e02e847167 100644 (file)
@@ -1,3 +1,34 @@
+2004-12-07  Uros Bizjak  <uros@kss-loka.si>
+
+       * config/i386/i386-protos.h (ix86_split_fp_branch): New rtx
+       argument.
+
+       * config/i386/i386.c (output_fp_compare): Fix is_sse condition.
+       Use EFLAGS_P only when fcomi insn should be used. Fix handling
+       of eflags_p variable. Change alt table accordingly. For non-fcomi
+       compare insn always use trailing fnstsw insn. Fix intmode
+       calculation for ficom insn.
+       (ix86_split_fp_branch): Add "rtx pushed" as new parameter. Call
+       ix86_free_from_memory when "pushed" is specified.
+       (ix86_expand_branch): Change call to ix86_split_fp_branch.
+
+       * config/i386/i386.md (*cmpfp_0_sf, *cmpfp_0_df, *cmpfp_0_xf):
+       Change eflags_p parameter in call to output_fp_compare.
+       (*cmpfp_2_sf, *cmpfp_2_df, *cmpfp_2_xf): Remove.
+       (*cmpfp_2_sf_1, *cmpfp_2_df_1, *cmpfp_2_xf_1): Rename to
+       *cmpfp_2_sf, *cmpfp_2_df, *cmpfp_2_xf.  Change eflags_p
+       parameter in call to output_fp_compare.
+       (*cmpfp_2_u): Remove.
+       (*cmpfp_2_u_1): Rename to *cmpfp_2_u. Change eflags_p parameter
+       in call to output_fp_compare.
+       (*ficom_1): Remove insn definition and corresponding define_split.
+       (*cmpfp_si): New insn definition.
+       (*fp_jcc_8): New insn definition. Add new splitters for
+       "memory_operand" and "register_operand".
+       (define_split): Add new parameter in call to ix86_split_fp_branch.
+
+       config/i386/predicates.md (float_operator): New predicate.
+
 2004-12-08  Kazu Hirata  <kazu@cs.umass.edu>
 
        * c-common.c (verify_tree): Don't check code length if we know
index d0ff2e16621287d099cd63c25fef9ccc41b37756..c79acd033ca9d0592f7c051c6245ae22051f8c0b 100644 (file)
@@ -165,7 +165,8 @@ extern rtx ix86_va_arg (tree, tree);
 
 extern rtx ix86_force_to_memory (enum machine_mode, rtx);
 extern void ix86_free_from_memory (enum machine_mode);
-extern void ix86_split_fp_branch (enum rtx_code code, rtx, rtx, rtx, rtx, rtx);
+extern void ix86_split_fp_branch (enum rtx_code code, rtx, rtx,
+                                 rtx, rtx, rtx, rtx);
 extern int ix86_hard_regno_mode_ok (int, enum machine_mode);
 extern int ix86_register_move_cost (enum machine_mode, enum reg_class,
                                    enum reg_class);
index 1a63fe08873dbc012798ccd4c194fa33eece8578..2bd53bc862f8ba4d7a4c41542489fa4e4175832a 100644 (file)
@@ -7208,25 +7208,24 @@ output_fix_trunc (rtx insn, rtx *operands)
 }
 
 /* Output code for INSN to compare OPERANDS.  EFLAGS_P is 1 when fcomi
-   should be used and 2 when fnstsw should be used.  UNORDERED_P is true
-   when fucom should be used.  */
+   should be used.  UNORDERED_P is true when fucom should be used.  */
 
 const char *
 output_fp_compare (rtx insn, rtx *operands, int eflags_p, int unordered_p)
 {
   int stack_top_dies;
   rtx cmp_op0, cmp_op1;
-  int is_sse = SSE_REG_P (operands[0]) | SSE_REG_P (operands[1]);
+  int is_sse = SSE_REG_P (operands[0]) || SSE_REG_P (operands[1]);
 
-  if (eflags_p == 2)
+  if (eflags_p)
     {
-      cmp_op0 = operands[1];
-      cmp_op1 = operands[2];
+      cmp_op0 = operands[0];
+      cmp_op1 = operands[1];
     }
   else
     {
-      cmp_op0 = operands[0];
-      cmp_op1 = operands[1];
+      cmp_op0 = operands[1];
+      cmp_op1 = operands[2];
     }
 
   if (is_sse)
@@ -7268,7 +7267,7 @@ output_fp_compare (rtx insn, rtx *operands, int eflags_p, int unordered_p)
         is also a stack register that dies, then this must be a
         `fcompp' float compare */
 
-      if (eflags_p == 1)
+      if (eflags_p)
        {
          /* There is no double popping fcomi variant.  Fortunately,
             eflags is immune from the fstp's cc clobbering.  */
@@ -7280,35 +7279,25 @@ output_fp_compare (rtx insn, rtx *operands, int eflags_p, int unordered_p)
        }
       else
        {
-         if (eflags_p == 2)
-           {
-             if (unordered_p)
-               return "fucompp\n\tfnstsw\t%0";
-             else
-               return "fcompp\n\tfnstsw\t%0";
-           }
+         if (unordered_p)
+           return "fucompp\n\tfnstsw\t%0";
          else
-           {
-             if (unordered_p)
-               return "fucompp";
-             else
-               return "fcompp";
-           }
+           return "fcompp\n\tfnstsw\t%0";
        }
     }
   else
     {
       /* Encoded here as eflags_p | intmode | unordered_p | stack_top_dies.  */
 
-      static const char * const alt[24] =
+      static const char * const alt[16] =
       {
-       "fcom%z1\t%y1",
-       "fcomp%z1\t%y1",
-       "fucom%z1\t%y1",
-       "fucomp%z1\t%y1",
+       "fcom%z2\t%y2\n\tfnstsw\t%0",
+       "fcomp%z2\t%y2\n\tfnstsw\t%0",
+       "fucom%z2\t%y2\n\tfnstsw\t%0",
+       "fucomp%z2\t%y2\n\tfnstsw\t%0",
 
-       "ficom%z1\t%y1",
-       "ficomp%z1\t%y1",
+       "ficom%z2\t%y2\n\tfnstsw\t%0",
+       "ficomp%z2\t%y2\n\tfnstsw\t%0",
        NULL,
        NULL,
 
@@ -7320,16 +7309,6 @@ output_fp_compare (rtx insn, rtx *operands, int eflags_p, int unordered_p)
        NULL,
        NULL,
        NULL,
-       NULL,
-
-       "fcom%z2\t%y2\n\tfnstsw\t%0",
-       "fcomp%z2\t%y2\n\tfnstsw\t%0",
-       "fucom%z2\t%y2\n\tfnstsw\t%0",
-       "fucomp%z2\t%y2\n\tfnstsw\t%0",
-
-       "ficom%z2\t%y2\n\tfnstsw\t%0",
-       "ficomp%z2\t%y2\n\tfnstsw\t%0",
-       NULL,
        NULL
       };
 
@@ -7337,11 +7316,11 @@ output_fp_compare (rtx insn, rtx *operands, int eflags_p, int unordered_p)
       const char *ret;
 
       mask  = eflags_p << 3;
-      mask |= (GET_MODE_CLASS (GET_MODE (operands[1])) == MODE_INT) << 2;
+      mask |= (GET_MODE_CLASS (GET_MODE (cmp_op1)) == MODE_INT) << 2;
       mask |= unordered_p << 1;
       mask |= stack_top_dies;
 
-      if (mask >= 24)
+      if (mask >= 16)
        abort ();
       ret = alt[mask];
       if (ret == NULL)
@@ -8458,7 +8437,7 @@ ix86_expand_branch (enum rtx_code code, rtx label)
          {
            ix86_split_fp_branch (code, ix86_compare_op0, ix86_compare_op1,
                                  gen_rtx_LABEL_REF (VOIDmode, label),
-                                 pc_rtx, NULL_RTX);
+                                 pc_rtx, NULL_RTX, NULL_RTX);
          }
        else
          {
@@ -8606,7 +8585,7 @@ ix86_expand_branch (enum rtx_code code, rtx label)
 /* Split branch based on floating point condition.  */
 void
 ix86_split_fp_branch (enum rtx_code code, rtx op1, rtx op2,
-                     rtx target1, rtx target2, rtx tmp)
+                     rtx target1, rtx target2, rtx tmp, rtx pushed)
 {
   rtx second, bypass;
   rtx label = NULL_RTX;
@@ -8625,6 +8604,10 @@ ix86_split_fp_branch (enum rtx_code code, rtx op1, rtx op2,
   condition = ix86_expand_fp_compare (code, op1, op2,
                                      tmp, &second, &bypass);
 
+  /* Remove pushed operand from stack.  */
+  if (pushed)
+    ix86_free_from_memory (GET_MODE (pushed));
+
   if (split_branch_probability >= 0)
     {
       /* Distribute the probabilities across the jumps.
index 84617c5f7ebe0dac308674250a7d37979d7966cb..84b97e86805ec8976c0499e359ab833d717d6174 100644 (file)
 ;; CCFPmode    compare with exceptions
 ;; CCFPUmode   compare with no exceptions
 
+;; 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.
+
 (define_insn "*cmpfp_0_sf"
   [(set (match_operand:HI 0 "register_operand" "=a")
        (unspec:HI
             (match_operand:SF 2 "const0_operand" "X"))]
        UNSPEC_FNSTSW))]
   "TARGET_80387"
-  "* return output_fp_compare (insn, operands, 2, 0);"
+  "* return output_fp_compare (insn, operands, 0, 0);"
   [(set_attr "type" "multi")
    (set_attr "mode" "SF")])
 
             (match_operand:DF 2 "const0_operand" "X"))]
        UNSPEC_FNSTSW))]
   "TARGET_80387"
-  "* return output_fp_compare (insn, operands, 2, 0);"
+  "* return output_fp_compare (insn, operands, 0, 0);"
   [(set_attr "type" "multi")
    (set_attr "mode" "DF")])
 
             (match_operand:XF 2 "const0_operand" "X"))]
        UNSPEC_FNSTSW))]
   "TARGET_80387"
-  "* return output_fp_compare (insn, operands, 2, 0);"
+  "* return output_fp_compare (insn, operands, 0, 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.
-
-(define_insn "*cmpfp_2_sf"
-  [(set (reg:CCFP FPSR_REG)
-       (compare:CCFP
-         (match_operand:SF 0 "register_operand" "f")
-         (match_operand:SF 1 "nonimmediate_operand" "fm")))]
-  "TARGET_80387"
-  "* return output_fp_compare (insn, operands, 0, 0);"
-  [(set_attr "type" "fcmp")
-   (set_attr "mode" "SF")])
-
-(define_insn "*cmpfp_2_sf_1"
+(define_insn "*cmpfp_sf"
   [(set (match_operand:HI 0 "register_operand" "=a")
        (unspec:HI
          [(compare:CCFP
             (match_operand:SF 2 "nonimmediate_operand" "fm"))]
          UNSPEC_FNSTSW))]
   "TARGET_80387"
-  "* return output_fp_compare (insn, operands, 2, 0);"
-  [(set_attr "type" "fcmp")
-   (set_attr "mode" "SF")])
-
-(define_insn "*cmpfp_2_df"
-  [(set (reg:CCFP FPSR_REG)
-       (compare:CCFP
-         (match_operand:DF 0 "register_operand" "f")
-         (match_operand:DF 1 "nonimmediate_operand" "fm")))]
-  "TARGET_80387"
   "* return output_fp_compare (insn, operands, 0, 0);"
   [(set_attr "type" "fcmp")
-   (set_attr "mode" "DF")])
+   (set_attr "mode" "SF")])
 
-(define_insn "*cmpfp_2_df_1"
+(define_insn "*cmpfp_df"
   [(set (match_operand:HI 0 "register_operand" "=a")
        (unspec:HI
          [(compare:CCFP
             (match_operand:DF 2 "nonimmediate_operand" "fm"))]
          UNSPEC_FNSTSW))]
   "TARGET_80387"
-  "* return output_fp_compare (insn, operands, 2, 0);"
+  "* return output_fp_compare (insn, operands, 0, 0);"
   [(set_attr "type" "multi")
    (set_attr "mode" "DF")])
 
-(define_insn "*cmpfp_2_xf"
-  [(set (reg:CCFP FPSR_REG)
-       (compare:CCFP
-         (match_operand:XF 0 "register_operand" "f")
-         (match_operand:XF 1 "register_operand" "f")))]
-  "TARGET_80387"
-  "* return output_fp_compare (insn, operands, 0, 0);"
-  [(set_attr "type" "fcmp")
-   (set_attr "mode" "XF")])
-
-(define_insn "*cmpfp_2_xf_1"
+(define_insn "*cmpfp_xf"
   [(set (match_operand:HI 0 "register_operand" "=a")
        (unspec:HI
          [(compare:CCFP
             (match_operand:XF 2 "register_operand" "f"))]
          UNSPEC_FNSTSW))]
   "TARGET_80387"
-  "* return output_fp_compare (insn, operands, 2, 0);"
+  "* return output_fp_compare (insn, operands, 0, 0);"
   [(set_attr "type" "multi")
    (set_attr "mode" "XF")])
 
-(define_insn "*cmpfp_2u"
-  [(set (reg:CCFPU FPSR_REG)
-       (compare:CCFPU
-         (match_operand 0 "register_operand" "f")
-         (match_operand 1 "register_operand" "f")))]
-  "TARGET_80387
-   && FLOAT_MODE_P (GET_MODE (operands[0]))
-   && GET_MODE (operands[0]) == GET_MODE (operands[1])"
-  "* return output_fp_compare (insn, operands, 0, 1);"
-  [(set_attr "type" "fcmp")
-   (set (attr "mode")
-     (cond [(match_operand:SF 1 "" "")
-             (const_string "SF")
-           (match_operand:DF 1 "" "")
-             (const_string "DF")
-          ]
-          (const_string "XF")))])
-
-(define_insn "*cmpfp_2u_1"
+(define_insn "*cmpfp_u"
   [(set (match_operand:HI 0 "register_operand" "=a")
        (unspec:HI
          [(compare:CCFPU
   "TARGET_80387
    && FLOAT_MODE_P (GET_MODE (operands[1]))
    && GET_MODE (operands[1]) == GET_MODE (operands[2])"
-  "* return output_fp_compare (insn, operands, 2, 1);"
+  "* return output_fp_compare (insn, operands, 0, 1);"
   [(set_attr "type" "multi")
    (set (attr "mode")
      (cond [(match_operand:SF 1 "" "")
           ]
           (const_string "XF")))])
 
-;; Patterns to match the SImode-in-memory ficom instructions.
-;;
-;; %%% Play games with accepting gp registers, as otherwise we have to
-;; force them to memory during rtl generation, which is no good.  We
-;; can get rid of this once we teach reload to do memory input reloads 
-;; via pushes.
-
-(define_insn "*ficom_1"
-  [(set (reg:CCFP FPSR_REG)
-       (compare:CCFP
-         (match_operand 0 "register_operand" "f,f")
-         (float (match_operand:SI 1 "nonimmediate_operand" "m,?r"))))]
-  "0 && TARGET_80387 && FLOAT_MODE_P (GET_MODE (operands[0]))
-   && GET_MODE (XEXP (SET_SRC (PATTERN (insn)), 1)) == GET_MODE (operands[0])"
-  "#")
-
-;; Split the not-really-implemented gp register case into a
-;; push-op-pop sequence.
-;;
-;; %%% This is most efficient, but am I gonna get in trouble
-;; for separating cc0_setter and cc0_user?
-
-(define_split
-  [(set (reg:CCFP FPSR_REG)
-       (compare:CCFP
-         (match_operand:SF 0 "register_operand" "")
-         (float (match_operand:SI 1 "register_operand" ""))))]
-  "0 && TARGET_80387 && reload_completed"
-  [(set (mem:SI (pre_dec:SI (reg:SI SP_REG))) (match_dup 1))
-   (set (reg:CCFP FPSR_REG) (compare:CCFP (match_dup 0) (match_dup 2)))
-   (parallel [(set (match_dup 1) (mem:SI (reg:SI SP_REG)))
-              (set (reg:SI SP_REG) (plus:SI (reg:SI SP_REG) (const_int 4)))])]
-  "operands[2] = gen_rtx_MEM (Pmode, stack_pointer_rtx);
-   operands[2] = gen_rtx_FLOAT (GET_MODE (operands[0]), operands[2]);")
+(define_insn "*cmpfp_si"
+  [(set (match_operand:HI 0 "register_operand" "=a")
+       (unspec:HI
+         [(compare:CCFP
+            (match_operand 1 "register_operand" "f")
+            (match_operator 3 "float_operator"
+              [(match_operand:SI 2 "memory_operand" "m")]))]
+         UNSPEC_FNSTSW))]
+  "TARGET_80387 && TARGET_USE_FIOP
+   && FLOAT_MODE_P (GET_MODE (operands[1]))
+   && (GET_MODE (operands [3]) == GET_MODE (operands[1]))"
+  "* return output_fp_compare (insn, operands, 0, 0);"
+  [(set_attr "type" "multi")
+   (set_attr "fp_int_src" "true")
+   (set_attr "mode" "SI")])
 
 ;; FP compares, step 2
 ;; Move the fpsw to ax.
    && ix86_fp_jump_nontrivial_p (GET_CODE (operands[0]))"
   "#")
 
+;; The order of operands in *fp_jcc_8 is forced by combine in
+;; simplify_comparison () function. Float operator is treated as RTX_OBJ
+;; with a precedence over other operators and is always put in the first
+;; place. Swap condition and operands to match ficom instruction.
+
+(define_insn "*fp_jcc_8"
+  [(set (pc)
+       (if_then_else (match_operator 0 "comparison_operator"
+                       [(match_operator 1 "float_operator"
+                          [(match_operand:SI 2 "nonimmediate_operand" "m,?r")])
+                          (match_operand 3 "register_operand" "f,f")])
+         (label_ref (match_operand 4 "" ""))
+         (pc)))
+   (clobber (reg:CCFP FPSR_REG))
+   (clobber (reg:CCFP FLAGS_REG))
+   (clobber (match_scratch:HI 5 "=a,a"))]
+  "TARGET_80387 && TARGET_USE_FIOP
+   && FLOAT_MODE_P (GET_MODE (operands[3]))
+   && GET_MODE (operands[1]) == GET_MODE (operands[3])
+   && !ix86_use_fcomi_compare (swap_condition (GET_CODE (operands[0])))
+   && ix86_fp_compare_mode (swap_condition (GET_CODE (operands[0]))) == CCFPmode
+   && ix86_fp_jump_nontrivial_p (swap_condition (GET_CODE (operands[0])))"
+  "#")
+
 (define_split
   [(set (pc)
        (if_then_else (match_operator 0 "comparison_operator"
   [(const_int 0)]
 {
   ix86_split_fp_branch (GET_CODE (operands[0]), operands[1], operands[2],
-                       operands[3], operands[4], NULL_RTX);
+                       operands[3], operands[4], NULL_RTX, NULL_RTX);
   DONE;
 })
 
   [(const_int 0)]
 {
   ix86_split_fp_branch (GET_CODE (operands[0]), operands[1], operands[2],
-                       operands[3], operands[4], operands[5]);
+                       operands[3], operands[4], operands[5], NULL_RTX);
+  DONE;
+})
+
+(define_split
+  [(set (pc)
+       (if_then_else (match_operator 0 "comparison_operator"
+                       [(match_operator 1 "float_operator"
+                          [(match_operand:SI 2 "memory_operand" "")])
+                          (match_operand 3 "register_operand" "")])
+         (match_operand 4 "" "")
+         (match_operand 5 "" "")))
+   (clobber (reg:CCFP FPSR_REG))
+   (clobber (reg:CCFP FLAGS_REG))
+   (clobber (match_scratch:HI 6 "=a"))]
+  "reload_completed"
+  [(const_int 0)]
+{
+  operands[7] = gen_rtx_FLOAT (GET_MODE (operands[1]), operands[2]);
+  ix86_split_fp_branch (swap_condition (GET_CODE (operands[0])),
+                       operands[3], operands[7],
+                       operands[4], operands[5], operands[6], NULL_RTX);
+  DONE;
+})
+
+;; %%% Kill this when reload knows how to do it.
+(define_split
+  [(set (pc)
+       (if_then_else (match_operator 0 "comparison_operator"
+                       [(match_operator 1 "float_operator"
+                          [(match_operand:SI 2 "register_operand" "")])
+                          (match_operand 3 "register_operand" "")])
+         (match_operand 4 "" "")
+         (match_operand 5 "" "")))
+   (clobber (reg:CCFP FPSR_REG))
+   (clobber (reg:CCFP FLAGS_REG))
+   (clobber (match_scratch:HI 6 "=a"))]
+  "reload_completed"
+  [(const_int 0)]
+{
+  operands[7] = ix86_force_to_memory (GET_MODE (operands[2]), operands[2]);
+  operands[7] = gen_rtx_FLOAT (GET_MODE (operands[1]), operands[7]);
+  ix86_split_fp_branch (swap_condition (GET_CODE (operands[0])),
+                       operands[3], operands[7],
+                       operands[4], operands[5], operands[6], operands[2]);
   DONE;
 })
 \f
index ec747aef20ecb384a0aa8262106bbc7248409157..9154aea8c62080776b84535f31e0ed71d51f7305 100644 (file)
 (define_predicate "div_operator"
   (match_code "div"))
 
+;; Return true if this is a float extend operation.
+(define_predicate "float_operator"
+  (match_code "float"))
+
 ;; Return true for ARITHMETIC_P.
 (define_predicate "arith_or_logical_operator"
   (match_code "PLUS,MULT,AND,IOR,XOR,SMIN,SMAX,UMIN,UMAX,COMPARE,MINUS,DIV,