FWIW I actually did this work twice, once for libjit and once for
LLVM. I'm happy to provide a comparison, from a jit-writing
perspective, if you're interested.
> Given your experience with both, I'd be very interested in any
> thoughts you have on how we can make LLVM better. 
Nice writeup, thanks for taking the time to do it.
libjit has a few advantages over LLVM in terms of the "gloss" -- how
it is packaged, JIT development using it:
* The API documentation is better.
libjit's documentation is not perfectly complete, but for my
purposes it was generally more complete and better organized than
LLVM's. With LLVM I ended up reading the header files to figure
everything out; with libjit I didn't.
Also libjit uses texinfo... sometimes I think I'm the last remaining
person who likes using info in Emacs, but this did make my life
simpler, so I thought I'd mention it. (Obviously this is a
subjective thing.. can you tell I'm defensive about it? 
Not to belabor this too much, but I've always found doxygen output
borderline unreadable... libjit also does comment extraction from
the source for its documentation, but puts it into a more-or-less
nicely structured context.
Understood. It certainly would be nice to have a "how to use the JIT" document that is concise and targetted for this. Also, unfortunately, most of the docs for the LLVM API are still in the headers, which sucks. 
Perhaps after the release I can help improve this situation.
* libjit is a lot smaller. Of course this is both a plus and a minus
(in the sense that small usually means things are missing).
However, in terms of development productivity, libjit is a win here:
a rebuild and relink of my libjit-based code takes under a minute.
I think it takes 20 minutes or more to link my LLVM-based JIT on my
laptop.
Are you using a debug or a release build? A release build (built with make ENABLE_OPTIMIZED=1) is often 10x to 20x smaller than a debug build, and links correspondingly faster. On some machines, a release build builds *faster* than a debug build because the debug symbols are so huge. The only thing you lose with a release build is the ability to step into LLVM libraries in a debugger.
* Likewise, libjit installs very simply: it is a couple of shared
libraries (one for the library and an extra one containing the C++
API). At least with the default install, LLVM is a weird (to me)
mix of static libraries and object files.
llvm-config saved the day here, in terms of the Makefile
hacking.
Yup, go llvm-config! 
I only saw today in the mail archives that there is a way to build
LLVM as shared libraries -- I haven't tried it yet, so apologies if
this is just my ignorance.
I'd suggest sticking with llvm-config and not using shared libraries.
* One oddity with LLVM came because a BasicBlock is a Value. I passed
it as the wrong argument to an AllocaInst constructor... oops.
(libjit's API is much simpler ... no names for instructions, new
instructions are implicitly linked into the current block, etc.
This has both plusses and minuses. I did wonder how much it costs
to have names everywhere...)
Instruction/BB names are completely optional (you can pass in "" for everything, and everything will still work fine) but are quite handy when trying to read the LLVM code.
It would be straight-forward to add a new "easy" interface for creating LLVM instructions. Would something like this work well for you?
class InstructionCreator {
BasicBlock *CurBB;
public:
void setCurrentBlock(BasicBlock *);
Value *createAdd(Value *LHS, Value *RHS, const std::string &Name = "");
Value *createSub(Value *LHS, Value *RHS, const std::string &Name = "");
...
};
Given this, use would be much more implicit:
InstructionCreator IC;
IC.setBasicBlock(FalseBB);
Value *A = IC.createAdd(LHS, RHS);
Value *B = IC.createSetEQ(A, RHS);
IC.createBr(B, TrueBB, FalseBB);
IC.setBasicBlock(TrueBB);
...
if so, I can add this. Do you have a suggestion for a name better than "InstructionCreator"?
I think libjit only has one technical idea that is missing from LLVM.
In libjit you can create a new function and get a pointer to it, but
set things up so that the IR for the function is also created lazily.
As I understand it, right now in LLVM you can make the IR and lazily
compile it, but not lazily make the IR. This seems pretty handy, at
least for my situation. It also looks pretty easy to add to LLVM 
Yup, it would be great to have this. 
I don't want to get you down or anything.
Heh, no problem. If we couldn't admit that improvement is possible, we probably wouldn't improve. 
-Chris