ia64.c (cmptf_libfunc): New static.
authorZack Weinberg <zack@codesourcery.com>
Wed, 29 Oct 2003 01:28:09 +0000 (01:28 +0000)
committerZack Weinberg <zack@gcc.gnu.org>
Wed, 29 Oct 2003 01:28:09 +0000 (01:28 +0000)
* config/ia64/ia64.c (cmptf_libfunc): New static.
(ia64_expand_compare): Add logic to open-code calls to
_U_Qfcmp for TFmode comparisons.
(ia64_hpux_init_libfuncs): Initialize cmptf_libfunc.
Set libfuncs for TFmode eq/ne/gt/ge/lt/gt to 0; these should
never be generated anymore.
* config/ia64/ia64.md (cmptf): New expander.

From-SVN: r73028

gcc/ChangeLog
gcc/config/ia64/ia64.c
gcc/config/ia64/ia64.md

index 585e25b6aefd6f478108374f2ca17b8fd1cc8bc9..b5823a992d1f0cc1ab760860e54193825c8a02b6 100644 (file)
@@ -1,3 +1,13 @@
+2003-10-28  Zack Weinberg  <zack@codesourcery.com>
+
+       * config/ia64/ia64.c (cmptf_libfunc): New static.
+       (ia64_expand_compare): Add logic to open-code calls to
+       _U_Qfcmp for TFmode comparisons.
+       (ia64_hpux_init_libfuncs): Initialize cmptf_libfunc.
+       Set libfuncs for TFmode eq/ne/gt/ge/lt/gt to 0; these should
+       never be generated anymore.
+       * config/ia64/ia64.md (cmptf): New expander.
+
 2003-10-28  Zack Weinberg  <zack@codesourcery.com>
 
        * ia64.md (UNSPEC_SETF_EXP,UNSPEC_FR_SQRT_RECIP_APPROX): New constants.
index a25c4c5a83d2d190ac6217ec3989d58fb77b2793..f4945709d105f65db617bfcfdf037bc3f11128c4 100644 (file)
@@ -1465,6 +1465,8 @@ spill_xfmode_operand (rtx in, int force)
 /* Emit comparison instruction if necessary, returning the expression
    that holds the compare result in the proper mode.  */
 
+static GTY(()) rtx cmptf_libfunc;
+
 rtx
 ia64_expand_compare (enum rtx_code code, enum machine_mode mode)
 {
@@ -1480,6 +1482,59 @@ ia64_expand_compare (enum rtx_code code, enum machine_mode mode)
       else
        abort ();
     }
+  /* HPUX TFmode compare requires a library call to _U_Qfcmp, which takes a
+     magic number as its third argument, that indicates what to do.
+     The return value is an integer to be compared against zero.  */
+  else if (TARGET_HPUX && GET_MODE (op0) == TFmode)
+    {
+      enum qfcmp_magic {
+       QCMP_INV = 1,   /* Raise FP_INVALID on SNaN as a side effect.  */
+       QCMP_UNORD = 2,
+       QCMP_EQ = 4,
+       QCMP_LT = 8,
+       QCMP_GT = 16
+      } magic;
+      enum rtx_code ncode;
+      rtx ret, insns;
+      if (GET_MODE (op1) != TFmode)
+       abort ();
+      switch (code)
+       {
+         /* 1 = equal, 0 = not equal.  Equality operators do
+            not raise FP_INVALID when given an SNaN operand.  */
+       case EQ:        magic = QCMP_EQ;                  ncode = NE; break;
+       case NE:        magic = QCMP_EQ;                  ncode = EQ; break;
+         /* isunordered() from C99.  */
+       case UNORDERED: magic = QCMP_UNORD;               ncode = NE; break;
+         /* Relational operators raise FP_INVALID when given
+            an SNaN operand.  */
+       case LT:        magic = QCMP_LT        |QCMP_INV; ncode = NE; break;
+       case LE:        magic = QCMP_LT|QCMP_EQ|QCMP_INV; ncode = NE; break;
+       case GT:        magic = QCMP_GT        |QCMP_INV; ncode = NE; break;
+       case GE:        magic = QCMP_GT|QCMP_EQ|QCMP_INV; ncode = NE; break;
+         /* FUTURE: Implement UNEQ, UNLT, UNLE, UNGT, UNGE, LTGT.
+            Expanders for buneq etc. weuld have to be added to ia64.md
+            for this to be useful.  */
+       default: abort ();
+       }
+
+      start_sequence ();
+
+      ret = emit_library_call_value (cmptf_libfunc, 0, LCT_CONST, DImode, 3,
+                                    op0, TFmode, op1, TFmode,
+                                    GEN_INT (magic), DImode);
+      cmp = gen_reg_rtx (BImode);
+      emit_insn (gen_rtx_SET (VOIDmode, cmp,
+                             gen_rtx_fmt_ee (ncode, BImode,
+                                             ret, const0_rtx)));
+
+      insns = get_insns ();
+      end_sequence ();
+
+      emit_libcall_block (insns, cmp, cmp,
+                         gen_rtx_fmt_ee (code, BImode, op0, op1));
+      code = NE;
+    }
   else
     {
       cmp = gen_reg_rtx (BImode);
@@ -8338,12 +8393,16 @@ ia64_hpux_init_libfuncs (void)
   set_optab_libfunc (abs_optab, TFmode, "_U_Qfabs");
   set_optab_libfunc (neg_optab, TFmode, "_U_Qfneg");
 
-  set_optab_libfunc (eq_optab, TFmode, "_U_Qfeq");
-  set_optab_libfunc (ne_optab, TFmode, "_U_Qfne");
-  set_optab_libfunc (gt_optab, TFmode, "_U_Qfgt");
-  set_optab_libfunc (ge_optab, TFmode, "_U_Qfge");
-  set_optab_libfunc (lt_optab, TFmode, "_U_Qflt");
-  set_optab_libfunc (le_optab, TFmode, "_U_Qfle");
+  /* ia64_expand_compare uses this.  */
+  cmptf_libfunc = init_one_libfunc ("_U_Qfcmp");
+
+  /* These should never be used.  */
+  set_optab_libfunc (eq_optab, TFmode, 0);
+  set_optab_libfunc (ne_optab, TFmode, 0);
+  set_optab_libfunc (gt_optab, TFmode, 0);
+  set_optab_libfunc (ge_optab, TFmode, 0);
+  set_optab_libfunc (lt_optab, TFmode, 0);
+  set_optab_libfunc (le_optab, TFmode, 0);
 
   set_conv_libfunc (sext_optab,   TFmode, SFmode, "_U_Qfcnvff_sgl_to_quad");
   set_conv_libfunc (sext_optab,   TFmode, DFmode, "_U_Qfcnvff_dbl_to_quad");
index ec66fd5a77de3e625ca9863d38667b9d896263fa..ddaff6ec7a9e2aeeb1d7178023cc9203d0493c1c 100644 (file)
   DONE;
 })
 
+(define_expand "cmptf"
+  [(set (cc0)
+        (compare (match_operand:TF 0 "gr_register_operand" "")
+                (match_operand:TF 1 "gr_register_operand" "")))]
+  "TARGET_HPUX"
+{
+  ia64_compare_op0 = operands[0];
+  ia64_compare_op1 = operands[1];
+  DONE;
+})
+
 (define_insn "*cmpsi_normal"
   [(set (match_operand:BI 0 "register_operand" "=c")
        (match_operator:BI 1 "normal_comparison_operator"