Re: [PATCH] Teach VRP about __builtin_{ffs,parity,popcount,clz,ctz,clrsb}{,l,ll,imax} (PR target/29776)
Jakub Jelinek wrote: >Hi! > >Attached are two versions of a patch to teach VRP about the int bitop >builtins. Both patches are identical for all builtins but >__builtin_c[lt]z*, which are the only two from these that are >documented >to have undefined behavior on some argument (0). > >The first version is strict, it assumes __builtin_c[lt]z* (0) doesn't >happen >in valid programs, while the second one attempts to be less strict to >avoid >breaking stuff too much. > >The reason for writing the second patch is that longlong.h on various >targets has stuff like: >#ifdef __alpha_cix__ >#define count_leading_zeros(COUNT,X)((COUNT) = __builtin_clzl (X)) >#define count_trailing_zeros(COUNT,X) ((COUNT) = __builtin_ctzl (X)) >#define COUNT_LEADING_ZEROS_0 64 >#else >and documents that if COUNT_LEADING_ZEROS_0 is defined, then >count_leading_zeros (cnt, 0) should be well defined and set >cnt to COUNT_LEADING_ZEROS_0. While neither gcc nor glibc use >COUNT_LEADING_ZEROS_0 macro, I'm a little bit afraid some code in the >wild >might do, and it might even have its own copy of longlong.h, so even if >we've removed those COUNT_LEADING_ZEROS_0 macros for targets that >use the builtins, something could stay broken. So, what the patch does >is if an optab exists for the mode of the builtin's argument and >C?Z_DEFINED_VALUE_AT_ZERO is defined, then it will add that value to >the >range unless VR of argument is non-zero (well, it handles only a few >interesting commonly used values, for CLZ only precision of the mode >(seems right now when CLZ_DEFINED_VALUE_AT_ZERO is non-zero, it sets >it always to bitsize of the mode, and even widening or double word >narrowing expansion should maintain this property), for CTZ -1 and >bitsize). If there isn't an optab for it, for CLZ it still assumes >it might be bitsize, for CTZ it just assumes it is undefined behavior >otherwise, because if I understand the code right, for CTZ we really >could >return various values for 0 without hw support for the mode, e.g. when >CTZ is implemented using CLZ, it might return something, if we use >wider >mode hw CTZ and it would return bitsize, that would be bitsize of the >wider >mode etc. I bet longlong.h only uses __builtin_c?z builtins for modes >actually implemented in hw anyway (otherwise it couldn't be used safely >in >libgcc implementation of those libcalls). > >Both patches have been bootstrapped/regtested on x86_64-linux and >i686-linux, which one do you prefer? The less strict variant. Thanks Richard. > Jakub
[PATCH, i386]: Fix PR57807, -masm=intel pointer size fixes
Hello! While ATT dialect doesn't care about pointer sizes, Intel dialect requires correct pointer size decorations. Attached patch introduces correct pointer size overrides, and fixes all instructions, so gcc.target/i386/sse-13.c mega-testcase compiles without problems with -masm=intel. Unfortunately, this also uncovers gas bug [1] with cvttps2pi. [1] http://sourceware.org/bugzilla/show_bug.cgi?id=13572 2013-07-06 Uros Bizjak PR target/57807 * config/i386/sse.md (iptr): New mode attribute. (sse2_movq128): Add pointer size overrides for Intel asm dialect. (_vm3): Ditto. (_vmmul3): Ditto. (_vmdiv3): Ditto. (sse_vmrcpv4sf2): Ditto. (_vmsqrt2): Ditto. (sse_vmrsqrtv4sf2): Ditto. (_vm3): Ditto. (avx_vmcmp3): Ditto. (_vmmaskcmp3): Ditto. (_comi): Ditto. (_ucomi): Ditto. (*xop_vmfrcz_): Ditto. (*fmai_fmadd_): Ditto. (*fmai_fmsub_): Ditto. (*fmai_fnmadd_): Ditto. (*fmai_fnmsub_): Ditto. (*fma4i_vmfmadd_): Ditto. (*fma4i_vmfmsub_): Ditto. (*fma4i_vmfnmadd_): Ditto. (*fma4i_vmfnmsub_): Ditto. (*xop_vmfrcz_): Ditto. (sse_cvtps2pi): Ditto. (sse_cvttps2pi): Ditto. (sse_cvtss2si): Ditto. (sse_cvtss2si_2): Ditto. (sse_cvtss2siq_2): Ditto. (sse_cvttss2si): Ditto. (sse_cvttss2siq): Ditto. (sse_cvtsd2si): Ditto. (sse_cvtsd2si_2): Ditto. (sse_cvtsd2siq_2): Ditto. (sse_cvttsd2si): Ditto. (sse_cvttsd2siq): Ditto. (sse_cvtsd2ss): Ditto. (sse_cvtss2sd): Ditto. (avx2_pbroadcast): Ditto. (avx2_pbroadcast_1): Ditto. (*avx_vperm_broadcast_v4sf): Ditto. (sse_movhlps): Ditto for movlp[sd]/movhp[sd] alternatives. (sse_movlhps): Ditto. (sse_storehps): Ditto. (sse_loadhps): Ditto. (sse_storelps): Ditto. (sse_loadlps): Ditto. (*vec_concatv4sf): Ditto. (*vec_interleave_highv2df): Ditto. (*vec_interleave_lowv2df): Ditto. (*vec_extractv2df_1_sse): Ditto. (*vec_extractv2df_0_sse): Ditto. (sse2_storelpd): Ditto. (sse2_loadlpd): Ditto. (sse2_movsd): Ditto. (*vec_concatv4si): Ditto. (vec_concatv2di): Ditto. * config/i386/mmx.md (mmx_punpcklbw): Add pointer size overrides for Intel asm dialect. (mmx_punpcklwd): Ditto. (mmx_punpckldq): Ditto. * config/i386/i386.c (ix86_print_operand) ['H']: Output 'qword ptr' for intel assembler dialect. testsuite/ChangeLog: 2013-07-06 Uros Bizjak PR target/57807 * gcc.target/i386/pr57807.c: New test. Patch was bootstrapped and regression tested on x86_64-pc-linux-gnu {,-m32}. Patch was committed to mainline SVN, but due to its size, I think it is not appropriate for release branches. Index: config/i386/i386.c === --- config/i386/i386.c (revision 200728) +++ config/i386/i386.c (working copy) @@ -14670,6 +14670,9 @@ ix86_print_operand (FILE *file, rtx x, int code) /* It doesn't actually matter what mode we use here, as we're only going to use this for printing. */ x = adjust_address_nv (x, DImode, 8); + /* Output 'qword ptr' for intel assembler dialect. */ + if (ASSEMBLER_DIALECT == ASM_INTEL) + code = 'q'; break; case 'K': Index: config/i386/mmx.md === --- config/i386/mmx.md (revision 200728) +++ config/i386/mmx.md (working copy) @@ -1078,7 +1078,7 @@ (const_int 2) (const_int 10) (const_int 3) (const_int 11)])))] "TARGET_MMX" - "punpcklbw\t{%2, %0|%0, %2}" + "punpcklbw\t{%2, %0|%0, %k2}" [(set_attr "type" "mmxcvt") (set_attr "mode" "DI")]) @@ -1104,7 +1104,7 @@ (parallel [(const_int 0) (const_int 4) (const_int 1) (const_int 5)])))] "TARGET_MMX" - "punpcklwd\t{%2, %0|%0, %2}" + "punpcklwd\t{%2, %0|%0, %k2}" [(set_attr "type" "mmxcvt") (set_attr "mode" "DI")]) @@ -1130,7 +1130,7 @@ (parallel [(const_int 0) (const_int 2)])))] "TARGET_MMX" - "punpckldq\t{%2, %0|%0, %2}" + "punpckldq\t{%2, %0|%0, %k2}" [(set_attr "type" "mmxcvt") (set_attr "mode" "DI")]) Index: config/i386/sse.md === --- config/i386/sse.md (revision 200728) +++ config/i386/sse.md (working copy) @@ -355,6 +355,14 @@ (V8SF "SF") (V4DF "DF") (V4SF "SF") (V2DF "DF")]) +;; Pointer size override for scalar modes (Intel asm dialect) +(define_mode_attr iptr + [(V32QI "b") (V16HI "w") (V8SI "k") (V4DI "q") + (V16QI "b") (V8HI "w") (V4SI "k") (V2DI "q") + (V8SF "k") (V4DF "q") + (V4SF "k") (V2DF "q") + (SF "k") (DF "q")]) + ;; Number of scalar elements in each vector type (define_mode_attr ssescalarnum [(V32QI "32") (V16HI "16") (V8SI "8") (V4DI "4") @@ -511,7 +519,7 @@ (parallel [(const_int 0)])) (const_int 0)))] "TARGET
Fix Bug 51776 (finally...)
Index: ChangeLog === --- ChangeLog (revision 200737) +++ ChangeLog (working copy) @@ -1,3 +1,7 @@ +2013-07-06 Bruce Korb + + * inclhack.def (cdef_cplusplus): removed, per Bug 51776 + 2013-05-23 Alexander Ivchenko * inclhack.def (complier_h_tradcpp): New. Index: fixincl.x === --- fixincl.x (revision 200737) +++ fixincl.x (working copy) @@ -1,12 +1,12 @@ /* -*- buffer-read-only: t -*- vi: set ro: - * + * * DO NOT EDIT THIS FILE (fixincl.x) - * - * It has been AutoGen-ed May 23, 2013 at 04:44:10 PM by AutoGen 5.12 + * + * It has been AutoGen-ed July 6, 2013 at 10:40:53 AM by AutoGen 5.17.5pre10 * From the definitionsinclhack.def * and the template file fixincl */ -/* DO NOT SVN-MERGE THIS FILE, EITHER Thu May 23 16:44:10 MSK 2013 +/* DO NOT SVN-MERGE THIS FILE, EITHER Sat Jul 6 10:40:53 PDT 2013 * * You must regenerate it. Use the ./genfixes script. * @@ -15,7 +15,7 @@ * certain ANSI-incompatible system header files which are fixed to work * correctly with ANSI C and placed in a directory that GNU C will search. * - * This file contains 228 fixup descriptions. + * This file contains 227 fixup descriptions. * * See README for more information. * @@ -2072,41 +2072,6 @@ /* * * * * * * * * * * * * * * * * * * * * * * * * * * - * Description of Cdef_Cplusplus fix - */ -tSCC zCdef_CplusplusName[] = - "cdef_cplusplus"; - -/* - * File name selection pattern - */ -tSCC zCdef_CplusplusList[] = - "sys/cdefs.h\0"; -/* - * Machine/OS name selection pattern - */ -#define apzCdef_CplusplusMachs (const char**)NULL - -/* - * content selection pattern - do fix if pattern found - */ -tSCC zCdef_CplusplusSelect0[] = - "\\[\\[noreturn\\]\\]"; - -#defineCDEF_CPLUSPLUS_TEST_CT 1 -static tTestDesc aCdef_CplusplusTests[] = { - { TT_EGREP,zCdef_CplusplusSelect0, (regex_t*)NULL }, }; - -/* - * Fix Command Arguments for Cdef_Cplusplus - */ -static const char* apzCdef_CplusplusPatch[] = { -"format", -"__attribute__((__noreturn__))", -(char*)NULL }; - -/* * * * * * * * * * * * * * * * * * * * * * * * * * - * * Description of Ctrl_Quotes_Def fix */ tSCC zCtrl_Quotes_DefName[] = @@ -9364,9 +9329,9 @@ * * List of all fixes */ -#define REGEX_COUNT 267 +#define REGEX_COUNT 266 #define MACH_LIST_SIZE_LIMIT 187 -#define FIX_COUNT228 +#define FIX_COUNT227 /* * Enumerate the fixes @@ -9418,7 +9383,6 @@ BROKEN_CABS_FIXIDX, BROKEN_NAN_FIXIDX, BSD_STDIO_ATTRS_CONFLICT_FIXIDX, -CDEF_CPLUSPLUS_FIXIDX, CTRL_QUOTES_DEF_FIXIDX, CTRL_QUOTES_USE_FIXIDX, CXX_UNREADY_FIXIDX, @@ -9833,11 +9797,6 @@ BSD_STDIO_ATTRS_CONFLICT_TEST_CT, FD_MACH_ONLY | FD_SUBROUTINE, aBsd_Stdio_Attrs_ConflictTests, apzBsd_Stdio_Attrs_ConflictPatch, 0 }, - { zCdef_CplusplusName,zCdef_CplusplusList, - apzCdef_CplusplusMachs, - CDEF_CPLUSPLUS_TEST_CT, FD_MACH_ONLY | FD_SUBROUTINE, - aCdef_CplusplusTests, apzCdef_CplusplusPatch, 0 }, - { zCtrl_Quotes_DefName,zCtrl_Quotes_DefList, apzCtrl_Quotes_DefMachs, CTRL_QUOTES_DEF_TEST_CT, FD_MACH_ONLY | FD_SUBROUTINE, Index: inclhack.def === --- inclhack.def (revision 200737) +++ inclhack.def (working copy) @@ -64,7 +64,6 @@ _EOArg_; }; - /* On AIX when _LARGE_FILES is defined fcntl.h defines open to * open64 and creat to creat64. This fixes fcntl.h to * undef those defines and use __asm__ to alias the symbols if @@ -103,7 +102,6 @@ _EOArg_; }; - /* * On Mac OS 10.3.9, the 'long double' functions are available in * libSystem, but are not prototyped in math.h. @@ -237,7 +235,6 @@ _EndOfHeader_; }; - /* * This fixes __FD_ZERO bug for glibc-1.x */ @@ -275,7 +272,6 @@ _EndOfHeader_; }; - /* * This fixes __FD_ZERO bug for glibc-2.0.x */ @@ -317,7 +313,6 @@ _EndOfHeader_; }; - /* * Solaris is a DDK (aka kernel-land) header providing * the same interface as . No idea why they couldn't have just @@ -336,7 +331,6 @@ _EndOfHeader_; }; - /* * Fix non-ANSI memcpy declaration that conflicts with gcc's builtin * declaration on Sun OS 4.x. We must only fix this on Sun OS 4.x, because @@ -574,7 +568,6 @@ _EndOfHeader_; }; - /* * complex.h on AIX 5 and AIX 6 define _Complex_I and I in terms of __I, * which only is provided by AIX xlc C99. @@ -727,7 +720,6 @@ "{...init stuff...}"; }; - /* * AIX stdint.h fixes. */ @@ -744,7 +736,9 @@ "#define UINT16_MAX (65535U)"; }; - +/* + * aix_stdint_2 + */ fix = { hackname = aix_stdint_2; mach = "*-*-aix*"; @@ -773,7 +767,9 @@ "#define UINTPTR_MAX UINT32_MAX"; }; - +/* + * aix_stdint_3 + */ fix = { hackname = aix_stdint_3; mach = "*-*-aix*"; @@
fixincludes 2013-05-23 Alexander Ivchenko
Alexander Ivchenko Mon, 29 Apr 2013 23:24:55 -0700 2013/4/29 Mike Stump : On Jan 9, 2013, at 7:14 AM, Alexander Ivchenko wrote: We have test fail for gcc.dg/cpp/trad/include.c on Android. The reason for that is that -ftraditional-cpp is not expected to work on Android due to variadic macro (like #define __builtin_warning(x, y...)) in standard headers and traditional preprocessor cannot handle them. The attached patch disables that test. Be sure to ask, Ok? in your patch submittals. Ok. thank you! I thought I did ask.. ... in standard headers and traditional preprocessor cannot handle them." is it ok for trunk? could someone commit that patch please? I don't have commit access. Actually, Alexander, you did not ask. And Kirill, you didn't verify before applying the patch. Patches to fixincludes are generally safe, but it is protocol to ask. Also, I prefer that the hacks get inserted alphabetically. So, actually, there are a few small complaints. $ fgrep -i fixincludes ../MAINTAINERS fixincludes Bruce Korb bk...@gnu.org The patch looks pretty reasonable, but I think someone else should verify the obsolescence. I also think it should be renamed to something like "obsolete_builtin_warning" because the current name gives no clue about what it really is. /* * Old Linux kernel's header breaks Traditional CPP */ fix = { hackname = complier_h_tradcpp; files = linux/compiler.h; select= "#define __builtin_warning\\(x, y\\.\\.\\.\\) \\(1\\)"; c_fix = format; c_fix_arg = "/* __builtin_warning(x, y...) is obsolete */"; test_text = "#define __builtin_warning(x, y...) (1)"; };
folding (vec_)cond_expr in a binary operation
Hello, the first attached patch does not bootstrap and has at least 2 main issues. The second patch does pass bootstrap+testsuite, but I liked the first more... First, the fold-const bit causes an assertion failure (building libjava) in combine_cond_expr_cond, which calls: t = fold_binary_loc (gimple_location (stmt), code, type, op0, op1); and then checks: /* Require that we got a boolean type out if we put one in. */ gcc_assert (TREE_CODE (TREE_TYPE (t)) == TREE_CODE (type)); which makes sense... Note that the 2 relevant types are: (gdb) call debug_tree((tree)0x75e78930) constant 8> unit size constant 1> align 8 symtab -169408800 alias set -1 canonical type 0x76635c78 precision 1 min max pointer_to_this chain > (gdb) call debug_tree(type) constant 8> unit size constant 1> align 8 symtab -170348640 alias set 19 canonical type 0x764f69d8 precision 1 min max pointer_to_this > I need to relax the conditions on the vec?-1:0 optimization because with vectors we often end up with several types that are equivalent. Can you think of a good way to do it? In the second patch I limit the transformation to vectors and hope it doesn't cause as much trouble there... Second, the way the forwprop transformation is done, it can be necessary to run the forwprop pass several times in a row, which is not nice. It takes: stmt_cond stmt_binop and produces: stmt_folded stmt_cond2 But one of the arguments of stmt_folded could be an ssa_name defined by a cond_expr, which could now be propagated into stmt_folded (there may be other new possible transformations). However, that cond_expr has already been visited and won't be again. The combine part of the pass uses a PLF to revisit statements, but the forwprop part doesn't have any specific mechanism. The workarounds I can think of are: - manually check if some of the arguments of stmt_folded are cond_expr and recursively call the function on them; - move the transformation to the combine part of the pass; - setup some system to revisit all earlier statements? I went with the second option in the second patch, but this limitation of forward propagation seems strange to me. (s/combine_binop_with_condition/forward_propagate_condition/ for the first patch) 2013-07-06 Marc Glisse PR tree-optimization/57755 gcc/ * tree-ssa-forwprop.c (combine_binop_with_condition): New function. (ssa_forward_propagate_and_combine): Call it. * fold-const.c (fold_ternary_loc): In gimple form, don't check for type equality. gcc/testsuite/ * g++.dg/tree-ssa/pr57755.C: New testcase. (this message does not supersede http://gcc.gnu.org/ml/gcc-patches/2013-06/msg01624.html ) -- Marc GlisseIndex: fold-const.c === --- fold-const.c(revision 200736) +++ fold-const.c(working copy) @@ -14124,21 +14124,23 @@ fold_ternary_loc (location_t loc, enum t /* Convert A ? 1 : 0 to simply A. */ if ((code == VEC_COND_EXPR ? integer_all_onesp (op1) : (integer_onep (op1) && !VECTOR_TYPE_P (type))) && integer_zerop (op2) /* If we try to convert OP0 to our type, the call to fold will try to move the conversion inside a COND, which will recurse. In that case, the COND_EXPR is probably the best choice, so leave it alone. */ - && type == TREE_TYPE (arg0)) + && (type == TREE_TYPE (arg0) + || (in_gimple_form + && useless_type_conversion_p (type, TREE_TYPE (arg0) return pedantic_non_lvalue_loc (loc, arg0); /* Convert A ? 0 : 1 to !A. This prefers the use of NOT_EXPR over COND_EXPR in cases such as floating point comparisons. */ if (integer_zerop (op1) && (code == VEC_COND_EXPR ? integer_all_onesp (op2) : (integer_onep (op2) && !VECTOR_TYPE_P (type))) && truth_value_p (TREE_CODE (arg0))) return pedantic_non_lvalue_loc (loc, Index: tree-ssa-forwprop.c === --- tree-ssa-forwprop.c (revision 200736) +++ tree-ssa-forwprop.c (working copy) @@ -1135,20 +1135,135 @@ forward_propagate_comparison (gimple_stm /* Remove defining statements. */ return remove_prop_source_from_use (name); bailout: gsi_next (defgsi); return false; } +/* Forward propagate the condition defined in *DEFGSI to uses in + binary operations. + Returns true if stmt is now unused. Advance DEFGSI to the next + statement. */ + +static bool +forward_propagate_condition (gimple_stmt_iterator *defgsi) +{ + gimple stmt = gsi_stmt (*defgsi); + tree name = gimple_assign_lhs (stmt); + enum tree_code defcode = gimple_assign_rhs_code (s
[PATCH] FPU IEEE 754 for MIPS r5900
Hello Richard, I used the SPU code in GCC as example for creating an r5900_single_format structure. The patch is attached to the e-mail. I want to submit this patch. > >> * removing the ISA_HAS_LDC1_SDC1 setting. I realise what you did > >> describes the reality of the processor, but the problem is that > >> the patch doesn't provide an alternative for 64-bit loads and > >> stores when -mfp64 is used. That combination also isn't rejected, > >> so we're likely to get an internal compiler error instead. > >> > >> This change shouldn't affect the soft-float case you describe. > >> It also shouldn't be important for the single-float code. I needed to patch ISA_HAS_LDC1_SDC1, because the GCC uses the instructions also for single float to store FPRs on the stack. To get around the missing alternative, I reject in the code the following combinations, because it would never work: -march=r5900 -mfp64 -mhard-float -march=r5900 -mdouble-float -mhard-float > >> FWIW, the Cygnus/Red Hat version of the port just stuck with the R5900 > >> behaviour and made GCC understand it (MODE_HAS_* & various other bits). > >> This code was then updated and extended for the SPU. I'd have expected > >> the support to be in reasonably good shape because of the SPU. > > > > I assume that you mean the cell processor of the PS3 and not the Sound > > Processing Unit of the PS2. > > :-) > > > The macros MODE_HAS_* in the GCC look promising. > > You've probably already seen it, but there's also spu_single_format. To be able to use it, you need to use mipsr5900el and "--with-float=single". "--with-float=hard" results in double float because of MIPS ISA III. I didn't changed the default in config.gcc. It is still soft float, because floating point doesn't behave as defined by IEEE 754. I don't see much improvement. This is the case on the PS2 and the PS3. For example inf minus inf should be NaN, but on both systems it is 0. I tested it on r5900 and the PS3 SPU. Both calculates the same result despite the MODE_HAS_* implementation. This means that there is a patch needed in the generic part (i.e. not mips) of the GCC. Currently I only provide a simple patch, so that the GCC knows the missing stuff, even if it is not correctly handled in the generic GCC part. I thought that Linux is running on SPU, but this is not the case, because it just a simple coprocessor. It seems that SPU is not used for complex floating point calculations in homebrew software. I am pretty sure that nearly nobody knows that floating point in GCC behaves this way on SPU. Best regards JürgenIndex: gcc/real.c === --- gcc/real.c (Revision 200583) +++ gcc/real.c (Arbeitskopie) @@ -3028,6 +3028,34 @@ true }; +/* r5900 Single precision format is the same as IEEE +single precision with the following differences: + - Infinities are not supported. Instead MAX_FLOAT or MIN_FLOAT + are generated. + - NaNs are not supported. + - Denormals are not supported. + - the only supported rounding mode is trunction (towards zero). */ +const struct real_format r5900_single_format = + { +encode_ieee_single, +decode_ieee_single, +2, +24, +24, +-125, +128, +31, +31, +true, +true, +false, +false, +false, +true, +false, +true + }; + const struct real_format motorola_single_format = { encode_ieee_single, Index: gcc/real.h === --- gcc/real.h (Revision 200583) +++ gcc/real.h (Arbeitskopie) @@ -303,6 +303,7 @@ /* Target formats defined in real.c. */ extern const struct real_format ieee_single_format; extern const struct real_format mips_single_format; +extern const struct real_format r5900_single_format; extern const struct real_format motorola_single_format; extern const struct real_format spu_single_format; extern const struct real_format ieee_double_format; Index: gcc/config.gcc === --- gcc/config.gcc (Revision 200583) +++ gcc/config.gcc (Arbeitskopie) @@ -3472,7 +3475,7 @@ supported_defaults="abi arch arch_32 arch_64 float tune tune_32 tune_64 divide llsc mips-plt synci" case ${with_float} in - "" | soft | hard) + "" | soft | hard | single | double) # OK ;; *) Index: gcc/config/mips/mips.c === --- gcc/config/mips/mips.c (Revision 200583) +++ gcc/config/mips/mips.c (Arbeitskopie) @@ -16830,6 +16830,19 @@ target_flags &= ~MASK_FLOAT64; } + if (TARGET_HARD_FLOAT_ABI && TARGET_FLOAT64 && TARGET_MIPS5900) +{ + /* FPU of r5900 only supports 32 bit. */ + error ("unsupported combination: %s", "-march=r5900 -mfp64 -mhard-float"); +} + + if (TARGET_HARD_FLOAT_ABI && TARGET_DOUBLE_FLOAT && TARGET_MIPS5900) +{ + /* FPU of r5900 only supports 32