Wrong tan

Hi!

<tangens_bug.cc>

#include <iostream>
#include <cmath>

int main()
{
        float a = 0.3;
        double b = 0.3;

        float result_a = std::tan( a );
        float result_b = std::tan( b );
        std::cout << "tan float: " << result_a << std::endl;
        std::cout << "tan double: " << result_b << std::endl;
}

<end tangens_bug.cc>

Result compiled with g++ 4.1:
tan float: 0.309336
tan double: 0.309336

Result compiled with llvm-g++ 2.0:
tan float: -2.18504
tan double: 0.309336

Am I missing something or should I file a bug report?

Thanks,
Gonsolo

Result compiled with llvm-g++ 2.0:
tan float: -2.18504
tan double: 0.309336

This may be due to bug 1505.

Ciao,

Duncan.

It fails on x86 using x87 floating point, with the inliner not run,
because of 1505, yes. Gonsolo, is that your situation?

(What happens is, there is a wrapper in the header file for std::tan(float),
like this:

   inline float
   tan(float __x)
   { return __builtin_tanf(__x); }

This wrapper is miscompiled due to 1505; when the inliner is run, no problem.)

(But, when opt -std-compile-opts is run, the 'tan' call is evaluated at compile
time, while 'tanf' resolves to a libc call. This is undesirable, since the whole
reason tanf exists is that it's supposed to be faster than tan. Of course you
have to be very careful about doing FP operations at compile time, but I
assume this is being done right; it's getting the right answer here, anyway.)

Hi!

Dale Johannesen schrieb:

Result compiled with llvm-g++ 2.0:
tan float: -2.18504
tan double: 0.309336

This may be due to bug 1505.

It fails on x86 using x87 floating point, with the inliner not run,
because of 1505, yes. Gonsolo, is that your situation?

I tried a simple "llvm-g++ -o simple tan.bug.cc"
Output:
tan float: -2.18504
tan double: 0.309336

(What happens is, there is a wrapper in the header file for std::tan(float),
like this:

  inline float
  tan(float __x)
  { return __builtin_tanf(__x); }

This wrapper is miscompiled due to 1505; when the inliner is run, no problem.)

(But, when opt -std-compile-opts is run, the 'tan' call is evaluated at compile
time, while 'tanf' resolves to a libc call. This is undesirable, since the whole
reason tanf exists is that it's supposed to be faster than tan. Of course you
have to be very careful about doing FP operations at compile time, but I
assume this is being done right; it's getting the right answer here, anyway.)

I also tried:

1. g++

Output:
tan float: 0.309336
tan double: 0.309336

Works.

2. lli

Output:
tan float: 0.309336
tan double: 0.309336

Works

3. lli with opt

Output:
tan float: 0.309336
tan double: 0.309336

Works.

4. opt + llc + as + g++

Output:
tan float: 0.309336
tan double: 0.309336

Works

5. opt + llc + as + llvm-g++

Output:
tan float: 0
tan double: 0

???

In summary: Everything works except linking with llvm-g++!

Gonsolo

Appendix A:

<tan_bug.cc>
#include <iostream>
#include <cmath>

int main()
{
        float a = 0.3;
        double b = 0.3;

        float result_a = std::tan( a );
        float result_b = std::tan( b );
        std::cout << "tan float: " << result_a << std::endl;
        std::cout << "tan double: " << result_b << std::endl;
}

</tan_bug.cc>

Appendix B:

<Makefile>

all: test_g++ test_llvm-g++ test_interpreter test_interpreter_opt
test_native_g++ test_native_llvm-g++

.PHONY: c clean test_simple test_interpreter test_interpreter_opt
test_native_g++ test_native_llvm-g++

test_g++: simple_g++
        ./simple_g++

test_llvm-g++: simple_llvm
        ./simple_llvm

test_interpreter: emit.bc
        lli emit.bc

test_interpreter_opt: opt.bc
        lli opt.bc

test_native_g++: native_g++
        ./native_g++

test_native_llvm-g++: native_llvm-g++
        ./native_llvm-g++

simple_g++: tan_bug.cc
        g++ -o simple_g++ tan_bug.cc

simple_llvm: tan_bug.cc
        llvm-g++ -o simple_llvm tan_bug.cc

emit.bc: tan_bug.cc
        llvm-g++ -c --emit-llvm -o emit.bc tan_bug.cc

opt.bc: emit.bc
        opt -std-compile-opts emit.bc -o opt.bc

opt.s: opt.bc
        llc opt.bc -o opt.s

opt.o: opt.s
        as opt.s -o opt.o

native_g++: opt.o
        g++ -o native_g++ opt.o

native_llvm-g++: opt.o
        llvm-g++ -o native_llvm-g++ opt.o

c: clean
clean:
        rm -f simple_g++ simple_llvm emit.bc opt.bc opt.s opt.o
native_g++ native_llvm-g++

</Makefile>

Appendix C:

Thanks for your quick reply!!

Thanks, but what I'm trying to get at is, what kind of machine are you running on?
If x86, are you set up to use x87 or SSE for floating point? (You can tell by
compiling with -save-temps and looking at the .s file. If you see any references
to %xmm registers, that's SSE.)