summaryrefslogtreecommitdiff
path: root/gcc/config
diff options
context:
space:
mode:
authorrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>2000-01-24 20:10:04 +0000
committerrth <rth@138bc75d-0d04-0410-961f-82ee72b054a4>2000-01-24 20:10:04 +0000
commita4110d9a66b1bfab2679b8b4774839bcfb1b3cba (patch)
treea9f7967b844ec94122754eade0945e4f551bf9f1 /gcc/config
parent8581412d5881e717bf3351f305d6b2e99dd64f96 (diff)
downloadgcc-a4110d9a66b1bfab2679b8b4774839bcfb1b3cba.tar.gz
* rtl.def: Add unordered fp comparisions.
* tree.def: Likewise. * tree.h: Add ISO C 9x unordered fp comparision builtins. * builtins.c (expand_tree_builtin): New function. * c-typeck.c (build_function_call): Use it. (build_binary_op): Support unordered compares. * c-common.c (c_common_nodes_and_builtins): Add unordered compares. * combine.c (known_cond): Handle reverse_condition returning UNKNOWN. (reversible_comparison_p): Allow UNORDERED/ORDERED to be reversed. * cse.c (fold_rtx): Check FLOAT_MODE_P before reversing. (record_jump_equiv): Handle reverse_condition returning UNKNOWN. * jump.c (reverse_condition): Don't abort for UNLE etc, but return UNKNOWN. (swap_condition): Handle unordered compares. (thread_jumps): Check can_reverse before reversing. * loop.c (get_condition): Likewise. Allow UNORERED/ORDERED to be reversed for FP. * optabs.c (can_compare_p): New argument CODE. Verify branch or setcc is present before acking for cmp_optab. Update all callers. (prepare_float_lib_cmp, init_optabs): Handle UNORDERED. * expmed.c (do_cmp_and_jump): Update for can_compare_p. * expr.c (expand_expr): Likewise. Support unordered compares. (do_jump, do_store_flag): Likewise. * expr.h (enum libfunc_index): Add unordered compares. * Makefile.in (FPBIT_FUNCS): Add _unord_sf. (DPBIT_FUNCS): Add _unord_df. * config/fp-bit.c (_unord_f2): New. * fp-test.c (main): Try unordered compare builtins. * alpha-protos.h (alpha_fp_comparison_operator): Declare. * alpha.c (alpha_comparison_operator): Check mode properly. (alpha_swapped_comparison_operator): Likewise. (signed_comparison_operator): Likewise. (alpha_fp_comparison_operator): New. (alpha_emit_conditional_branch): Handle unordered compares. * alpha.h (PREDICATE_CODES): Update. * alpha.md (fp compares): Use alpha_fp_comparison_operator. (bunordered, bordered): New. * cp/call.c (build_over_call): Use expand_tree_builtin. * cp/typeck.c (build_function_call_real): Likewise. (build_binary_op_nodefault): Handle unordered compares. * gcc.c-torture/execute/ieee/fp-cmp-4.c: New. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@31591 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config')
-rw-r--r--gcc/config/alpha/alpha-protos.h1
-rw-r--r--gcc/config/alpha/alpha.c43
-rw-r--r--gcc/config/alpha/alpha.h1
-rw-r--r--gcc/config/alpha/alpha.md38
-rw-r--r--gcc/config/fp-bit.c24
5 files changed, 83 insertions, 24 deletions
diff --git a/gcc/config/alpha/alpha-protos.h b/gcc/config/alpha/alpha-protos.h
index c29063e9fd2..693fa245bcc 100644
--- a/gcc/config/alpha/alpha-protos.h
+++ b/gcc/config/alpha/alpha-protos.h
@@ -58,6 +58,7 @@ extern int call_operand PARAMS ((rtx, enum machine_mode));
extern int alpha_comparison_operator PARAMS ((rtx, enum machine_mode));
extern int alpha_swapped_comparison_operator PARAMS ((rtx, enum machine_mode));
extern int signed_comparison_operator PARAMS ((rtx, enum machine_mode));
+extern int alpha_fp_comparison_operator PARAMS ((rtx, enum machine_mode));
extern int divmod_operator PARAMS ((rtx, enum machine_mode));
extern int aligned_memory_operand PARAMS ((rtx, enum machine_mode));
extern int unaligned_memory_operand PARAMS ((rtx, enum machine_mode));
diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c
index ca9e0ecaf35..cbc16883d6f 100644
--- a/gcc/config/alpha/alpha.c
+++ b/gcc/config/alpha/alpha.c
@@ -706,7 +706,7 @@ alpha_comparison_operator (op, mode)
{
enum rtx_code code = GET_CODE (op);
- if (mode != GET_MODE (op) || GET_RTX_CLASS (code) != '<')
+ if (mode != GET_MODE (op) && mode != VOIDmode)
return 0;
return (code == EQ || code == LE || code == LT
@@ -722,7 +722,8 @@ alpha_swapped_comparison_operator (op, mode)
{
enum rtx_code code = GET_CODE (op);
- if (mode != GET_MODE (op) || GET_RTX_CLASS (code) != '<')
+ if ((mode != GET_MODE (op) && mode != VOIDmode)
+ || GET_RTX_CLASS (code) != '<')
return 0;
code = swap_condition (code);
@@ -737,16 +738,30 @@ signed_comparison_operator (op, mode)
register rtx op;
enum machine_mode mode ATTRIBUTE_UNUSED;
{
- switch (GET_CODE (op))
- {
- case EQ: case NE: case LE: case LT: case GE: case GT:
- return 1;
+ enum rtx_code code = GET_CODE (op);
- default:
- break;
- }
+ if (mode != GET_MODE (op) && mode != VOIDmode)
+ return 0;
- return 0;
+ return (code == EQ || code == NE
+ || code == LE || code == LT
+ || code == GE || code == GT);
+}
+
+/* Return 1 if OP is a valid Alpha floating point comparison operator.
+ Here we know which comparisons are valid in which insn. */
+
+int
+alpha_fp_comparison_operator (op, mode)
+ register rtx op;
+ enum machine_mode mode;
+{
+ enum rtx_code code = GET_CODE (op);
+
+ if (mode != GET_MODE (op) && mode != VOIDmode)
+ return 0;
+
+ return (code == EQ || code == LE || code == LT || code == UNORDERED);
}
/* Return 1 if this is a divide or modulus operator. */
@@ -1484,13 +1499,15 @@ alpha_emit_conditional_branch (code)
switch (code)
{
case EQ: case LE: case LT: case LEU: case LTU:
+ case UNORDERED:
/* We have these compares: */
cmp_code = code, branch_code = NE;
break;
case NE:
- /* This must be reversed. */
- cmp_code = EQ, branch_code = EQ;
+ case ORDERED:
+ /* These must be reversed. */
+ cmp_code = reverse_condition (code), branch_code = EQ;
break;
case GE: case GT: case GEU: case GTU:
@@ -3383,6 +3400,8 @@ print_operand (file, x, code)
fprintf (file, "ule");
else if (c == LTU)
fprintf (file, "ult");
+ else if (c == UNORDERED)
+ fprintf (file, "un");
else
fprintf (file, "%s", GET_RTX_NAME (c));
}
diff --git a/gcc/config/alpha/alpha.h b/gcc/config/alpha/alpha.h
index b146a5a4c24..ad45596f0bb 100644
--- a/gcc/config/alpha/alpha.h
+++ b/gcc/config/alpha/alpha.h
@@ -2311,6 +2311,7 @@ do { \
{"alpha_comparison_operator", {EQ, LE, LT, LEU, LTU}}, \
{"alpha_swapped_comparison_operator", {EQ, GE, GT, GEU, GTU}}, \
{"signed_comparison_operator", {EQ, NE, LE, LT, GE, GT}}, \
+ {"alpha_fp_comparison_operator", {EQ, LE, LT, UNORDERED}}, \
{"divmod_operator", {DIV, MOD, UDIV, UMOD}}, \
{"fp0_operand", {CONST_DOUBLE}}, \
{"current_file_function_operand", {SYMBOL_REF}}, \
diff --git a/gcc/config/alpha/alpha.md b/gcc/config/alpha/alpha.md
index 5f0e2219bbd..2325483d02d 100644
--- a/gcc/config/alpha/alpha.md
+++ b/gcc/config/alpha/alpha.md
@@ -2752,12 +2752,12 @@
"")
;; The following are the corresponding floating-point insns. Recall
-;; we need to have variants that expand the arguments from SF mode
+;; we need to have variants that expand the arguments from SFmode
;; to DFmode.
-(define_insn ""
+(define_insn "*cmpdf_tp"
[(set (match_operand:DF 0 "register_operand" "=&f")
- (match_operator:DF 1 "alpha_comparison_operator"
+ (match_operator:DF 1 "alpha_fp_comparison_operator"
[(match_operand:DF 2 "reg_or_fp0_operand" "fG")
(match_operand:DF 3 "reg_or_fp0_operand" "fG")]))]
"TARGET_FP && alpha_fptm >= ALPHA_FPTM_SU"
@@ -2765,9 +2765,9 @@
[(set_attr "type" "fadd")
(set_attr "trap" "yes")])
-(define_insn ""
+(define_insn "*cmpdf_no_tp"
[(set (match_operand:DF 0 "register_operand" "=f")
- (match_operator:DF 1 "alpha_comparison_operator"
+ (match_operator:DF 1 "alpha_fp_comparison_operator"
[(match_operand:DF 2 "reg_or_fp0_operand" "fG")
(match_operand:DF 3 "reg_or_fp0_operand" "fG")]))]
"TARGET_FP && alpha_fptm < ALPHA_FPTM_SU"
@@ -2777,7 +2777,7 @@
(define_insn ""
[(set (match_operand:DF 0 "register_operand" "=&f")
- (match_operator:DF 1 "alpha_comparison_operator"
+ (match_operator:DF 1 "alpha_fp_comparison_operator"
[(float_extend:DF
(match_operand:SF 2 "reg_or_fp0_operand" "fG"))
(match_operand:DF 3 "reg_or_fp0_operand" "fG")]))]
@@ -2788,7 +2788,7 @@
(define_insn ""
[(set (match_operand:DF 0 "register_operand" "=f")
- (match_operator:DF 1 "alpha_comparison_operator"
+ (match_operator:DF 1 "alpha_fp_comparison_operator"
[(float_extend:DF
(match_operand:SF 2 "reg_or_fp0_operand" "fG"))
(match_operand:DF 3 "reg_or_fp0_operand" "fG")]))]
@@ -2799,7 +2799,7 @@
(define_insn ""
[(set (match_operand:DF 0 "register_operand" "=&f")
- (match_operator:DF 1 "alpha_comparison_operator"
+ (match_operator:DF 1 "alpha_fp_comparison_operator"
[(match_operand:DF 2 "reg_or_fp0_operand" "fG")
(float_extend:DF
(match_operand:SF 3 "reg_or_fp0_operand" "fG"))]))]
@@ -2810,7 +2810,7 @@
(define_insn ""
[(set (match_operand:DF 0 "register_operand" "=f")
- (match_operator:DF 1 "alpha_comparison_operator"
+ (match_operator:DF 1 "alpha_fp_comparison_operator"
[(match_operand:DF 2 "reg_or_fp0_operand" "fG")
(float_extend:DF
(match_operand:SF 3 "reg_or_fp0_operand" "fG"))]))]
@@ -2821,7 +2821,7 @@
(define_insn ""
[(set (match_operand:DF 0 "register_operand" "=&f")
- (match_operator:DF 1 "alpha_comparison_operator"
+ (match_operator:DF 1 "alpha_fp_comparison_operator"
[(float_extend:DF
(match_operand:SF 2 "reg_or_fp0_operand" "fG"))
(float_extend:DF
@@ -2833,7 +2833,7 @@
(define_insn ""
[(set (match_operand:DF 0 "register_operand" "=f")
- (match_operator:DF 1 "alpha_comparison_operator"
+ (match_operator:DF 1 "alpha_fp_comparison_operator"
[(float_extend:DF
(match_operand:SF 2 "reg_or_fp0_operand" "fG"))
(float_extend:DF
@@ -3126,6 +3126,22 @@
""
"{ operands[1] = alpha_emit_conditional_branch (GEU); }")
+(define_expand "bunordered"
+ [(set (pc)
+ (if_then_else (match_dup 1)
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "{ operands[1] = alpha_emit_conditional_branch (UNORDERED); }")
+
+(define_expand "bordered"
+ [(set (pc)
+ (if_then_else (match_dup 1)
+ (label_ref (match_operand 0 "" ""))
+ (pc)))]
+ ""
+ "{ operands[1] = alpha_emit_conditional_branch (ORDERED); }")
+
(define_expand "seq"
[(set (match_operand:DI 0 "register_operand" "")
(match_dup 1))]
diff --git a/gcc/config/fp-bit.c b/gcc/config/fp-bit.c
index d7bc3de38f4..fc496c0f059 100644
--- a/gcc/config/fp-bit.c
+++ b/gcc/config/fp-bit.c
@@ -1,7 +1,7 @@
/* This is a software floating point library which can be used instead of
the floating point routines in libgcc1.c for targets without hardware
floating point.
- Copyright (C) 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
+ Copyright (C) 1994-1998, 2000 Free Software Foundation, Inc.
This file is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
@@ -78,6 +78,8 @@ Boston, MA 02111-1307, USA. */
#define L_lt_df
#define L_le_sf
#define L_le_df
+#define L_unord_sf
+#define L_unord_df
#define L_si_to_sf
#define L_si_to_df
#define L_sf_to_si
@@ -268,6 +270,7 @@ typedef unsigned int UDItype __attribute__ ((mode (DI)));
# define _ge_f2 __gesf2
# define _lt_f2 __ltsf2
# define _le_f2 __lesf2
+# define _unord_f2 __unordsf2
# define si_to_float __floatsisf
# define float_to_si __fixsfsi
# define float_to_usi __fixunssfsi
@@ -285,6 +288,7 @@ typedef unsigned int UDItype __attribute__ ((mode (DI)));
# define _ge_f2 __gedf2
# define _lt_f2 __ltdf2
# define _le_f2 __ledf2
+# define _unord_f2 __unorddf2
# define si_to_float __floatsidf
# define float_to_si __fixdfsi
# define float_to_usi __fixunsdfsi
@@ -1370,6 +1374,24 @@ _le_f2 (FLO_type arg_a, FLO_type arg_b)
}
#endif
+#if defined(L_unord_sf) || defined(L_unord_df)
+CMPtype
+_unord_f2 (FLO_type arg_a, FLO_type arg_b)
+{
+ fp_number_type a;
+ fp_number_type b;
+ FLO_union_type au, bu;
+
+ au.value = arg_a;
+ bu.value = arg_b;
+
+ unpack_d (&au, &a);
+ unpack_d (&bu, &b);
+
+ return (isnan (&a) || isnan (&b);
+}
+#endif
+
#endif /* ! US_SOFTWARE_GOFAST */
#if defined(L_si_to_sf) || defined(L_si_to_df)