RFA: fix PR tree-optimization/28144
Roger Sayle
roger@eyesopen.com
Tue Jun 27 02:19:00 GMT 2006
Hi Joern,
On Mon, 26 Jun 2006, Joern RENNECKE wrote:
> As well as fixing the java language issue, this patch also addresses the
> gratuitous inconsistency between -O0 and -O1 for C/C++ (PR27394).
One good reason why overflow in float->int conversion is undefined
in the C/C++ standards (and therefore why PR tree-optimization/27394
was closed as invalid), is because different (current) FP hardware
implements different semantics. The code not only produces different
results between -O0 and -O1, but between x86 and PowerPC (if memory
serves). For example, all overflowing FIX on x87 produce the result
-1 (regardless of the original low order bits)!
However, your patch is reasonable not for any "least surprise" for
novice C/C++ programmer's that don't understand FP portability issues
but because GCC's compile-time interpretation attempts to follow the
Java semantics in this respect, where the C/C++ standards allow us a
choice of implementations.
However, your current patch as posted does have its warts...
+ real_from_integer (&l, VOIDmode, (HOST_WIDE_INT) 0,
+ (HOST_WIDE_INT) -1 << 31, 0);
For the lower bound, the high word should be -1, so that this value
will be interpreted as a negative number, returning a negative real.
+ real_from_integer (&u, VOIDmode, (HOST_WIDE_INT) 0,
+ (HOST_WIDE_INT) 32767 << 16 | 65535L, 0);
And this integer constant should never be written as "32767 << 16 |
65535L". Please be consistent, using either matching shifts, such
as "-1 << 31" and "(1 << 31) - 1", or (when applicable) hexadecimal
constants.
In this case the magic numbers "31" and "32" are reasonable, over the
use of BITS_PER_WORD, to correctly match the Java semantics.
However, (i) you probably also need to consider conversion to unsigned
types, where the lower bound is zero, and the upper is UINT_MAX, and
(ii) the setting of high and low to ut/lt's values when we do overflow
is probably incorrect in these cases, and (iii) you need some additional
testcases to confirm that GCC correctly implements the intended
(Java-like) semantics and maybe even catch logic errors such as those
discussed above.
I think you probably want to write this patch something more like:
if (!overflow)
{
HOST_WIDE_INT lhi;
unsigned HOST_WIDE_INT llo;
REAL_VALUE_TYPE l;
if (TYPE_PRECISION (type) >= 32)
{
tree lt = TYPE_MIN_VALUE (type);
lhi = TREE_INT_CST_HIGH (lt);
llo = TREE_INT_CST_LOW (lt);
}
else if (TYPE_UNSIGNED (type))
{
lhi = 0;
llo = 0;
}
else
{
lhi = -1;
llo = (HOST_WIDE_INT) -1 << 31;
}
real_from_integer (&l, VOIDmode, lhi, llo,
TYPE_UNSIGNED (type));
if (REAL_VALUES_LESS (r, l))
{
overflow = 1;
high = lhi;
low = llo;
}
and something similar for the symmetric upper bound case, with uhi
and ulo (slightly complicated by the need to test for TYPE_MAX_VALUE
(type) != NULL_TREE).
Thanks for tackling this. Please could you post an updated patch
after bootstrap and regression testing, together with a new dejagnu
testcase or two. Thanks in advance.
Roger
--
More information about the Gcc-patches
mailing list