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
This commit is contained in:
parent
1c64553627
commit
ec21a884b3
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
break;
|
||||
|
||||
case UNLT:
|
||||
mask_value = PPC_CMP_GREATER_THEN | PPC_CMP_EQUAL;
|
||||
code = EQ;
|
||||
break;
|
||||
|
||||
case UNGE:
|
||||
mask_value = PPC_CMP_LESS_THEN;
|
||||
code = EQ;
|
||||
break;
|
||||
|
||||
case UNGT:
|
||||
mask_value = PPC_CMP_LESS_THEN | PPC_CMP_EQUAL;
|
||||
code = EQ;
|
||||
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;
|
||||
libfunc = optab_libfunc (le_optab, mode);
|
||||
break;
|
||||
|
||||
case UNORDERED:
|
||||
mask_value = PPC_CMP_UNORDERED;
|
||||
code = NE;
|
||||
case ORDERED:
|
||||
libfunc = optab_libfunc (unord_optab, mode);
|
||||
code = (code == UNORDERED) ? NE : EQ;
|
||||
break;
|
||||
|
||||
case ORDERED:
|
||||
mask_value = PPC_CMP_UNORDERED;
|
||||
code = EQ;
|
||||
case UNGE:
|
||||
case UNGT:
|
||||
libfunc = optab_libfunc (le_optab, mode);
|
||||
code = (code == UNGE) ? GE : GT;
|
||||
break;
|
||||
|
||||
case UNLE:
|
||||
case UNLT:
|
||||
libfunc = optab_libfunc (ge_optab, mode);
|
||||
code = (code == UNLE) ? LE : LT;
|
||||
break;
|
||||
|
||||
case UNEQ:
|
||||
case LTGT:
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue