Ticket #530 (closed bug: wontfix)

Opened 6 years ago

Last modified 5 years ago

Failure of atan2 in jit core - ref TT #38

Reported by: mikehh Owned by:
Priority: normal Milestone:
Component: none Version: trunk
Severity: medium Keywords:
Cc: Language:
Patch status: Platform: linux

Description

Failure of atan2 in jit core on Kubuntu Intrepid i386 at r37825.

from make fulltest at r37704

not ok 13 - atan2 # TODO broken under JIT TT #201

TT #201 was marked as duplicate of TT #38

from make fulltest at r37825 (and r37831)

#   Failed test 'atan2'
#   at t/op/trans.t line 275.
#          got: 'not ok 1
# not ok 2
# not ok 3
# not ok 4
# not ok 5
# not ok 6
# not ok 7
# not ok 8
# not ok 9
# not ok 10
# not ok 11
# not ok 12
# ok 13
# ok 14
# ok 15
# ok 16
# '
#     expected: 'ok 1
# ok 2
# ok 3
# ok 4
# ok 5
# ok 6
# ok 7
# ok 8
# ok 9
# ok 10
# ok 11
# ok 12
# ok 13
# ok 14
# ok 15
# ok 16
# '
# Looks like you failed 1 test of 22.
t/op/trans.t ........................... 
Dubious, test returned 1 (wstat 256, 0x100)
Failed 1/22 subtests 

smolder test passes  http://smolder.plusthree.com/app/public_projects/report_details/19505

also 19530 - the other cores pass the test.

I have recently been running on Ubuntu Intrepid Amd64 where make fulltest PASSes but that does not test the jit core.

I have seen some work done on atan (supposedly on Solaris) recently - that might have had an effect?

I tried to reopen TT #38, but did not have permission.

Cheers Michael (mikehh)

Attachments

jit.patch Download (3.4 KB) - added by rg 6 years ago.

Change History

  Changed 6 years ago by mikehh

I tried various things to get this to work.

I even thought it might be the compiler. I actually downloaded gcc-4.3.3 and built it - which took me a whole day. Using this gave the same result. I tried without the --optimize flag on the configure - same result.

The test fails with the above results with and without the --optimize flag on parrot r37894.

smolder with --optimize  http://smolder.plusthree.com/app/public_projects/tap_archive/19613

without  http://smolder.plusthree.com/app/public_projects/tap_archive/19614

The test perl t/harness -j t/op/trans.t fails as above with or without the optimize.

Failed test 'atan2'

The test PASSes for -b, -C, -f, -g, -r and -S both with and without --optimize.

I am not sure how to proceed here - any ideas would be welcome.

Cheers, Michael (mikehh)

follow-up: ↓ 3   Changed 6 years ago by mikehh

I thought I would have a look at this again - r37921

The test in question t/op/trans.t generates various .pasm files - the failing one bring t/op/trans_13.pasm:

        .include 'include/fp_equality.pasm'
        set N0, 0.0
        set I0, 0
        set N1, 1.0
        set I1, 1
        set N2, 1.0
        set I2, 1
        set I3, -1
        set N3, -1.0

        atan N4, N1, N2
        .fp_eq_pasm  (N4, 0.785398, EQ1)
        print "not "
EQ1:    print "ok 1\n"

        atan N4, N1, I2
        .fp_eq_pasm  (N4, 0.785398, EQ2)
        print "not "
EQ2:    print "ok 2\n"

        atan N4, I1, N2
        .fp_eq_pasm  (N4, 0.785398, EQ3)
        print "not "
EQ3:    print "ok 3\n"

        atan N4, I1, I2
        .fp_eq_pasm  (N4, 0.785398, EQ4)
        print "not "
EQ4:    print "ok 4\n"

        atan N4, N3, 1.0
        .fp_eq_pasm   (N4, -0.785398, EQ5)
        print "not "
EQ5:    print "ok 5\n"

        atan N4, N1, 0
        .fp_eq_pasm   (N4, 1.570796, EQ6)
        print "not "
