dylan-lang / opendylan

Open Dylan compiler and IDE
http://opendylan.org/
Other
456 stars 68 forks source link

Arithmetic domain error on perfectly fine code with LLVM-Backend #1606

Open spreadLink opened 3 months ago

spreadLink commented 3 months ago

The following code should be fine according to Dylan semantics, but causes an arithmetic-domain-error:

define constant <v3> = limited(<vector>, of: <single-float>, size: 3);

define function stop-llvm-from-inlining-everything(v :: <v3>) => (v :: <v3>)
  v
end function;

define function run()
  let v = make(<v3>, fill: 0.0);
  v[0] := 1.0;
  v[1] := 2.0;
  v[2] := 3.0;
  stop-llvm-from-inlining-everything(v);
  v[0] := v[1] / 40.0;
  v[1] := v[2] / 40.0;
  v[2] := v[0] / 40.0;
end function;

run();

Presumably this happens due to floating point traps being enabled via feenableexcept, but LLVM assumes they are not.

cgay commented 3 months ago

The error occurs on the second assignment to v[1]: https://play.opendylan.org/shared/e9eb19497771d59e

and doesn't occur when we use doubles everywhere: https://play.opendylan.org/shared/4bbbb7e7045e1a1c

spreadLink commented 3 months ago

Yes, it occurs because LLVM believes it can coalesce the last two divisions into a simd packed single division, as that would be legal with the default semantics for C, but isn't a valid transform when the invalid floating point flag is in effect. This SO post also ran into the issue (in C): https://stackoverflow.com/questions/53982412/perfectly-fine-division-throws-floating-point-exception

housel commented 3 months ago

I verified that the issue can be fixed by adding the strictfp attribute to all relevant functions. My llvm library's attribute support is still stuck in 2015, but once this is resolved I'll be able to add it.