Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

JIT & branches under the Sun

6 views
Skip to first unread message

Stephane Peiry

unread,
Feb 12, 2004, 4:07:28 PM2/12/04
to perl6-i...@perl.org

Hi All,

While playing with JIT on Suns, I've found out that the following pasm code:

set I1, 2
LOOP: sub I1, 1
if I1, LOOP
print "end\n"
end

never finishes.. that is: parrot -j loop.pasm hangs forever (never printing
'end') while the non-jitted "parrot loop.pasm" prints 'end' and finishes
there as expected.

Can anybody give me some hints as to what is going on there? :)
Thanks,
Stephane

PS.: placing a 'print I1' within the loop resolves the problem, both jitted
and non jitted finishing properly in that case. Instead 'noop', 'set <some>'
or else within the loop dont help the jitted case and hangs again..

loop.pasm
myconfig

Leopold Toetsch

unread,
Feb 13, 2004, 4:48:09 AM2/13/04
to Stephane Peiry, perl6-i...@perl.org
Stephane Peiry <step...@modxml.org> wrote:

> While playing with JIT on Suns, I've found out that the following pasm code:

> set I1, 2
> LOOP: sub I1, 1
> if I1, LOOP
> print "end\n"
> end

> never finishes.. that is: parrot -j loop.pasm hangs forever (never printing
> 'end') while the non-jitted "parrot loop.pasm" prints 'end' and finishes
> there as expected.

I don't know suns JIT code nor the assembler syntax, but it seems that
the two subcc lines are broken:

emitm_subcc_r(NATIVECODE, MAP[1], emitm_g(0), emitm_g(0));

If I understand that correctly it should read:

emitm_subcc_r(NATIVECODE, MAP[1], MAP[1], emitm_g(0));

(and similar a few lines below) - at least when compared to other code
that uses subcc_r.

> Thanks,
> Stephane

> PS.: placing a 'print I1' within the loop resolves the problem,

That could clear g(0) ...

leo

Stephane Peiry

unread,
Feb 14, 2004, 7:39:25 AM2/14/04
to Leopold Toetsch, perl6-i...@perl.org
On Fri, Feb 13, 2004 at 10:48:09AM +0100, Leopold Toetsch wrote:
> I don't know suns JIT code nor the assembler syntax, but it seems that
> the two subcc lines are broken:
>
> emitm_subcc_r(NATIVECODE, MAP[1], emitm_g(0), emitm_g(0));
>
> If I understand that correctly it should read:
>
> emitm_subcc_r(NATIVECODE, MAP[1], MAP[1], emitm_g(0));

This would actually compare, say I1, to itself, and would then always be equal.
So as I understand it, the line is ok: the subcc_r lines build these "synthetic"
instructions where a compare is

cmp reg, reg_or_imm <--> subcc reg, reg_or_imm, %g0

Since <if> compares reg to 0 (as the not jitted core does), it uses register %g0
(for reg_or_imm) which contains 0 (%g0 is actually a special register in sparc
always containing 0 no matter how - its just "constant 0"). Hence we have

subcc reg, %g0, %g0

and in parrot(jit) terms:

emitm_subcc_r(NATIVECODE, MAP[1], emitm_g(0), emitm_g(0));

Somehow I thaught that the problem could lie in the "optimize" section? Is there
any simple way to disable that for jit? (it seems quite hardwired atm). Also,
whats a good way to debug jit? meanning, I'm able to step through and see what
is going on with gdb while still in "parrot itself" so to speak, but as soon as
it jumps in jit.. its just a sort of blackbox.

> > PS.: placing a 'print I1' within the loop resolves the problem,
>
> That could clear g(0) ...

As said %g0 is just always 0, the only thing is that this one kind of "jumps
out of jit"?

>
> leo

Thanks,
Stephane

Leopold Toetsch

unread,
Feb 14, 2004, 8:35:02 AM2/14/04
to Stephane Peiry, perl6-i...@perl.org
Stephane Peiry <step...@modxml.org> wrote:
> whats a good way to debug jit?