EQ6:    print "ok 6\n"

        atan N4, I3, 0.0
        .fp_eq_pasm   (N4, -1.570796, EQ7)
        print "not "
EQ7:    print "ok 7\n"

        atan N4, I3, -1
        .fp_eq_pasm   (N4, -2.356194, EQ8)
        print "not "
EQ8:    print "ok 8\n"

        atan N4, 1.0, N3
        .fp_eq_pasm   (N4, 2.356194, EQ9)
        print "not "
EQ9:    print "ok 9\n"

        atan N4, 1.0, I0
        .fp_eq_pasm   (N4, 1.570796, EQ10)
        print "not "
EQ10:   print "ok 10\n"

        atan N4, 1, N1
        .fp_eq_pasm   (N4, 0.785398, EQ11)
        print "not "
EQ11:   print "ok 11\n"

        atan N4, 1, I1
        .fp_eq_pasm   (N4, 0.785398, EQ12)
        print "not "
EQ12:   print "ok 12\n"

        atan N4, 0.0, 1.0
        .fp_eq_pasm   (N4, 0.000000, EQ13)
        print "not "
EQ13:   print "ok 13\n"

        atan N4, -1.0, 0
        .fp_eq_pasm   (N4, -1.570796, EQ14)
        print "not "
EQ14:   print "ok 14\n"

        atan N4, 1, -1.0
        .fp_eq_pasm   (N4, 2.356194, EQ15)
        print "not "
EQ15:   print "ok 15\n"

        atan N4, 0, 1
        .fp_eq_pasm   (N4, 0.000000, EQ16)
        print "not "
EQ16:   print "ok 16\n"
        end

running with the jit core gives the failing result:
./parrot -Rjit t/op/trans_13.pasm ->

not ok 1
not ok 2
not ok 3
not ok 4
not ok 5
not ok 6
not ok 7
not ok 8
not ok 9
not ok 10
not ok 11
not ok 12
ok 13
ok 14
ok 15
ok 16

runnung without the jit core produces OK results. I then edited the .pasm file removing the test stuff and inserting print statements - trans_test_13.pasm ->

        set N0, 0.0
        set I0, 0
        set N1, 1.0
        set I1, 1
        set N2, 1.0
        set I2, 1
        set I3, -1
        set N3, -1.0

        atan N4, N1, N2
	print N4
	print "\n"

        atan N4, N1, I2
	print N4
	print "\n"

        atan N4, I1, N2
	print N4
	print "\n"

        atan N4, I1, I2
	print N4
	print "\n"

        atan N4, N3, 1.0
	print N4
	print "\n"

        atan N4, N1, 0
	print N4
	print "\n"

        atan N4, I3, 0.0
	print N4
	print "\n"

        atan N4, I3, -1
	print N4
	print "\n"

        atan N4, 1.0, N3
	print N4
	print "\n"

        atan N4, 1.0, I0
	print N4
	print "\n"

        atan N4, 1, N1
	print N4
	print "\n"

        atan N4, 1, I1
	print N4
	print "\n"

        atan N4, 0.0, 1.0
	print N4
	print "\n"

        atan N4, -1.0, 0
	print N4
	print "\n"

        atan N4, 1, -1.0
	print N4
	print "\n"

        atan N4, 0, 1
	print N4
	print "\n"

        end

This generated the following - ./parrot -Rjit trans_test_13.pasm ->

NaN
0.785398163397448
0.785398163397448
0.785398163397448
-0.785398163397448
1.5707963267949
-1.5707963267949
-2.35619449019234
2.35619449019234
1.5707963267949
0.785398163397448
0.785398163397448
0
-1.5707963267949
2.35619449019234
0

Running this without the jit core replaces the first line Nan with 0.785398163397448

I then inserted the following lines afrer the first call and print (line 19) ->

        print "do it again\n"
        atan N4, N1, N2
	print N4
	print "\n"

./parrot -Rjit trans_test_13.pasm
NaN
do it again
0.785398163397448
0.785398163397448
0.785398163397448
0.785398163397448
-0.785398163397448
1.5707963267949
-1.5707963267949
-2.35619449019234
2.35619449019234
1.5707963267949
0.785398163397448
0.785398163397448
0
-1.5707963267949
2.35619449019234
0

