re PR c/39902 (x * 1.0DF gets wrong value)
PR c/39902 * tree.c (real_zerop, real_onep, real_twop, real_minus_onep): Special-case decimal float constants. PR c/39902 * gcc.dg/dfp/pr39902.c: New test. From-SVN: r149058
This commit is contained in:
parent
086799fd3d
commit
ea3ce666e1
|
@ -1,3 +1,9 @@
|
|||
2009-06-29 Janis Johnson <janis187@us.ibm.com>
|
||||
|
||||
PR c/39902
|
||||
* tree.c (real_zerop, real_onep, real_twop, real_minus_onep):
|
||||
Special-case decimal float constants.
|
||||
|
||||
2009-06-29 Uros Bizjak <ubizjak@gmail.com>
|
||||
|
||||
* doc/extend.texi (Additional Floating Types): __float128 is also
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
2009-06-29 Janis Johnson <janis187@us.ibm.com>
|
||||
|
||||
PR c/39902
|
||||
* gcc.dg/dfp/pr39902.c: New test.
|
||||
|
||||
2009-06-29 Paul Thomas <pault@gcc.gnu.org>
|
||||
|
||||
PR fortran/40443
|
||||
|
|
|
@ -0,0 +1,239 @@
|
|||
/* { dg-options "--std=gnu99" } */
|
||||
|
||||
/* Check that optimizations like (x * 1) to x, or (x * -1) to -x,
|
||||
do not apply to decimal float computations where trailing zeroes
|
||||
are significant. */
|
||||
|
||||
extern void abort (void);
|
||||
int failcnt;
|
||||
|
||||
#ifdef DBG
|
||||
extern int printf (const char *, ...);
|
||||
#define FAILURE { printf ("failed at line %d\n", __LINE__); failcnt++; }
|
||||
#else
|
||||
#define FAILURE abort ();
|
||||
#endif
|
||||
|
||||
#define COMPARE32(A,B) \
|
||||
A.i == B.i
|
||||
|
||||
#define COMPARE64(A,B) \
|
||||
A.i[0] == B.i[0] && A.i[1] == B.i[1]
|
||||
|
||||
#define COMPARE128(A,B) \
|
||||
A.i[0] == B.i[0] && A.i[1] == B.i[1] && A.i[2] == B.i[2] && A.i[3] == B.i[3]
|
||||
|
||||
typedef union {
|
||||
_Decimal32 d;
|
||||
unsigned int i;
|
||||
} u32;
|
||||
|
||||
typedef union {
|
||||
_Decimal64 d;
|
||||
unsigned int i[2];
|
||||
} u64;
|
||||
|
||||
typedef union {
|
||||
_Decimal128 d;
|
||||
unsigned int i[4];
|
||||
} u128;
|
||||
|
||||
volatile u32 p32_1;
|
||||
volatile u32 p32_1_0;
|
||||
volatile u32 p32_2_0;
|
||||
volatile u32 m32_1;
|
||||
volatile u32 m32_1_0;
|
||||
volatile u32 m32_2_0;
|
||||
volatile u32 a32;
|
||||
|
||||
volatile u64 p64_1;
|
||||
volatile u64 p64_1_0;
|
||||
volatile u64 p64_2_0;
|
||||
volatile u64 m64_1;
|
||||
volatile u64 m64_1_0;
|
||||
volatile u64 m64_2_0;
|
||||
volatile u64 a64;
|
||||
|
||||
volatile u128 p128_1;
|
||||
volatile u128 p128_1_0;
|
||||
volatile u128 p128_2_0;
|
||||
volatile u128 m128_1;
|
||||
volatile u128 m128_1_0;
|
||||
volatile u128 m128_2_0;
|
||||
volatile u128 a128;
|
||||
|
||||
void
|
||||
init32 (void)
|
||||
{
|
||||
p32_1.d = 1.DF;
|
||||
p32_1_0.d = 1.0DF;
|
||||
p32_2_0.d = 2.0DF;
|
||||
m32_1.d = -1.DF;
|
||||
m32_1_0.d = -1.0DF;
|
||||
m32_2_0.d = -2.0DF;
|
||||
}
|
||||
|
||||
void
|
||||
init64 (void)
|
||||
{
|
||||
p64_1.d = 1.DD;
|
||||
p64_1_0.d = 1.0DD;
|
||||
p64_2_0.d = 2.0DD;
|
||||
m64_1.d = -1.DD;
|
||||
m64_1_0.d = -1.0DD;
|
||||
m64_2_0.d = -2.0DD;
|
||||
}
|
||||
|
||||
void
|
||||
init128 (void)
|
||||
{
|
||||
p128_1.d = 1.DL;
|
||||
p128_1_0.d = 1.0DL;
|
||||
p128_2_0.d = 2.0DL;
|
||||
m128_1.d = -1.DL;
|
||||
m128_1_0.d = -1.0DL;
|
||||
m128_2_0.d = -2.0DL;
|
||||
}
|
||||
|
||||
void
|
||||
doit32 (void)
|
||||
{
|
||||
/* Multiplying by a value with no trailing zero should not change the
|
||||
quantum exponent. */
|
||||
|
||||
a32.d = p32_2_0.d * p32_1.d;
|
||||
if (! (COMPARE32 (a32, p32_2_0)))
|
||||
FAILURE
|
||||
|
||||
a32.d = p32_2_0.d * 1.DF;
|
||||
if (! (COMPARE32 (a32, p32_2_0)))
|
||||
FAILURE
|
||||
|
||||
a32.d = p32_2_0.d * m32_1.d;
|
||||
if (! (COMPARE32 (a32, m32_2_0)))
|
||||
FAILURE
|
||||
|
||||
a32.d = p32_2_0.d * -1.DF;
|
||||
if (! (COMPARE32 (a32, m32_2_0)))
|
||||
FAILURE
|
||||
|
||||
/* Multiplying by a value with a trailing zero should change the
|
||||
quantum exponent. */
|
||||
|
||||
a32.d = p32_2_0.d * p32_1_0.d;
|
||||
if (COMPARE32 (a32, p32_2_0))
|
||||
FAILURE
|
||||
|
||||
a32.d = p32_2_0.d * 1.0DF;
|
||||
if (COMPARE32 (a32, p32_2_0))
|
||||
FAILURE
|
||||
|
||||
a32.d = p32_2_0.d * m32_1_0.d;
|
||||
if (COMPARE32 (a32, m32_2_0))
|
||||
FAILURE
|
||||
|
||||
a32.d = p32_2_0.d * -1.0DF;
|
||||
if (COMPARE32 (a32, m32_2_0))
|
||||
FAILURE
|
||||
}
|
||||
|
||||
void
|
||||
doit64 (void)
|
||||
{
|
||||
/* Multiplying by a value with no trailing zero should not change the
|
||||
quantum exponent. */
|
||||
|
||||
a64.d = p64_2_0.d * p64_1.d;
|
||||
if (! (COMPARE64 (a64, p64_2_0)))
|
||||
FAILURE
|
||||
|
||||
a64.d = p64_2_0.d * 1.DD;
|
||||
if (! (COMPARE64 (a64, p64_2_0)))
|
||||
FAILURE
|
||||
|
||||
a64.d = p64_2_0.d * m64_1.d;
|
||||
if (! (COMPARE64 (a64, m64_2_0)))
|
||||
FAILURE
|
||||
|
||||
a64.d = p64_2_0.d * -1.DD;
|
||||
if (! (COMPARE64 (a64, m64_2_0)))
|
||||
FAILURE
|
||||
|
||||
/* Multiplying by a value with a trailing zero should change the
|
||||
quantum exponent. */
|
||||
|
||||
a64.d = p64_2_0.d * p64_1_0.d;
|
||||
if (COMPARE64 (a64, p64_2_0))
|
||||
FAILURE
|
||||
|
||||
a64.d = p64_2_0.d * 1.0DD;
|
||||
if (COMPARE64 (a64, p64_2_0))
|
||||
FAILURE
|
||||
|
||||
a64.d = p64_2_0.d * m64_1_0.d;
|
||||
if (COMPARE64 (a64, m64_2_0))
|
||||
FAILURE
|
||||
|
||||
a64.d = p64_2_0.d * -1.0DD;
|
||||
if (COMPARE64 (a64, m64_2_0))
|
||||
FAILURE
|
||||
}
|
||||
|
||||
void
|
||||
doit128 (void)
|
||||
{
|
||||
/* Multiplying by a value with no trailing zero should not change the
|
||||
quantum exponent. */
|
||||
|
||||
a128.d = p128_2_0.d * p128_1_0.d;
|
||||
if (COMPARE128 (a128, p128_2_0))
|
||||
FAILURE
|
||||
|
||||
a128.d = p128_2_0.d * 1.0DD;
|
||||
if (COMPARE128 (a128, p128_2_0))
|
||||
FAILURE
|
||||
|
||||
a128.d = p128_2_0.d * m128_1_0.d;
|
||||
if (COMPARE128 (a128, m128_2_0))
|
||||
FAILURE
|
||||
|
||||
a128.d = p128_2_0.d * -1.0DD;
|
||||
if (COMPARE128 (a128, m128_2_0))
|
||||
FAILURE
|
||||
|
||||
/* Multiplying by a value with a trailing zero should change the
|
||||
quantum exponent. */
|
||||
|
||||
a128.d = p128_2_0.d * p128_1.d;
|
||||
if (! (COMPARE128 (a128, p128_2_0)))
|
||||
FAILURE
|
||||
|
||||
a128.d = p128_2_0.d * 1.DD;
|
||||
if (! (COMPARE128 (a128, p128_2_0)))
|
||||
FAILURE
|
||||
|
||||
a128.d = p128_2_0.d * m128_1.d;
|
||||
if (! (COMPARE128 (a128, m128_2_0)))
|
||||
FAILURE
|
||||
|
||||
a128.d = p128_2_0.d * -1.DD;
|
||||
if (! (COMPARE128 (a128, m128_2_0)))
|
||||
FAILURE
|
||||
}
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
init32 ();
|
||||
init64 ();
|
||||
init128 ();
|
||||
|
||||
doit32 ();
|
||||
doit64 ();
|
||||
doit128 ();
|
||||
|
||||
if (failcnt != 0)
|
||||
abort ();
|
||||
|
||||
return 0;
|
||||
}
|
25
gcc/tree.c
25
gcc/tree.c
|
@ -1606,7 +1606,8 @@ tree_floor_log2 (const_tree expr)
|
|||
: floor_log2 (low));
|
||||
}
|
||||
|
||||
/* Return 1 if EXPR is the real constant zero. */
|
||||
/* Return 1 if EXPR is the real constant zero. Trailing zeroes matter for
|
||||
decimal float constants, so don't return 1 for them. */
|
||||
|
||||
int
|
||||
real_zerop (const_tree expr)
|
||||
|
@ -1614,13 +1615,16 @@ real_zerop (const_tree expr)
|
|||
STRIP_NOPS (expr);
|
||||
|
||||
return ((TREE_CODE (expr) == REAL_CST
|
||||
&& REAL_VALUES_EQUAL (TREE_REAL_CST (expr), dconst0))
|
||||
&& REAL_VALUES_EQUAL (TREE_REAL_CST (expr), dconst0)
|
||||
&& !(DECIMAL_FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (expr)))))
|
||||
|| (TREE_CODE (expr) == COMPLEX_CST
|
||||
&& real_zerop (TREE_REALPART (expr))
|
||||
&& real_zerop (TREE_IMAGPART (expr))));
|
||||
}
|
||||
|
||||
/* Return 1 if EXPR is the real constant one in real or complex form. */
|
||||
/* Return 1 if EXPR is the real constant one in real or complex form.
|
||||
Trailing zeroes matter for decimal float constants, so don't return
|
||||
1 for them. */
|
||||
|
||||
int
|
||||
real_onep (const_tree expr)
|
||||
|
@ -1628,13 +1632,15 @@ real_onep (const_tree expr)
|
|||
STRIP_NOPS (expr);
|
||||
|
||||
return ((TREE_CODE (expr) == REAL_CST
|
||||
&& REAL_VALUES_EQUAL (TREE_REAL_CST (expr), dconst1))
|
||||
&& REAL_VALUES_EQUAL (TREE_REAL_CST (expr), dconst1)
|
||||
&& !(DECIMAL_FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (expr)))))
|
||||
|| (TREE_CODE (expr) == COMPLEX_CST
|
||||
&& real_onep (TREE_REALPART (expr))
|
||||
&& real_zerop (TREE_IMAGPART (expr))));
|
||||
}
|
||||
|
||||
/* Return 1 if EXPR is the real constant two. */
|
||||
/* Return 1 if EXPR is the real constant two. Trailing zeroes matter
|
||||
for decimal float constants, so don't return 1 for them. */
|
||||
|
||||
int
|
||||
real_twop (const_tree expr)
|
||||
|
@ -1642,13 +1648,15 @@ real_twop (const_tree expr)
|
|||
STRIP_NOPS (expr);
|
||||
|
||||
return ((TREE_CODE (expr) == REAL_CST
|
||||
&& REAL_VALUES_EQUAL (TREE_REAL_CST (expr), dconst2))
|
||||
&& REAL_VALUES_EQUAL (TREE_REAL_CST (expr), dconst2)
|
||||
&& !(DECIMAL_FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (expr)))))
|
||||
|| (TREE_CODE (expr) == COMPLEX_CST
|
||||
&& real_twop (TREE_REALPART (expr))
|
||||
&& real_zerop (TREE_IMAGPART (expr))));
|
||||
}
|
||||
|
||||
/* Return 1 if EXPR is the real constant minus one. */
|
||||
/* Return 1 if EXPR is the real constant minus one. Trailing zeroes
|
||||
matter for decimal float constants, so don't return 1 for them. */
|
||||
|
||||
int
|
||||
real_minus_onep (const_tree expr)
|
||||
|
@ -1656,7 +1664,8 @@ real_minus_onep (const_tree expr)
|
|||
STRIP_NOPS (expr);
|
||||
|
||||
return ((TREE_CODE (expr) == REAL_CST
|
||||
&& REAL_VALUES_EQUAL (TREE_REAL_CST (expr), dconstm1))
|
||||
&& REAL_VALUES_EQUAL (TREE_REAL_CST (expr), dconstm1)
|
||||
&& !(DECIMAL_FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (expr)))))
|
||||
|| (TREE_CODE (expr) == COMPLEX_CST
|
||||
&& real_minus_onep (TREE_REALPART (expr))
|
||||
&& real_zerop (TREE_IMAGPART (expr))));
|
||||
|
|
Loading…
Reference in New Issue