Hi Basile,

But I don't understand how Ggc could be avoided (and I am not sure to
understand how even LLVM can avoid any kind of garbage collection in the
long run).

I doubt LLVM will ever need garbage collection, because the way it is designed
makes memory management easy.  I already mentioned the use of containers, but
of course containers can't handle everything.  So consider a typical thing you
might want to do: replace an instruction I1 by a different one I2 (for example
because you understood that I1 simplifies to the simpler instruction I2) and
delete I1.  You can think of an LLVM instruction as being a gimple
statement.  One of the design points of LLVM is that instructions always know
about all users of the instruction (def-use chains are built in).  Thus you
can do
  I1->replaceAllUsesWith(I2);
and at this point everything using I1 as an operand now uses I2 instead.  Thus
the only place still referring to I1 is the function that the instruction I1
is linked into.  You can unlink it and free the memory for I1 as follows
  I1->eraseFromParent();
And that's it.  The price you pay for this simplicity is the need to keep track
of uses - and this does cost compilation time (clear to anyone who does some
profiling of LLVM) but it isn't that big.  The big advantage is that memory
management is easy - so easy that I suspect many LLVM users never thought
about the design choices (and trade-offs) that make it possible.

Ciao, Duncan.

PS: You may wonder about copies of I1 cached in a map or whatnot, where it can
be tricky (eg breaks an abstraction) or expensive to flush I1 from the data
structure.  This situation is handled conveniently by an extension of the above
mechanism where in essence your copy of I1 in the data structure can register
itself as an additional user of I1.  When I1 is replaced by I2 then (according
to how you chose to set things up) either the copy in the data structure gets
turned into I2, or nulled out, or a special action of your choice is performed.

Reply via email to