It appears that the jit core produces a Nan the first time it is run and afterwards produces the correct results. This is NOT reflected in the test.

Cheers, Michael (mikehh)

in reply to: ↑ 2   Changed 6 years ago by jkeenan

Replying to mikehh:

I thought I would have a look at this again - r37921

Thanks for the very thorough presentation. But, as reported on #parrot, I could not reproduce the test failures in Linux/i386:

$ ./parrot -Rjit t/op/trans_13.pasm
ok 1
ok 2
ok 3
ok 4
ok 5
ok 6
ok 7
ok 8
ok 9
ok 10
ok 11
ok 12
ok 13
ok 14
ok 15
ok 16

$ cat myconfig 
Summary of my parrot 1.0.0 (r37932) configuration:
  configdate='Mon Apr  6 22:52:56 2009 GMT'
  Platform:
    osname=linux, archname=i686-linux
    jitcapable=1, jitarchname=i386-linux,
    jitosname=LINUX, jitcpuarch=i386
    execcapable=1
    perl=/usr/local/bin/perl
  Compiler:
    cc='cc', ccflags=' -pipe -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE -DHASATTRIBUTE_CONST  -DHASATTRIBUTE_DEPRECATED  -DHASATTRIBUTE_MALLOC  -DHASATTRIBUTE_NONNULL  -DHASATTRIBUTE_NORETURN  -DHASATTRIBUTE_PURE  -DHASATTRIBUTE_UNUSED  -DHASATTRIBUTE_WARN_UNUSED_RESULT  -falign-functions=16 -fvisibility=hidden -funit-at-a-time -maccumulate-outgoing-args -W -Wall -Waggregate-return -Wcast-align -Wcast-qual -Wchar-subscripts -Wcomment -Wdisabled-optimization -Wendif-labels -Wextra -Wformat -Wformat-extra-args -Wformat-nonliteral -Wformat-security -Wformat-y2k -Wimplicit -Wimport -Winit-self -Winline -Winvalid-pch -Wmissing-braces -Wmissing-field-initializers -Wno-missing-format-attribute -Wmissing-include-dirs -Wpacked -Wparentheses -Wpointer-arith -Wreturn-type -Wsequence-point -Wno-shadow -Wsign-compare -Wstrict-aliasing -Wstrict-aliasing=2 -Wswitch -Wswitch-default -Wtrigraphs -Wundef -Wunknown-pragmas -Wno-unused -Wvariadic-macros -Wwrite-strings -Wbad-function-cast -Wc++-compat -Wdeclaration-after-statement -Wimplicit-function-declaration -Wimplicit-int -Wmain -Wmissing-declarations -Wmissing-prototypes -Wnested-externs -Wnonnull -DHAS_GETTEXT',
  Linker and Libraries:
    ld='cc', ldflags=' -L/usr/local/lib',
    cc_ldflags='',
    libs='-lnsl -ldl -lm -lcrypt -lutil -lpthread -lgmp -lreadline '
  Dynamic Linking:
    share_ext='.so', ld_share_flags='-shared -O2 -L/usr/local/lib -fPIC',
    load_ext='.so', ld_load_flags='-shared -O2 -L/usr/local/lib -fPIC'
  Types:
    iv=long, intvalsize=4, intsize=4, opcode_t=long, opcode_t_size=4,
    ptrsize=4, ptr_alignment=1 byteorder=1234, 
    nv=double, numvalsize=8, doublesize=8, longdoublesize=12

