inside the GHC code generator

Bulat Ziganshin bulat.ziganshin at gmail.com
Fri Feb 24 04:09:12 EST 2006


Hello Jean-Philippe,

Friday, February 24, 2006, 2:04:57 AM, you wrote:

JPB> From my (limited) knowledge of GHC backend, the difficult part of your
JPB> plan is that STG is not suited to compilation to native C at all. You
JPB> might need to do quite advanced translation from STG to another
JPB> intemediate language, (as GRIN for example), and then some more
JPB> advanced analysis/optimization before C can be generated.

your knowledge is very limited, because STG at all times was compiled
to C and then compiled by gcc :)  moreover, it's very easy to
implement efficient compilation of fac() definition from STG to
"natural C". it's one-hour task, maximum. the real problem is changing
the whole environment, including AST representing C code inside the GHC,
RTS and so on

JPB> iirc, the tricky part is the handling of lazyness. At any point you
JPB> may end up with a thunk (closure), which ghc handles easily by
JPB> "evaluating" it: it's always a function pointer. (That's the tagless
JPB> part) When in WHNF, it just calls a very simple function that fills
JPB> registers with the evaluated data. Otherwise, the function call
JPB> performs the reduction to WHNF.

STG attaches explicit typing information to any var. i propose:

1) compile code that works with unboxed values to equivalent "natural
C" code
2) for the boxed values, MAXIMALLY simplify test that they are already
in WHNF. current solution leads to two jumps, what is a very expensive
on modern cpus. i propose to make instead one check and one
conditional jump what will be much cheaper. then, if value is in WHNF,
we just load all the needed data himself. if it is not in WHNF, we
perform just the same operations as in current GHC. for example,
wrapper that calls the "int fac(int n, int r)" worker, can be
something like this:

if (p = n->closure) then goto eval_n;
n_evaluated:
if (p = r->closure) then goto eval_r;
r_evaluated:
return fac (n->value, r->value);

eval_n:
(*p) (); // sets n->closure=NULL; n->value to n's value
goto n_evaluated;

eval_r:
(*p) ();
goto r_evaluated;

JPB> If you want to use the same trick, you'll end up with the same
JPB> problems (bad C). So, you'll want to eliminate thunks statically,
JPB> finally requiring a 'high level' analysis as I suggested above.

really? :)

JPB> Also, allocation + garbage collection is extremely efficient in
JPB> current GHC... C/C++ alloc doesn't even come close. It's entirely
JPB> possible that with even a very fast backend, the better ghc allocator
JPB> will be enough to swing the balance. (see jhc)
JPB> It might be possible to re-use most of it however.

i don't propose to replace everything in ghc backend, just the way
"unboxed" code is compiled and something around it. i just don't know
enough about other parts of ghc backend/rts :)))

-- 
Best regards,
 Bulat                            mailto:Bulat.Ziganshin at gmail.com



More information about the Glasgow-haskell-users mailing list