s. docs/jit.pod /Debugging
docs/debug.pod /jit

> Thanks,
> Stephane

leo

Stephane Peiry

unread,
Feb 14, 2004, 10:31:26 AM2/14/04
to Leopold Toetsch, perl6-i...@perl.org
On Sat, Feb 14, 2004 at 02:35:02PM +0100, Leopold Toetsch wrote:
> docs/debug.pod /jit
saw that one, but jit doesn't generate a .o file under sparc?
Stéphane

Leopold Toetsch

unread,
Feb 14, 2004, 12:19:42 PM2/14/04
to Stephane Peiry, perl6-i...@perl.org

Calling Parrot_jit_debug() is enabled for __GNUC__ and __IBMC__. If your
system doesn't define one of these, try adding a define.

If that runs and it works you get a stabs file (for parrot -d -j). This is
compiled via an hardcoded line with "as". s. jit_debug.c

$ parrot -d -j t.imc
$ l *stabs*
-rw-r--r-- 1 lt users 8891 Feb 14 18:17 t.stabs.s

> Stéphane

leo

Stephane Peiry

unread,
Feb 15, 2004, 4:38:22 PM2/15/04
to Leopold Toetsch, perl6-i...@perl.org
On Sat, Feb 14, 2004 at 06:19:42PM +0100, Leopold Toetsch wrote:
> If that runs and it works you get a stabs file (for parrot -d -j). This is
> compiled via an hardcoded line with "as". s. jit_debug.c

mh ok, I do get the stabs file, and apparently the reason no objfile gets
created is that "as" complains with loads of warnings and some errors when
given the stab file.

Attached is an example stab file generated for a very simple pasm, and the
warnings/errors "as" complains about when feeded with it.. mainly hopping
that you can spot the problem? :)

> leo

Thanks,
Stéphane

set.pasm
set.stabs.s
set.pasm.debug.log

Leopold Toetsch

unread,
Feb 16, 2004, 3:08:55 AM2/16/04
to Stephane Peiry, perl6-i...@perl.org
Stephane Peiry <step...@modxml.org> wrote:

> mh ok, I do get the stabs file, and apparently the reason no objfile gets
> created is that "as" complains with loads of warnings and some errors when
> given the stab file.

I see. Your libc's sprintf seems to be missing the "0x" prefix for the
"%p" format. Can you verfy that with a small test:

$ cat p.c
#include <stdio.h>
int main(void) {
printf("main %p\n", main);
return 0;
}

$ cc -Wall p.c && ./a.out
main 0x8048400

I see two ways to work around that:

1) have a test for above case and double the lines in jit_debug.c that
use %p

#ifdef PARROT_LIBC_SPRINTF_P_IS_OK
... %p
else
... 0x%p
#endif

(a define for a specific $arch is fine in the first place)

2) use Parrot_sprintf and friends.

As this whole stuff is system dependend anyway I'd use 1) for now.

> .stabs "set.pasm",100,0,0,0
> .stabs "jit_func:F(0,1)",36,0,1,267f10

# line 2 - last item ought to be 0x267f10

leo

Stephane Peiry

unread,
Feb 21, 2004, 8:30:35 AM2/21/04
to Leopold Toetsch, perl6-i...@perl.org
On Mon, Feb 16, 2004 at 09:08:55AM +0100, Leopold Toetsch wrote:
> I see. Your libc's sprintf seems to be missing the "0x" prefix for the
> "%p" format.
Ok you were right, that fixed it immediatly, and I'm now able to
see "within jit" :). Attached are the dumps for this loop, with
and without the print in between.

Looking at it makes it pretty clear why it loops forever (mainly
it jumps back to a load, loading always the same value). Somehow
it relates to the way these "jit sections" are built afaik, but
still do have to dig more and understand better its works.

(if there are any hints/pointers, they are greatly appreciated ;)
Thanks again for the help,
Stephane

PS.: apoligize for the delay in answering back.

Also concerning fixing the debug part, I kind of prefer your second
option (using Parrot_sprintf) since as I understand it its meant
to avoid platform specific quirks?

