This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Fix E500 unordered comparisons
- From: "Joseph S. Myers" <joseph at codesourcery dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Tue, 1 May 2007 15:42:44 +0000 (UTC)
- Subject: Fix E500 unordered comparisons
E500 processors lack instructions to do unordered comparisons. For the
simple case (__builtin_isunordered) this causes libcalls to be generated.
For TFmode this is unfortunately __unordtf2, which isn't defined; this
patch makes it use the same __gcc_qunord used for soft-float in that case.
For the compound case (testing unordered-or-something-else), the E500
compares quietly ignore the "unordered" part of the testing. Fixed by
disabling relevant instruction patterns for E500 (as bunordered/sunordered
already are disabled) so the core compiler will generate the composition
of a libcall to test unordered and a comparison for the rest.
Tested with cross to powerpc-none-linux-gnuspe, with
gcc.c-torture/execute/ieee/ieee.exp enabled. (Running the IEEE tests on
E500 requires kernel trap handlers from Freescale, and it seems these
still have some bugs in the version I have so there are still some
ieee.exp failures after this patch.) OK to commit?
2007-05-01 Joseph Myers <joseph@codesourcery.com>
* config/rs6000/darwin-ldouble.c (__gcc_qunord): Define if
__NO_FPRS__, not just if _SOFT_DOUBLE.
* config/rs6000/libgcc-ppc-glibc.ver (__gcc_qunord): Likewise.
* config/rs6000/rs6000.c (rs6000_init_libfuncs): Use __gcc_qunord
also for E500 double.
* config/rs6000/rs6000.md (buneq, bunge, bungt, bunle, bunlt,
suneq, sunge, sungt, sunle, sunlt): Disable for (TARGET_HARD_FLOAT
&& !TARGET_FPRS).
Index: config/rs6000/darwin-ldouble.c
===================================================================
--- config/rs6000/darwin-ldouble.c (revision 124330)
+++ config/rs6000/darwin-ldouble.c (working copy)
@@ -225,7 +225,6 @@
int __gcc_qne (double, double, double, double);
int __gcc_qge (double, double, double, double);
int __gcc_qle (double, double, double, double);
-int __gcc_qunord (double, double, double, double);
long double __gcc_stoq (float);
long double __gcc_dtoq (double);
float __gcc_qtos (double, double);
@@ -238,7 +237,6 @@
extern int __eqdf2 (double, double);
extern int __ledf2 (double, double);
extern int __gedf2 (double, double);
-extern int __unorddf2 (double, double);
/* Negate 'long double' value and return the result. */
long double
@@ -284,15 +282,6 @@
strong_alias (__gcc_qge, __gcc_qgt);
-/* Compare two 'long double' values for unordered. */
-int
-__gcc_qunord (double a, double aa, double c, double cc)
-{
- if (__eqdf2 (a, c) == 0)
- return __unorddf2 (aa, cc);
- return __unorddf2 (a, c);
-}
-
/* Convert single to long double. */
long double
__gcc_stoq (float a)
@@ -365,6 +354,20 @@
#ifdef __NO_FPRS__
+int __gcc_qunord (double, double, double, double);
+
+extern int __eqdf2 (double, double);
+extern int __unorddf2 (double, double);
+
+/* Compare two 'long double' values for unordered. */
+int
+__gcc_qunord (double a, double aa, double c, double cc)
+{
+ if (__eqdf2 (a, c) == 0)
+ return __unorddf2 (aa, cc);
+ return __unorddf2 (a, c);
+}
+
#include "config/soft-fp/soft-fp.h"
#include "config/soft-fp/double.h"
#include "config/soft-fp/quad.h"
Index: config/rs6000/rs6000.c
===================================================================
--- config/rs6000/rs6000.c (revision 124330)
+++ config/rs6000/rs6000.c (working copy)
@@ -9587,7 +9587,6 @@
set_optab_libfunc (ge_optab, TFmode, "__gcc_qge");
set_optab_libfunc (lt_optab, TFmode, "__gcc_qlt");
set_optab_libfunc (le_optab, TFmode, "__gcc_qle");
- set_optab_libfunc (unord_optab, TFmode, "__gcc_qunord");
set_conv_libfunc (sext_optab, TFmode, SFmode, "__gcc_stoq");
set_conv_libfunc (sext_optab, TFmode, DFmode, "__gcc_dtoq");
@@ -9598,6 +9597,9 @@
set_conv_libfunc (sfloat_optab, TFmode, SImode, "__gcc_itoq");
set_conv_libfunc (ufloat_optab, TFmode, SImode, "__gcc_utoq");
}
+
+ if (!(TARGET_HARD_FLOAT && TARGET_FPRS))
+ set_optab_libfunc (unord_optab, TFmode, "__gcc_qunord");
}
else
{
Index: config/rs6000/libgcc-ppc-glibc.ver
===================================================================
--- config/rs6000/libgcc-ppc-glibc.ver (revision 124330)
+++ config/rs6000/libgcc-ppc-glibc.ver (working copy)
@@ -39,7 +39,6 @@
__gcc_qge
__gcc_qlt
__gcc_qle
- __gcc_qunord
__gcc_stoq
__gcc_dtoq
__gcc_qtos
@@ -49,4 +48,8 @@
__gcc_itoq
__gcc_utoq
%endif
+
+%ifdef __NO_FPRS__
+ __gcc_qunord
+%endif
}
Index: config/rs6000/rs6000.md
===================================================================
--- config/rs6000/rs6000.md (revision 124330)
+++ config/rs6000/rs6000.md (working copy)
@@ -11530,27 +11530,27 @@
(define_expand "buneq"
[(use (match_operand 0 "" ""))]
- ""
+ "! (TARGET_HARD_FLOAT && !TARGET_FPRS)"
"{ rs6000_emit_cbranch (UNEQ, operands[0]); DONE; }")
(define_expand "bunge"
[(use (match_operand 0 "" ""))]
- ""
+ "! (TARGET_HARD_FLOAT && !TARGET_FPRS)"
"{ rs6000_emit_cbranch (UNGE, operands[0]); DONE; }")
(define_expand "bungt"
[(use (match_operand 0 "" ""))]
- ""
+ "! (TARGET_HARD_FLOAT && !TARGET_FPRS)"
"{ rs6000_emit_cbranch (UNGT, operands[0]); DONE; }")
(define_expand "bunle"
[(use (match_operand 0 "" ""))]
- ""
+ "! (TARGET_HARD_FLOAT && !TARGET_FPRS)"
"{ rs6000_emit_cbranch (UNLE, operands[0]); DONE; }")
(define_expand "bunlt"
[(use (match_operand 0 "" ""))]
- ""
+ "! (TARGET_HARD_FLOAT && !TARGET_FPRS)"
"{ rs6000_emit_cbranch (UNLT, operands[0]); DONE; }")
(define_expand "bltgt"
@@ -11664,27 +11664,27 @@
(define_expand "suneq"
[(clobber (match_operand:SI 0 "gpc_reg_operand" ""))]
- ""
+ "! (TARGET_HARD_FLOAT && !TARGET_FPRS)"
"{ rs6000_emit_sCOND (UNEQ, operands[0]); DONE; }")
(define_expand "sunge"
[(clobber (match_operand:SI 0 "gpc_reg_operand" ""))]
- ""
+ "! (TARGET_HARD_FLOAT && !TARGET_FPRS)"
"{ rs6000_emit_sCOND (UNGE, operands[0]); DONE; }")
(define_expand "sungt"
[(clobber (match_operand:SI 0 "gpc_reg_operand" ""))]
- ""
+ "! (TARGET_HARD_FLOAT && !TARGET_FPRS)"
"{ rs6000_emit_sCOND (UNGT, operands[0]); DONE; }")
(define_expand "sunle"
[(clobber (match_operand:SI 0 "gpc_reg_operand" ""))]
- ""
+ "! (TARGET_HARD_FLOAT && !TARGET_FPRS)"
"{ rs6000_emit_sCOND (UNLE, operands[0]); DONE; }")
(define_expand "sunlt"
[(clobber (match_operand:SI 0 "gpc_reg_operand" ""))]
- ""
+ "! (TARGET_HARD_FLOAT && !TARGET_FPRS)"
"{ rs6000_emit_sCOND (UNLT, operands[0]); DONE; }")
(define_expand "sltgt"
--
Joseph S. Myers
joseph@codesourcery.com