kid51 (who doesn't pretend to understand the deeper issues here)

  Changed 6 years ago by mikehh

I decided to have a look at this again:

I reduced the test to just the first try (and repeated)

mhk@mhk-desktop:~/parrot.t$ cat ../../mh/parrot.bu/tmp/test_atan_1.pasm
        set N0, 0.0
        set I0, 0
        set N1, 1.0
        set I1, 1
        set N2, 1.0
        set I2, 1
        set I3, -1
        set N3, -1.0

        print "N1 = "
        print N1
        print ", N2 = "
        print N2
        print ", N4 -> atan N4, N1, N2 = "
        atan N4, N1, N2
        print N4
        print "\n"

        print "do it again\n"
        print "N1 = "
        print N1
        print ", N2 = "
        print N2
        print ", N4 -> atan N4, N1, N2 = "
        atan N4, N1, N2
        print N4
        print "\n"

        end

mhk@mhk-desktop:~/parrot.t$ ./parrot -Rjit ../../mh/parrot.bu/tmp/test_atan_1.pasm
N1 = 1, N2 = 1, N4 -> atan N4, N1, N2 = NaN
do it again
N1 = 1, N2 = 1, N4 -> atan N4, N1, N2 = 0.785398163397448

I then removed the unused registers and the Damned thing worked:

mhk@mhk-desktop:~/parrot.t$ cat ../../mh/parrot.bu/tmp/test_atan_2.pasm
        set N1, 1.0
        set N2, 1.0

        print "N1 = "
        print N1
        print ", N2 = "
        print N2
        print ", N4 -> atan N4, N1, N2 = "
        atan N4, N1, N2
        print N4
        print "\n"

        print "do it again\n"
        print "N1 = "
        print N1
        print ", N2 = "
        print N2
        print ", N4 -> atan N4, N1, N2 = "
        atan N4, N1, N2
        print N4
        print "\n"

        end

mhk@mhk-desktop:~/parrot.t$ ./parrot -Rjit ../../mh/parrot.bu/tmp/test_atan_2.pasm
N1 = 1, N2 = 1, N4 -> atan N4, N1, N2 = 0.785398163397448
do it again
N1 = 1, N2 = 1, N4 -> atan N4, N1, N2 = 0.785398163397448

This was at r38059

Cheers, Michael (mikehh)

  Changed 6 years ago by rg

I've finally figured out the reason for these failures:
Parrot is mapping some N registers to x87 floating point registers. Before calling a non-jitted function, the registers are written back to memory (the N registers), however, they are not removed from the x87 registers. The problem with that is, that x87 treats those registers as a stack and produces a failure when it hits a register that is in use. What's worse is that Intel's documentation does not have a big warning that even if you're ignoring the stack overflow error, you're not getting the result you wanted, but a NaN instead. The thing is, the OS math libraries in question hit the registers used by parrot's jit, suddenly have junk values in their registers and the tests fail. (On FreeBSD, the pow function even uses the whole 8 registers, i.e. there may be *nothing* left behind in the registers.)

Now I've tried to change the function that saves the registers to also clear them, but I've hit a snag in the design of the jit there. Basically, the registers are also saved before a branch (or jump) statement, however if the branch is conditional and depends on a value from a number register, it assumes it's still there, i.e. all hell breaks loose after changing that ;)

As a result, the only solution I can offer so far is to not map any float registers. I'm attaching a patch that does just that and fixes a couple of resulting or related bugs aswell. It passes the same tests as without the patch for me on Ubuntu 9.04 beta and FreeBSD 7.1 (i386 obviously) plus the previously failed or todo-ed ones from trans.t.

Unfortunately, the jit code is not easy to work with, either. It has obviously evolved and some of the obsolete parts seem to be still in there. Therefor, I'm not sure how to proceed. Obviously I'd like to see the patch committed, so we are more correct. On the other hand, not mapping any float registers is of course a bit of a performance hit (not much since only true jitted ops can benefit from the mapped registers and there really aren't that many of those), still it's not the right thing to do. My problem is, I don't have the time to get it right. So are we going to open yet another ticket to describe what's really required? Ignore jit? Get a better jit from gsoc? Just leave this ticket open for someone to fix things properly?

Please advise.

Changed 6 years ago by rg

  Changed 6 years ago by mikehh

I tested at r38198 and got the same failures on Ubuntu Intrepid i386.

I then applied rg++'s patch did a make and the test passed. I then did a make testj which PASSed.

Cheers, Michael (mikehh)

  Changed 5 years ago by bacek

  • status changed from new to closed
  • resolution set to wontfix

Current JIT is deprecated.

Note: See TracTickets for help on using tickets.