mirror of git://gcc.gnu.org/git/gcc.git
re PR target/71869 (__builtin_isgreater raises an invalid exception on PPC64 using __float128 inputs.)
[gcc] 2016-07-26 Michael Meissner <meissner@linux.vnet.ibm.com> PR target/71869 * config/rs6000/rs6000.c (rs6000_generate_compare): Rework __float128 support when we don't have hardware support, so that the IEEE built-in functions like isgreater, first call __unordkf3 to make sure neither operand is a NaN, and if both operands are ordered, do the normal comparison. [gcc/testsuite] 2016-07-26 Michael Meissner <meissner@linux.vnet.ibm.com> PR target/71869 * gcc.target/powerpc/float128-cmp.c: New test to make sure that IEEE built-in functions handle quiet and signalling NaNs correctly. From-SVN: r238779
This commit is contained in:
parent
2f65c3b337
commit
71abba1e35
|
|
@ -1,3 +1,12 @@
|
||||||
|
2016-07-26 Michael Meissner <meissner@linux.vnet.ibm.com>
|
||||||
|
|
||||||
|
PR target/71869
|
||||||
|
* config/rs6000/rs6000.c (rs6000_generate_compare): Rework
|
||||||
|
__float128 support when we don't have hardware support, so that
|
||||||
|
the IEEE built-in functions like isgreater, first call __unordkf3
|
||||||
|
to make sure neither operand is a NaN, and if both operands are
|
||||||
|
ordered, do the normal comparison.
|
||||||
|
|
||||||
2016-07-26 Patrick Palka <ppalka@gcc.gnu.org>
|
2016-07-26 Patrick Palka <ppalka@gcc.gnu.org>
|
||||||
|
|
||||||
* tree-vrp.c (dump_asserts_for): Print loc->expr instead of
|
* tree-vrp.c (dump_asserts_for): Print loc->expr instead of
|
||||||
|
|
|
||||||
|
|
@ -21756,8 +21756,8 @@ rs6000_generate_compare (rtx cmp, machine_mode mode)
|
||||||
else if (!TARGET_FLOAT128_HW && FLOAT128_VECTOR_P (mode))
|
else if (!TARGET_FLOAT128_HW && FLOAT128_VECTOR_P (mode))
|
||||||
{
|
{
|
||||||
rtx libfunc = NULL_RTX;
|
rtx libfunc = NULL_RTX;
|
||||||
bool uneq_or_ltgt = false;
|
bool check_nan = false;
|
||||||
rtx dest = gen_reg_rtx (SImode);
|
rtx dest;
|
||||||
|
|
||||||
switch (code)
|
switch (code)
|
||||||
{
|
{
|
||||||
|
|
@ -21784,21 +21784,23 @@ rs6000_generate_compare (rtx cmp, machine_mode mode)
|
||||||
|
|
||||||
case UNGE:
|
case UNGE:
|
||||||
case UNGT:
|
case UNGT:
|
||||||
libfunc = optab_libfunc (le_optab, mode);
|
check_nan = true;
|
||||||
|
libfunc = optab_libfunc (ge_optab, mode);
|
||||||
code = (code == UNGE) ? GE : GT;
|
code = (code == UNGE) ? GE : GT;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case UNLE:
|
case UNLE:
|
||||||
case UNLT:
|
case UNLT:
|
||||||
libfunc = optab_libfunc (ge_optab, mode);
|
check_nan = true;
|
||||||
|
libfunc = optab_libfunc (le_optab, mode);
|
||||||
code = (code == UNLE) ? LE : LT;
|
code = (code == UNLE) ? LE : LT;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case UNEQ:
|
case UNEQ:
|
||||||
case LTGT:
|
case LTGT:
|
||||||
libfunc = optab_libfunc (le_optab, mode);
|
check_nan = true;
|
||||||
uneq_or_ltgt = true;
|
libfunc = optab_libfunc (eq_optab, mode);
|
||||||
code = (code = UNEQ) ? NE : EQ;
|
code = (code = UNEQ) ? EQ : NE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|
@ -21806,21 +21808,56 @@ rs6000_generate_compare (rtx cmp, machine_mode mode)
|
||||||
}
|
}
|
||||||
|
|
||||||
gcc_assert (libfunc);
|
gcc_assert (libfunc);
|
||||||
dest = emit_library_call_value (libfunc, NULL_RTX, LCT_CONST,
|
|
||||||
SImode, 2, op0, mode, op1, mode);
|
|
||||||
|
|
||||||
/* If this is UNEQ or LTGT, we call __lekf2, which returns -1 for less
|
if (!check_nan)
|
||||||
than, 0 for equal, +1 for greater, and +2 for nan. We add 1, to give
|
dest = emit_library_call_value (libfunc, NULL_RTX, LCT_CONST,
|
||||||
a value of 0..3, and then do and AND immediate of 1 to isolate whether
|
SImode, 2, op0, mode, op1, mode);
|
||||||
it is 0/Nan (i.e. bottom bit is 0), or less than/greater than
|
|
||||||
(i.e. bottom bit is 1). */
|
/* The library signals an exception for signalling NaNs, so we need to
|
||||||
if (uneq_or_ltgt)
|
handle isgreater, etc. by first checking isordered. */
|
||||||
|
else
|
||||||
{
|
{
|
||||||
rtx add_result = gen_reg_rtx (SImode);
|
rtx ne_rtx, normal_dest, unord_dest;
|
||||||
rtx and_result = gen_reg_rtx (SImode);
|
rtx unord_func = optab_libfunc (unord_optab, mode);
|
||||||
emit_insn (gen_addsi3 (add_result, dest, GEN_INT (1)));
|
rtx join_label = gen_label_rtx ();
|
||||||
emit_insn (gen_andsi3 (and_result, add_result, GEN_INT (1)));
|
rtx join_ref = gen_rtx_LABEL_REF (VOIDmode, join_label);
|
||||||
dest = and_result;
|
rtx unord_cmp = gen_reg_rtx (comp_mode);
|
||||||
|
|
||||||
|
|
||||||
|
/* Test for either value being a NaN. */
|
||||||
|
gcc_assert (unord_func);
|
||||||
|
unord_dest = emit_library_call_value (unord_func, NULL_RTX, LCT_CONST,
|
||||||
|
SImode, 2, op0, mode, op1,
|
||||||
|
mode);
|
||||||
|
|
||||||
|
/* Set value (0) if either value is a NaN, and jump to the join
|
||||||
|
label. */
|
||||||
|
dest = gen_reg_rtx (SImode);
|
||||||
|
emit_move_insn (dest, const1_rtx);
|
||||||
|
emit_insn (gen_rtx_SET (unord_cmp,
|
||||||
|
gen_rtx_COMPARE (comp_mode, unord_dest,
|
||||||
|
const0_rtx)));
|
||||||
|
|
||||||
|
ne_rtx = gen_rtx_NE (comp_mode, unord_cmp, const0_rtx);
|
||||||
|
emit_jump_insn (gen_rtx_SET (pc_rtx,
|
||||||
|
gen_rtx_IF_THEN_ELSE (VOIDmode, ne_rtx,
|
||||||
|
join_ref,
|
||||||
|
pc_rtx)));
|
||||||
|
|
||||||
|
/* Do the normal comparison, knowing that the values are not
|
||||||
|
NaNs. */
|
||||||
|
normal_dest = emit_library_call_value (libfunc, NULL_RTX, LCT_CONST,
|
||||||
|
SImode, 2, op0, mode, op1,
|
||||||
|
mode);
|
||||||
|
|
||||||
|
emit_insn (gen_cstoresi4 (dest,
|
||||||
|
gen_rtx_fmt_ee (code, SImode, normal_dest,
|
||||||
|
const0_rtx),
|
||||||
|
normal_dest, const0_rtx));
|
||||||
|
|
||||||
|
/* Join NaN and non-Nan paths. Compare dest against 0. */
|
||||||
|
emit_label (join_label);
|
||||||
|
code = NE;
|
||||||
}
|
}
|
||||||
|
|
||||||
emit_insn (gen_rtx_SET (compare_result,
|
emit_insn (gen_rtx_SET (compare_result,
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,10 @@
|
||||||
|
2016-07-26 Michael Meissner <meissner@linux.vnet.ibm.com>
|
||||||
|
|
||||||
|
PR target/71869
|
||||||
|
* gcc.target/powerpc/float128-cmp.c: New test to make sure that
|
||||||
|
IEEE built-in functions handle quiet and signalling NaNs
|
||||||
|
correctly.
|
||||||
|
|
||||||
2016-07-26 Steven G. Kargl <kargl@gcc.gnu.org>
|
2016-07-26 Steven G. Kargl <kargl@gcc.gnu.org>
|
||||||
|
|
||||||
PR fortran/71862
|
PR fortran/71862
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,106 @@
|
||||||
|
/* { dg-do run { target { powerpc*-*-linux* } } } */
|
||||||
|
/* { dg-require-effective-target ppc_float128_sw } */
|
||||||
|
/* { dg-options "-mvsx -O2 -mfloat128" } */
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#ifndef TYPE
|
||||||
|
#define TYPE __float128
|
||||||
|
#define NAN __builtin_nanq ("")
|
||||||
|
#define SNAN __builtin_nansq ("")
|
||||||
|
#else
|
||||||
|
#define NAN __builtin_nan ("")
|
||||||
|
#define SNAN __builtin_nans ("")
|
||||||
|
#endif
|
||||||
|
|
||||||
|
extern void check (TYPE a,
|
||||||
|
TYPE b,
|
||||||
|
int eq,
|
||||||
|
int ne,
|
||||||
|
int lt,
|
||||||
|
int le,
|
||||||
|
int gt,
|
||||||
|
int ge,
|
||||||
|
int i_lt,
|
||||||
|
int i_le,
|
||||||
|
int i_gt,
|
||||||
|
int i_ge,
|
||||||
|
int i_lg,
|
||||||
|
int i_un) __attribute__((__noinline__));
|
||||||
|
|
||||||
|
void
|
||||||
|
check (TYPE a,
|
||||||
|
TYPE b,
|
||||||
|
int eq,
|
||||||
|
int ne,
|
||||||
|
int lt,
|
||||||
|
int le,
|
||||||
|
int gt,
|
||||||
|
int ge,
|
||||||
|
int i_lt,
|
||||||
|
int i_le,
|
||||||
|
int i_gt,
|
||||||
|
int i_ge,
|
||||||
|
int i_lg,
|
||||||
|
int i_un)
|
||||||
|
{
|
||||||
|
if (eq != (a == b))
|
||||||
|
abort ();
|
||||||
|
|
||||||
|
if (ne != (a != b))
|
||||||
|
abort ();
|
||||||
|
|
||||||
|
if (lt != (a < b))
|
||||||
|
abort ();
|
||||||
|
|
||||||
|
if (le != (a <= b))
|
||||||
|
abort ();
|
||||||
|
|
||||||
|
if (gt != (a > b))
|
||||||
|
abort ();
|
||||||
|
|
||||||
|
if (ge != (a >= b))
|
||||||
|
abort ();
|
||||||
|
|
||||||
|
if (i_lt != __builtin_isless (a, b))
|
||||||
|
abort ();
|
||||||
|
|
||||||
|
if (i_le != __builtin_islessequal (a, b))
|
||||||
|
abort ();
|
||||||
|
|
||||||
|
if (i_gt != __builtin_isgreater (a, b))
|
||||||
|
abort ();
|
||||||
|
|
||||||
|
if (i_ge != __builtin_isgreaterequal (a, b))
|
||||||
|
abort ();
|
||||||
|
|
||||||
|
if (i_lg != __builtin_islessgreater (a, b))
|
||||||
|
abort ();
|
||||||
|
|
||||||
|
if (i_un != __builtin_isunordered (a, b))
|
||||||
|
abort ();
|
||||||
|
}
|
||||||
|
|
||||||
|
int main (void)
|
||||||
|
{
|
||||||
|
TYPE one = (TYPE) +1.0;
|
||||||
|
TYPE two = (TYPE) +2.0;
|
||||||
|
TYPE pzero = (TYPE) +0.0;
|
||||||
|
TYPE mzero = (TYPE) -0.0;
|
||||||
|
TYPE nan = (TYPE) NAN;
|
||||||
|
TYPE snan = (TYPE) SNAN;
|
||||||
|
|
||||||
|
check (one, two, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0);
|
||||||
|
check (one, one, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0);
|
||||||
|
check (one, pzero, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 0);
|
||||||
|
check (mzero, pzero, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0);
|
||||||
|
check (nan, one, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1);
|
||||||
|
check (one, nan, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1);
|
||||||
|
check (nan, nan, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1);
|
||||||
|
check (snan, one, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1);
|
||||||
|
check (one, snan, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1);
|
||||||
|
check (snan, nan, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1);
|
||||||
|
check (nan, snan, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue