aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZack Weinberg <zack@codesourcery.com>2003-10-29 01:28:09 +0000
committerZack Weinberg <zack@gcc.gnu.org>2003-10-29 01:28:09 +0000
commit24ea7948dc54d6458adf654750c67d8d0ed4c055 (patch)
tree18ee97a45e6e621740dd8e3b0fcfd007028453ed
parentb38ba46301ac50a5c0d8c93953aa150d748bff8b (diff)
downloadgcc-24ea7948dc54d6458adf654750c67d8d0ed4c055.zip
gcc-24ea7948dc54d6458adf654750c67d8d0ed4c055.tar.gz
gcc-24ea7948dc54d6458adf654750c67d8d0ed4c055.tar.bz2
ia64.c (cmptf_libfunc): New static.
* 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
-rw-r--r--gcc/ChangeLog10
-rw-r--r--gcc/config/ia64/ia64.c71
-rw-r--r--gcc/config/ia64/ia64.md11
3 files changed, 86 insertions, 6 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 585e25b..b5823a9 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,15 @@
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.
(*sqrt_approx): New instruction pattern for approximate square roots.
(*setf_exp_xf): New instruction pattern for exponentiation.
diff --git a/gcc/config/ia64/ia64.c b/gcc/config/ia64/ia64.c
index a25c4c5..f494570 100644
--- a/gcc/config/ia64/ia64.c
+++ b/gcc/config/ia64/ia64.c
@@ -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");
diff --git a/gcc/config/ia64/ia64.md b/gcc/config/ia64/ia64.md
index ec66fd5..ddaff6e 100644
--- a/gcc/config/ia64/ia64.md
+++ b/gcc/config/ia64/ia64.md
@@ -4484,6 +4484,17 @@
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"