[m-rev.] for review: Re-factor the MR_join_and_continue macro.

Paul Bone pbone at csse.unimelb.edu.au
Tue Nov 24 10:51:26 AEDT 2009


On Mon, Nov 23, 2009 at 11:39:31PM +1100, Zoltan Somogyi wrote:
> On 23-Nov-2009, Paul Bone <pbone at csse.unimelb.edu.au> wrote:
> > compiler/par_conj_gen.m:
> >     Modified the generation of the join and continue code.  This now includes
> >     instructions for saving a pointer to the synchronization term into MR_r1,
> >     before calling MR_join_and_continue.
> >     Added an XXX: How to I tell the low-level backend that I will clobber MR_r1
> >     and MR_succip?  Could someone familiar with the low-level backend help me?
> 
> That kind of problem is what I meant when I said that implementing this as a
> call would be harder than fixing the macro.

Yes, I thought so.

> You shouldn't have to clear other needed values of r1; you should have
> *reserved* r1 earlier, before anything else gets put in it. Since you didn't,
> you can move the value in r1 to a stack slot, using the predicates in
> var_locn.m (which are well commented, and which are usually accessed through
> their wrapper predicates in code_info.m), but since what you want is
> effectively a call to a builtin predicate, you should instead either (a)
> implement the call as a HLDS-to-HLDS transform in an earlier compiler pass,
> or (b) use the infrastructure that already exists in call_gen.m to generate
> the code for the call at code generation time. (a) seems to me to be
> preferable.

I like the HLDS to HLDS idea as it keeps the backend simple (and is backend
independent).  Although, the HLDS works on a representation of a logic program,
therefore a whole parallel conjunction would have to be transformed into
something else.  I'm not sure what that 'something else' should be since I don't
think we have any HLDS structures that can represent the execution flow of a
parallel conjunction.

Doing this at a HLDS to LLDS stage therefore seems better. But I'm not sure
that an LLDS call instruction is considered to have the right operational
semantics.  If join_and_continue is a call then the join label can be assumed
to be a continuation label.  But not very call to MR_join_and_continue will
return (jump to the join label) only the last to be executed in the conjunction
(not necessary the rightmost conjunct).  The LLDS call instruction might still
be suitable, but it's not an ideal match.

The other benefit of doing this at code generation time will be that it will
be easier to implement parallel conjunctions for the high level C backend by
using blocks and GCD.

I'm beginning to wonder if it would be best to write MR_join_and_continue as a
C function and use a macro that wraps it to avoid the stack leak as follows:

extern MR_Code *MR_do_join_and_continue(MR_SyncTerm *sync_term); 

#define MR_join_and_continue(sync_term, join_label) \
    do { \
        MR_Code *jump_target; \
        jump_target = MR_do_join_and_continue(sync_term); \
        if (jump_target) { \
            MR_GOTO(jump_target); \
        } else { \
            MR_GOTO(join_label); \
        } \
    }

Well, this already looks remarkably simple in comparison!  It also avoids a
computed GOTO when it should jump to the join label (at the cost of the
if-then-else).


-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 489 bytes
Desc: Digital signature
URL: <http://lists.mercurylang.org/archives/reviews/attachments/20091124/18134418/attachment.sig>


More information about the reviews mailing list