[m-users.] That parallel low-level C bug

Volker Wysk post at volker-wysk.de
Mon Sep 14 22:36:53 AEST 2026


Am Montag, dem 14.09.2026 um 13:10 +0200 schrieb Zoltan Somogyi:
> > Since no "asm_fast.par" grades are available, you need to compile in a
> > high level C grade instead. But some programs need the tail recursion
> > optimization, which isn't available there.
> 
> Yes, it is. For about a decade, tail recursion optimization has been
> almost as good in high level C grades as in low level C grades.
> For most purposes, though not all, they are just as good.

Somewhere I've got the notion that there's no TRO in high level C grades...
I think I read it here on the list. Maybe I've misinterpreted something.

>  
> > When I try to compile in a high-level C grade, doing this:
> > 
> > :- pragma require_tail_recursion(master_loop_normal/12,
> >     [error, in_all_grades]).
> > 
> > ... then I get:
> > 
> > mfwpar.m:1044: Error in predicate `master_loop_abort'/12:
> > mfwpar.m:1044:   this self-recursive call is not tail recursive.
> 
> The differences between low and high level C's ability to do
> tail recursion involve *mutual* recursion. If a self-recursive call
> is not tail recursive in a hlc grade, it won't be tail recursive
> in a low level C grade either, UNLESS some other grade component
> prevents ALL tail recursion.
> 
> I am pretty sure that there is some computation in the code
> of master_loop_abort that takes as input some result of the call
> on line 1044, and therefore must be done after that call.

There indeed is something done after one call of master_loop_abort, in the
generated hlc code. But I don't understand, what. The abbreviated code
follows. I can't see anything being done there in the Mercury code:

-----snip-----
:- pred master_loop_abort(
    par_bits(MasterCustomMsg, FeederCustomMsg, WorkerCustomMsg)::in,

    master_finish(MasterCustomMsg, FeederCustomMsg, WorkerCustomMsg, 
                  MasterData, Result)
    ::in(master_finish),

    % Number of running worker threads
    int::in, int::out,

    % If the feeder has exited
    bool::in, bool::out,

    % Custom data that's being maintained inside the master loop.
    MasterData::in, MasterData::out,

    % The exception which is being treated.
    Exc::in,

    io::di, io::uo
) is erroneous.

master_loop_abort(
    ParBits, Finish, 
    !NumWorkers, !FeederExited, !MasterData,
    Exc,
    !IO
) :-
    ...
    (
        if
            ...
        then
            ...
            throw(Exc)
        else
            ...
            master_loop_abort(         % <== HERE
                ParBits, Finish,
                !NumWorkers, !FeederExited, !MasterData,
                Exc, !IO
            )
    ).
-----snip-----

And moving the recursive call out of the else branch, doesn't make it tail
recursive as well. 


> > And here, please add "in the current grade" to the message.
> 
> The test for tail recursion is always specific to the current grade.
> It would be expensive to repeat the test in any other grade,
> and your proposed message extension could be misleading
> without the compiler knowing that the result *can be different*
> in a different grade.

okay.

> > I'm wondering how bad the lack of tail recursion optimization in hlc
> > grades is.
> 
> Not bad at all.
> 
> > Is there only a constant amount of stack space available?
> > Won't it grow automatically? I can't see any hlc grade with ".stseg".
> > We have multi-gigabytes of RAM nowadays, so if the stack would grow as
> > needed, it might still work.
> 
> The whole point of high level C grades is that they generate *normal*
> C code, which means that the C compiler is in charge of managing the
> stack.
> All of your questions have the same answers as if you asked the
> implementor
> of the C compiler: stack space can and will grow dynamically as needed,
> until you run the whole computer out of memory and swap space.

Seems like I jumped to conclusions.

> 
> > Is the fixing of the problem in process?
> 
> There is no problem of "finite stack space in hlc grades"  to fix.

I mean the problem that the compiled program crashes or has weird errors in
some Linux distributions, while it works in others. That is, when it is
compiled in a parallel low-level C grade with an earlier version of the
compiler, which doesn't abort with an error message.

Volker


More information about the users mailing list