dylan-lang / opendylan

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

LLVM: bug when calling primitive-single-float-sqrt #875

Open waywardmonkeys opened 9 years ago

waywardmonkeys commented 9 years ago

When compiling this code:

define common-extensions class-test <arithmetic-domain-error> ()
  check-condition("sqrt(-1.0) signals <arithmetic-domain-error>",
                  <arithmetic-domain-error>,
                  begin
                    let x :: <single-float> = -1.0s0;
                    primitive-single-float-sqrt(x);
                  end);
end class-test <arithmetic-domain-error>;

I get:

fatal error: error in backend: Cannot select: 0x7fbd4c03ec10: i32 = fsqrt 0x7fbd4c049630 [ORD=2] [ID=9] dbg:classes.dylan:70
  0x7fbd4c049630: i32 = add 0x7fbd4c046728, 0x7fbd4c046410 [ORD=2] [ID=8] dbg:classes.dylan:70
    0x7fbd4c046728: i32 = X86ISD::GlobalBaseReg [ORD=2] [ID=6] dbg:classes.dylan:70
    0x7fbd4c046410: i32 = X86ISD::Wrapper 0x7fbd4c046518 [ORD=2] [ID=7] dbg:classes.dylan:70
      0x7fbd4c046518: i32 = TargetGlobalAddress<%KLsingle_floatGVKd* @K188> 0 [TF=2] [ORD=2] [ID=5] dbg:classes.dylan:70
In function: Kanonymous_of_test_protocol_definitionF187I

clang: error: clang frontend command failed with exit code 70 (use -v to see invocation)

clang version 3.5.0 (tags/RELEASE_350/final)
Target: i386-apple-darwin14.1.0
Thread model: posix

clang: note: diagnostic msg: PLEASE submit a bug report to http://llvm.org/bugs/ and include the crash backtrace, preprocessed source, and associated run script.

clang: note: diagnostic msg: Error generating preprocessed source(s) - no preprocessable inputs.

The generated LLVM IR was:

define internal fastcc %struct.MV @Kanonymous_of_test_protocol_definitionF187I(i8* %.next, i8* %.function) {
bb.entry:
  %0 = call i8* @llvm.sqrt.p0i8(i8* bitcast (%KLsingle_floatGVKd* @K188 to i8*)) #2, !dbg !242
  %1 = insertvalue %struct.MV undef, i8* %0, 0, !dbg !243
  %2 = insertvalue %struct.MV %1, i8 1, 1, !dbg !243
  ret %struct.MV %2, !dbg !243
}
waywardmonkeys commented 9 years ago

Changing this to be correct with type conversions and all is well (at compilation time):

define common-extensions class-test <arithmetic-domain-error> ()
  check-condition("sqrt(-1.0) signals <arithmetic-domain-error>",
                  <arithmetic-domain-error>,
                  begin
                    let x :: <single-float> = -1.0s0;
                    primitive-raw-as-single-float(primitive-single-float-sqrt(primitive-single-float-as-raw(x)));
                  end);
end class-test <arithmetic-domain-error>;

That generated this IR:

define internal fastcc %struct.MV @Kanonymous_of_test_protocol_definitionF187I(i8* %.next, i8* %.function) {
bb.entry:
  %0 = call float @llvm.sqrt.f32(float -1.000000e+00) #2, !dbg !242
  %1 = call fastcc %KLsingle_floatGVKd* @primitive_raw_as_single_float(float %0), !dbg !242
  %2 = bitcast %KLsingle_floatGVKd* %1 to i8*, !dbg !242
  %3 = insertvalue %struct.MV undef, i8* %2, 0, !dbg !243
  %4 = insertvalue %struct.MV %3, i8 1, 1, !dbg !243
  ret %struct.MV %4, !dbg !243
}

(which didn't end up signaling the condition I was testing for ...)

housel commented 9 years ago

I imagine llvm.sqrt.f32 gets lowered to the standard sqrtf() function, which probably has its own domain checks so that it "returns a NaN and generates a domain error for x < 0."

waywardmonkeys commented 9 years ago

Well, on Mac OS X, this generates the right FP trap:

#include <fenv.h>
#include <math.h>
#include <stdio.h>

int main (int argc, char **argv)
{
  feclearexcept(FE_ALL_EXCEPT);
  fenv_t fenv;
  fegetenv(&fenv);
  fenv.__control &= ~(FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW | FE_INVALID);
  fenv.__mxcsr &= ~((FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW | FE_INVALID) << 7);
  fesetenv(&fenv);

  printf("%f\n", sqrt(-1.0 * argc));
  return 0;
}