Enabling inlining

My language is producing a lot of very short functions, typically two or
three instructions long. These should be ideal candidates for inlining,
but it isn't happening.

My compiler is producing one big bitcode file, and all the functions are
marked as 'internal'. I'm then doing the optimisation and translation
manually using llc -O3 into a .s file, and then linking this against the
runtime using gcc.

I see that llvm-ld supports an inlining pass; is this the *only* place
it happens? i.e. do I need to run llvm-ld on my bitcode file before
translation? If not, is there anything specifically I need to do in the
compiler to make inlining happen?

My language is producing a lot of very short functions, typically two or
three instructions long. These should be ideal candidates for inlining,
but it isn't happening.

My compiler is producing one big bitcode file, and all the functions are
marked as 'internal'. I'm then doing the optimisation and translation
manually using llc -O3 into a .s file, and then linking this against the
runtime using gcc.

Are you running 'opt' on your bitcode or otherwise manually running those passes?

[...]

Are you running 'opt' on your bitcode or otherwise manually running those passes?

Aha. After running opt I now have inlined (and much better) code.
Previously I'd been using llc -O3 to do the optimisation.

What's the different between opt -O3 and llc -O3, then?

They are different programs. opt transforms llvm IR to llvm IR, doing (largely) target independent optimizations along the way. llc transforms llvm IR to a .s or, for some targets, .o file, doing (largely) target dependent optimizations.

[...]

Are you running 'opt' on your bitcode or otherwise manually running those passes?

Aha. After running opt I now have inlined (and much better) code.
Previously I'd been using llc -O3 to do the optimisation.

Glad to hear you're having better results!

What's the different between opt -O3 and llc -O3, then?

At the risk of a somewhat circular answer, they run different sets of passes. For best results, you want both.

More specifically, 'opt' runs target-independent IR optimizations and outputs back to LLVM IR, while llc runs (mostly) lower-level target-dependent optimizations, many of which operate at the machine instruction level rather than the IR level, and outputs the machine assembly code.

If you want more gory details of what's run in each, add "-debug-pass=Executions" to the command lines for them and they'll tell you which passes are being executed.

Regards,

-Jim