diff options
author | Michael Meissner <meissner@linux.vnet.ibm.com> | 2015-12-29 17:15:14 +0000 |
---|---|---|
committer | Michael Meissner <meissner@gcc.gnu.org> | 2015-12-29 17:15:14 +0000 |
commit | ec21a884b30c42083cb79da52db5257acb12fc5d (patch) | |
tree | 5ceb4a02404f0471ca1c43bbca8a105917573652 /gcc | |
parent | 1c645536272780edf11eacc98bf2fa014f8c1489 (diff) | |
download | gcc-ec21a884b30c42083cb79da52db5257acb12fc5d.zip gcc-ec21a884b30c42083cb79da52db5257acb12fc5d.tar.gz gcc-ec21a884b30c42083cb79da52db5257acb12fc5d.tar.bz2 |
rs6000.c (init_float128_ieee): Remove IEEE 128-bit comparison functions in cmp_optab and ucmp_optab.
2015-12-29 Michael Meissner <meissner@linux.vnet.ibm.com>
* config/rs6000/rs6000.c (init_float128_ieee): Remove IEEE 128-bit
comparison functions in cmp_optab and ucmp_optab.
(rs6000_generate_compare): Rewrite IEEE 128-bit floating point
software emulation comparisons to only use __eqkf2, __gekf2,
__lekf2, and __unordkf2 functions.
(rs6000_invalid_binary_op): Add support for -mfloat128-convert.
* config/rs6000/rs6000-c.c (rs6000_cpu_cpp_builtins): Define
__FLOAT128_HARDWARE__ if hardware IEEE 128-bit support is
available.
* config/rs6000/rs6000.opt (-mfloat128-convert): Add debug switch
to allow IBM extended double and IEEE 128-bit floating point to be
converted with default conversions.
* config/rs6000/rs6000.md (extendkftf2): Add converters between
KFmode and TFmode if -mabi=ieeelongdouble.
(trunctfkf2): Likewise.
(ieee128_mfvsrd): Split 64-bit integer conversions into 32-bit and
64-bit insns.
(ieee128_mfvsrd_64bit): Likewise.
(ieee128_mfvsrd_32bit): Likewise.
(ieee128_mtvsrd): Likewise.
(ieee128_mtvsrd_64bit): Likewise.
(ieee128_mtvsrd_32bit): Likewise.
* doc/extend.texi (Floating Types): Document that complex
__float128 does not work currently.
* doc/invoke.texi (RS/6000 and PowerPC Options): Document that
-mfloat128 is only supported on PowerPC 64-bit Linux systems.
From-SVN: r231996
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 34 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000-c.c | 2 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000.c | 142 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000.md | 61 | ||||
-rw-r--r-- | gcc/config/rs6000/rs6000.opt | 4 | ||||
-rw-r--r-- | gcc/doc/extend.texi | 20 | ||||
-rw-r--r-- | gcc/doc/invoke.texi | 3 |
7 files changed, 168 insertions, 98 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 5f7e000..1643888 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,37 @@ +2015-12-29 Michael Meissner <meissner@linux.vnet.ibm.com> + + * config/rs6000/rs6000.c (init_float128_ieee): Remove IEEE 128-bit + comparison functions in cmp_optab and ucmp_optab. + (rs6000_generate_compare): Rewrite IEEE 128-bit floating point + software emulation comparisons to only use __eqkf2, __gekf2, + __lekf2, and __unordkf2 functions. + (rs6000_invalid_binary_op): Add support for -mfloat128-convert. + + * config/rs6000/rs6000-c.c (rs6000_cpu_cpp_builtins): Define + __FLOAT128_HARDWARE__ if hardware IEEE 128-bit support is + available. + + * config/rs6000/rs6000.opt (-mfloat128-convert): Add debug switch + to allow IBM extended double and IEEE 128-bit floating point to be + converted with default conversions. + + * config/rs6000/rs6000.md (extendkftf2): Add converters between + KFmode and TFmode if -mabi=ieeelongdouble. + (trunctfkf2): Likewise. + (ieee128_mfvsrd): Split 64-bit integer conversions into 32-bit and + 64-bit insns. + (ieee128_mfvsrd_64bit): Likewise. + (ieee128_mfvsrd_32bit): Likewise. + (ieee128_mtvsrd): Likewise. + (ieee128_mtvsrd_64bit): Likewise. + (ieee128_mtvsrd_32bit): Likewise. + + * doc/extend.texi (Floating Types): Document that complex + __float128 does not work currently. + + * doc/invoke.texi (RS/6000 and PowerPC Options): Document that + -mfloat128 is only supported on PowerPC 64-bit Linux systems. + 2015-12-28 Bill Schmidt <wschmidt@linux.vnet.ibm.com> * config/rs6000/rs6000.c (rs6000_emit_le_vsx_move): Verify that diff --git a/gcc/config/rs6000/rs6000-c.c b/gcc/config/rs6000/rs6000-c.c index a1b4fd4..85b4b3c 100644 --- a/gcc/config/rs6000/rs6000-c.c +++ b/gcc/config/rs6000/rs6000-c.c @@ -412,6 +412,8 @@ rs6000_cpu_cpp_builtins (cpp_reader *pfile) builtin_define ("__RSQRTEF__"); if (TARGET_FLOAT128) builtin_define ("__FLOAT128__"); + if (TARGET_FLOAT128_HW) + builtin_define ("__FLOAT128_HARDWARE__"); if (TARGET_EXTRA_BUILTINS && cpp_get_options (pfile)->lang != CLK_ASM) { diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index a97e47a..a71d0b6 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -16501,8 +16501,6 @@ init_float128_ieee (machine_mode mode) set_optab_libfunc (lt_optab, mode, "__ltkf2"); set_optab_libfunc (le_optab, mode, "__lekf2"); set_optab_libfunc (unord_optab, mode, "__unordkf2"); - set_optab_libfunc (cmp_optab, mode, "__cmpokf2"); /* fcmpo */ - set_optab_libfunc (ucmp_optab, mode, "__cmpukf2"); /* fcmpu */ set_conv_libfunc (sext_optab, mode, SFmode, "__extendsfkf2"); set_conv_libfunc (sext_optab, mode, DFmode, "__extenddfkf2"); @@ -20297,7 +20295,9 @@ rs6000_generate_compare (rtx cmp, machine_mode mode) rtx op0 = XEXP (cmp, 0); rtx op1 = XEXP (cmp, 1); - if (FLOAT_MODE_P (mode)) + if (!TARGET_FLOAT128_HW && FLOAT128_VECTOR_P (mode)) + comp_mode = CCmode; + else if (FLOAT_MODE_P (mode)) comp_mode = CCFPmode; else if (code == GTU || code == LTU || code == GEU || code == LEU) @@ -20503,106 +20503,77 @@ rs6000_generate_compare (rtx cmp, machine_mode mode) emit_insn (cmp); } - /* IEEE 128-bit support in VSX registers. If we do not have IEEE 128-bit - hardware, the comparison functions (__cmpokf2 and __cmpukf2) returns 0..15 - that is laid out the same way as the PowerPC CR register would for a - normal floating point comparison from the fcmpo and fcmpu - instructions. */ - else if (!TARGET_FLOAT128_HW && FLOAT128_IEEE_P (mode)) + /* IEEE 128-bit support in VSX registers when we do not have hardware + support. */ + else if (!TARGET_FLOAT128_HW && FLOAT128_VECTOR_P (mode)) { - rtx and_reg = gen_reg_rtx (SImode); + rtx libfunc = NULL_RTX; + bool uneq_or_ltgt = false; rtx dest = gen_reg_rtx (SImode); - rtx libfunc = optab_libfunc (ucmp_optab, mode); - HOST_WIDE_INT mask_value = 0; - - /* Values that __cmpokf2/__cmpukf2 returns. */ -#define PPC_CMP_UNORDERED 0x1 /* isnan (a) || isnan (b). */ -#define PPC_CMP_EQUAL 0x2 /* a == b. */ -#define PPC_CMP_GREATER_THEN 0x4 /* a > b. */ -#define PPC_CMP_LESS_THEN 0x8 /* a < b. */ switch (code) { case EQ: - mask_value = PPC_CMP_EQUAL; - code = NE; - break; - case NE: - mask_value = PPC_CMP_EQUAL; - code = EQ; + libfunc = optab_libfunc (eq_optab, mode); break; case GT: - mask_value = PPC_CMP_GREATER_THEN; - code = NE; - break; - case GE: - mask_value = PPC_CMP_GREATER_THEN | PPC_CMP_EQUAL; - code = NE; + libfunc = optab_libfunc (ge_optab, mode); break; case LT: - mask_value = PPC_CMP_LESS_THEN; - code = NE; - break; - case LE: - mask_value = PPC_CMP_LESS_THEN | PPC_CMP_EQUAL; - code = NE; - break; - - case UNLE: - mask_value = PPC_CMP_GREATER_THEN; - code = EQ; + libfunc = optab_libfunc (le_optab, mode); break; - case UNLT: - mask_value = PPC_CMP_GREATER_THEN | PPC_CMP_EQUAL; - code = EQ; + case UNORDERED: + case ORDERED: + libfunc = optab_libfunc (unord_optab, mode); + code = (code == UNORDERED) ? NE : EQ; break; case UNGE: - mask_value = PPC_CMP_LESS_THEN; - code = EQ; + case UNGT: + libfunc = optab_libfunc (le_optab, mode); + code = (code == UNGE) ? GE : GT; break; - case UNGT: - mask_value = PPC_CMP_LESS_THEN | PPC_CMP_EQUAL; - code = EQ; + case UNLE: + case UNLT: + libfunc = optab_libfunc (ge_optab, mode); + code = (code == UNLE) ? LE : LT; break; case UNEQ: - mask_value = PPC_CMP_EQUAL | PPC_CMP_UNORDERED; - code = NE; - case LTGT: - mask_value = PPC_CMP_EQUAL | PPC_CMP_UNORDERED; - code = EQ; - break; - - case UNORDERED: - mask_value = PPC_CMP_UNORDERED; - code = NE; - break; - - case ORDERED: - mask_value = PPC_CMP_UNORDERED; - code = EQ; + libfunc = optab_libfunc (le_optab, mode); + uneq_or_ltgt = true; + code = (code = UNEQ) ? NE : EQ; break; default: gcc_unreachable (); } - gcc_assert (mask_value != 0); - and_reg = emit_library_call_value (libfunc, and_reg, LCT_CONST, SImode, 2, - op0, mode, op1, mode); + gcc_assert (libfunc); + dest = emit_library_call_value (libfunc, NULL_RTX, LCT_CONST, + SImode, 2, op0, mode, op1, mode); - emit_insn (gen_andsi3 (dest, and_reg, GEN_INT (mask_value))); - compare_result = gen_reg_rtx (CCmode); - comp_mode = CCmode; + /* If this is UNEQ or LTGT, we call __lekf2, which returns -1 for less + than, 0 for equal, +1 for greater, and +2 for nan. We add 1, to give + a value of 0..3, and then do and AND immediate of 1 to isolate whether + it is 0/Nan (i.e. bottom bit is 0), or less than/greater than + (i.e. bottom bit is 1). */ + if (uneq_or_ltgt) + { + rtx add_result = gen_reg_rtx (SImode); + rtx and_result = gen_reg_rtx (SImode); + emit_insn (gen_addsi3 (add_result, dest, GEN_INT (1))); + emit_insn (gen_andsi3 (and_result, add_result, GEN_INT (1))); + dest = and_result; + } emit_insn (gen_rtx_SET (compare_result, gen_rtx_COMPARE (comp_mode, dest, const0_rtx))); @@ -20706,24 +20677,29 @@ rs6000_invalid_binary_op (int op ATTRIBUTE_UNUSED, mode2 = GET_MODE_INNER (mode2); /* Don't allow IEEE 754R 128-bit binary floating point and IBM extended - double to intermix. */ + double to intermix unless -mfloat128-convert. */ if (mode1 == mode2) return NULL; - if ((mode1 == KFmode && mode2 == IFmode) - || (mode1 == IFmode && mode2 == KFmode)) - return N_("__float128 and __ibm128 cannot be used in the same expression"); + if (!TARGET_FLOAT128_CVT) + { + if ((mode1 == KFmode && mode2 == IFmode) + || (mode1 == IFmode && mode2 == KFmode)) + return N_("__float128 and __ibm128 cannot be used in the same " + "expression"); - if (TARGET_IEEEQUAD - && ((mode1 == IFmode && mode2 == TFmode) - || (mode1 == TFmode && mode2 == IFmode))) - return N_("__ibm128 and long double cannot be used in the same expression"); + if (TARGET_IEEEQUAD + && ((mode1 == IFmode && mode2 == TFmode) + || (mode1 == TFmode && mode2 == IFmode))) + return N_("__ibm128 and long double cannot be used in the same " + "expression"); - if (!TARGET_IEEEQUAD - && ((mode1 == KFmode && mode2 == TFmode) - || (mode1 == TFmode && mode2 == KFmode))) - return N_("__float128 and long double cannot be used in the same " - "expression"); + if (!TARGET_IEEEQUAD + && ((mode1 == KFmode && mode2 == TFmode) + || (mode1 == TFmode && mode2 == KFmode))) + return N_("__float128 and long double cannot be used in the same " + "expression"); + } return NULL; } diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index 35685a9..0b035ca 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -13352,6 +13352,40 @@ "xscvdpqp %0,%1" [(set_attr "type" "vecfloat")]) +;; Conversion between KFmode and TFmode if TFmode is ieee 128-bit floating +;; point is a simple copy. +(define_insn_and_split "extendkftf2" + [(set (match_operand:TF 0 "vsx_register_operand" "=wa,?wa") + (float_extend:TF (match_operand:KF 1 "vsx_register_operand" "0,wa")))] + "TARGET_FLOAT128 && TARGET_IEEEQUAD" + "@ + # + xxlor %x0,%x1,%x1" + "&& reload_completed && REGNO (operands[0]) == REGNO (operands[1])" + [(const_int 0)] +{ + emit_note (NOTE_INSN_DELETED); + DONE; +} + [(set_attr "type" "*,vecsimple") + (set_attr "length" "0,4")]) + +(define_insn_and_split "trunctfkf2" + [(set (match_operand:KF 0 "vsx_register_operand" "=wa,?wa") + (float_extend:KF (match_operand:TF 1 "vsx_register_operand" "0,wa")))] + "TARGET_FLOAT128 && TARGET_IEEEQUAD" + "@ + # + xxlor %x0,%x1,%x1" + "&& reload_completed && REGNO (operands[0]) == REGNO (operands[1])" + [(const_int 0)] +{ + emit_note (NOTE_INSN_DELETED); + DONE; +} + [(set_attr "type" "*,vecsimple") + (set_attr "length" "0,4")]) + (define_insn "trunc<mode>df2_hw" [(set (match_operand:DF 0 "altivec_register_operand" "=v") (float_truncate:DF @@ -13476,7 +13510,7 @@ "xscv<su>dqp %0,%1" [(set_attr "type" "vecfloat")]) -(define_insn "*ieee128_mfvsrd" +(define_insn "*ieee128_mfvsrd_64bit" [(set (match_operand:DI 0 "reg_or_indexed_operand" "=wr,Z,wi") (unspec:DI [(match_operand:V2DI 1 "altivec_register_operand" "v,v,v")] UNSPEC_IEEE128_MOVE))] @@ -13487,6 +13521,17 @@ xxlor %x0,%x1,%x1" [(set_attr "type" "mftgpr,vecsimple,fpstore")]) + +(define_insn "*ieee128_mfvsrd_32bit" + [(set (match_operand:DI 0 "reg_or_indexed_operand" "=Z,wi") + (unspec:DI [(match_operand:V2DI 1 "altivec_register_operand" "v,v")] + UNSPEC_IEEE128_MOVE))] + "TARGET_FLOAT128_HW && !TARGET_POWERPC64" + "@ + stxsdx %x1,%y0 + xxlor %x0,%x1,%x1" + [(set_attr "type" "vecsimple,fpstore")]) + (define_insn "*ieee128_mfvsrwz" [(set (match_operand:SI 0 "reg_or_indexed_operand" "=r,Z") (unspec:SI [(match_operand:V2DI 1 "altivec_register_operand" "v,v")] @@ -13512,17 +13557,27 @@ [(set_attr "type" "mffgpr,fpload,mffgpr,fpload")]) -(define_insn "*ieee128_mtvsrd" +(define_insn "*ieee128_mtvsrd_64bit" [(set (match_operand:V2DI 0 "altivec_register_operand" "=v,v,v") (unspec:V2DI [(match_operand:DI 1 "nonimmediate_operand" "wr,Z,wi")] UNSPEC_IEEE128_MOVE))] - "TARGET_FLOAT128_HW" + "TARGET_FLOAT128_HW && TARGET_POWERPC64" "@ mtvsrd %x0,%1 lxsdx %x0,%y1 xxlor %x0,%x1,%x1" [(set_attr "type" "mffgpr,fpload,vecsimple")]) +(define_insn "*ieee128_mtvsrd_32bit" + [(set (match_operand:V2DI 0 "altivec_register_operand" "=v,v") + (unspec:V2DI [(match_operand:DI 1 "nonimmediate_operand" "Z,wi")] + UNSPEC_IEEE128_MOVE))] + "TARGET_FLOAT128_HW && !TARGET_POWERPC64" + "@ + lxsdx %x0,%y1 + xxlor %x0,%x1,%x1" + [(set_attr "type" "fpload,vecsimple")]) + ;; IEEE 128-bit instructions with round to odd semantics (define_insn "*trunc<mode>df2_odd" [(set (match_operand:DF 0 "vsx_register_operand" "=v") diff --git a/gcc/config/rs6000/rs6000.opt b/gcc/config/rs6000/rs6000.opt index 61e3c8a..8064f23 100644 --- a/gcc/config/rs6000/rs6000.opt +++ b/gcc/config/rs6000/rs6000.opt @@ -632,3 +632,7 @@ Enable/disable IEEE 128-bit floating point via the __float128 keyword. mfloat128-hardware Target Report Mask(FLOAT128_HW) Var(rs6000_isa_flags) Enable/disable using IEEE 128-bit floating point instructions. + +mfloat128-convert +Target Undocumented Mask(FLOAT128_CVT) Var(rs6000_isa_flags) +Enable/disable default conversions between __float128 & long double. diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index 4578925..65b6a96 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -954,22 +954,20 @@ typedef _Complex float __attribute__((mode(TC))) _Complex128; typedef _Complex float __attribute__((mode(XC))) _Complex80; @end smallexample -On PowerPC Linux, Freebsd and Darwin systems, the default for -@code{long double} is to use the IBM extended floating point format -that uses a pair of @code{double} values to extend the precision. -This means that the mode @code{TCmode} was already used by the -traditional IBM long double format, and you would need to use the mode -@code{KCmode}: +On PowerPC 64-bit Linux systems there are currently problems in using +the complex @code{__float128} type. When these problems are fixed, +you would use: @smallexample typedef _Complex float __attribute__((mode(KC))) _Complex128; @end smallexample -Not all targets support additional floating-point types. @code{__float80} -and @code{__float128} types are supported on x86 and IA-64 targets. -The @code{__float128} type is supported on hppa HP-UX. -The @code{__float128} type is supported on PowerPC systems by default -if the vector scalar instruction set (VSX) is enabled. +Not all targets support additional floating-point types. +@code{__float80} and @code{__float128} types are supported on x86 and +IA-64 targets. The @code{__float128} type is supported on hppa HP-UX. +The @code{__float128} type is supported on PowerPC 64-bit Linux +systems by default if the vector scalar instruction set (VSX) is +enabled. On the PowerPC, @code{__ibm128} provides access to the IBM extended double format, and it is intended to be used by the library functions diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 4e2cf8f..b85f9b5 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -19690,7 +19690,8 @@ hardware instructions. The VSX instruction set (@option{-mvsx}, @option{-mcpu=power7}, or @option{-mcpu=power8}) must be enabled to use the @option{-mfloat128} -option. +option. The @code{-mfloat128} option only works on PowerPC 64-bit +Linux systems. @item -mfloat128-hardware @itemx -mno-float128-hardware |