On Thu, Nov 06, 2014 at 08:57:44AM -0800, Ian Taylor wrote:
> On Wed, Nov 5, 2014 at 9:13 AM, Dominik Vogt <
vo...@linux.vnet.ibm.com> wrote:
> > But there is no issue in Gcc. The Go testsuite's assumption that
> > run time calculations must yield the same result as pre-calculated
> > constant calculations does not hold true in Gcc because Gcc uses
> > higher precision for that (libgmp).
>
> For the Go language, I can't describe that as anything other than a
> bug. Go has both untyped constants and typed constants. Calculations
> involving typed constants follow the exact rules of the type. The Go
> frontend implements this. Untyped constants are handled entirely by
> the frontend and never reach the GCC middle-end. Typed constants are
> computed one operation at a time and rounded back to the type after
> each operation.
I'm not sure whether what you say is really applicable here. From
cplx2.go:
const (
R = 5
I = 6i
C1 = R + I // ADD(5,6)
C5 = C1 + R // ADD(10,6)
C6 = C1 + I // ADD(5,12)
Cd = C5 / C6 // DIV(0.721893,-0.532544)
)
The mentioned test case compares with Cd. There are three
approaches how the compiler could express that:
1) Every time Cd appears in the code with type T, generate code
to calculate
Cd T = C5 / C6 = (T(5) + T(6i) + T(5)) / (T(5) + T(6i) + T(6i))
T can be a different type every time Cd is used. (I.e.
disable pre-calculation of anonymous constants.) Only possible
if the whole definition of the constant is in the same compile
unit. This would rule out linking Go code with libraries that
define anonymous constants, or in other words, anonymous constants
cannot be exported to other compile units. (But this is done
in the math library anyway.)
2) Pre-calculate a different version of Cd for every possible
type (complex64, complex128, float32(?), int64(?), ...), then
pick the correct version every time it's used.
3) Pre-calculate Cd with the highest possible precision, then
scale it down to the type that is actually needed in the code
that uses Cd. (This is done in the frontend.)
Gcc currently does (3), and if I read your explanation correctly,
you imply that it should do (1) and must not do (2)?
--
To understand this issue better, can you point me to the specs
that require that
a) Calculations using constants in Go must have the same result as
calculations using dynamic values.
b) Multiple identical calculations of the same formula in
different places of the Go code (i.e. in different surrounding
context) must yield identical results?
Especially (b) seems to be impossible to guarantee to me, because
it depends on the code that is actually generated at the place
where the constant is used.
> I admit that I have still have not looked at the actual code in GCC,
> but your description makes the code sound simply wrong for Go. It is
> probably acceptable for C/C++, though I doubt it is correct for Java.
> And it may not be worth fixing. But I don't see any way to describe
> it as correct.
>
> That said, when I look at PR 60181, it appears to be saying something
> different. It appears to be saying that the compile-time calculation
> is correct, but the runtime calculation is not.
What do you mean? In the comments I find
>> Constant folding is correctly rounding, runtime complex
>> multiplication / division isn't (and given complaints about
>> slowness at present, I don't think users would want it to be even
>> slower, though there may well be a case for defining a standard
>> library interface for correctly rounding complex multiplication /
>> division).
and
>> you generally cannot expect constant folding and runtime execution
>> to produce the exact same result. This is FP after all ...
And regardless of the discussion above, "this is FP after all"
always wins, no?