loop.disassemble
loop.disassemble.print
set.disassemble

Leopold Toetsch

unread,
Feb 23, 2004, 5:07:48 AM2/23/04
to Stephane Peiry, perl6-i...@perl.org
Stephane Peiry wrote:

>
> Looking at it makes it pretty clear why it loops forever (mainly
> it jumps back to a load, loading always the same value).

Yep. That's a bit complicated. The jit code tries to avoid
loading/storing the same register from/to memory. This is achieved by
remembering the size of the register loads (load_size) and setting
fixup->skip accordingly.
When now a branch goes to the same section (a backward branch like in
mops.pasm), then the load should be skipped.

jit/i386/jit_emit.h implements all the necessary bits.
s. jit_emit_jcc, fixup->skip and load_size.

.
> Stephane

leo

Stephane Peiry

unread,
Feb 23, 2004, 4:04:22 PM2/23/04
to Leopold Toetsch, perl6-i...@perl.org
On Mon, Feb 23, 2004 at 11:07:48AM +0100, Leopold Toetsch wrote:
> Yep. That's a bit complicated. The jit code tries to avoid
> loading/storing the same register from/to memory.
Actually on this, while looking at what jit on i386 would give for this
particular loop, just noticed it does quite a lot of these store/loads to
memory who are, afaik, useless? (althaugh as I understand they are needed
for the general case)

0x0829c5ed <jit_func+53>: mov $0x2,%ebx
0x0829c5f2 <jit_func+58>: mov %esi,%esi
0x0829c5f4 <jit_func+60>: mov %ebx,0x8278c74
0x0829c5fa <jit_func+66>: mov 0x8278c74,%ebx
0x0829c600 <jit_func+72>: sub $0x1,%ebx
0x0829c606 <jit_func+78>: test %ebx,%ebx
0x0829c608 <jit_func+80>: jne 0x829c600 <jit_func+72>

(up here we could just skeep 58 to 66)

> jit/i386/jit_emit.h implements all the necessary bits.
> s. jit_emit_jcc, fixup->skip and load_size.

Thanks.. was going "round in loops" ;)
I'll go on it as time permits.

> leo

Stéphane

Leopold Toetsch

unread,
Feb 23, 2004, 4:31:28 PM2/23/04
to Stephane Peiry, perl6-i...@perl.org
Stephane Peiry <step...@modxml.org> wrote:
> On Mon, Feb 23, 2004 at 11:07:48AM +0100, Leopold Toetsch wrote:
>> Yep. That's a bit complicated. The jit code tries to avoid
>> loading/storing the same register from/to memory.
> Actually on this, while looking at what jit on i386 would give for this
> particular loop, just noticed it does quite a lot of these store/loads to
> memory who are, afaik, useless? (althaugh as I understand they are needed
> for the general case)

Yes. The problem are of course branches and branch targets. Before a
branch there is a store and on a branch target is a load (the register
assignment CPU-reg <-> Parrot-reg can and will differ in different basic
blocks).

So there may be unneeded store/load sequences. I tried (with some success)
to avoid such sequences with imcc/jit.c, but that is currently unusable
due to register renumbering with PCC.

> 0x0829c5ed <jit_func+53>: mov $0x2,%ebx
> 0x0829c5f2 <jit_func+58>: mov %esi,%esi
> 0x0829c5f4 <jit_func+60>: mov %ebx,0x8278c74
> 0x0829c5fa <jit_func+66>: mov 0x8278c74,%ebx
> 0x0829c600 <jit_func+72>: sub $0x1,%ebx
> 0x0829c606 <jit_func+78>: test %ebx,%ebx
> 0x0829c608 <jit_func+80>: jne 0x829c600 <jit_func+72>

> (up here we could just skeep 58 to 66)

No. mov %esi, %esi is a nop to align the branch target. And the load on
the branch target can't be omitted either (or only if you know that the
only brach comes from a place, where registers match. But - the loop
itself doesn't do any load/stores so that's fine.

> Stéphane

leo

0 new messages