I've been working on a draft of a Trilangle compiler using LLVM. Out of curiosity, I took the generated IR (given the Trilangle program ?!oi@) and plugged it into Godbolt, and this is what I see for main:

main:                                   # @main
        sub     rsp, 24
        mov     rdi, rsp
        call    _stack_ctor
        mov     rdi, rsp
        call    _get_int
        mov     rdi, rsp
        call    _print_int
        mov     rdi, rsp
        call    _get_unichar
        mov     rdi, rsp
        call    _print_unichar
        mov     rdi, rsp
        call    _stack_dtor
        xor     eax, eax
        add     rsp, 24

Nothing I do seems to inline any of that. _stack_dtor is the most egregious, because its implementation is just

inline void _stack_dtor(stack* self) {

As can be confirmed by the assembly:

_stack_dtor:                            # @_stack_dtor
        mov     rdi, qword ptr [rdi]
        jmp     free@PLT                        # TAILCALL

Some things I have tried that seem to not work, at least in Godbolt:

  • Setting -inline-threshold and/or -inlinehint-threshold to a very high or very low value
  • Replacing the inlinehint attribute with alwaysinline or alwaysinline "nooutline"
  • Specifying an optimization level in the flags, e.g. -O3
  • Removing comdat specifiers
  • Changing the functions from linkonce_odr dsolocal to private
  • Marking the functions hot

All of these seem to produce the same assembly (though private changes the label name): https://godbolt.org/z/hxj15dMnW

How do I make LLVM inline anything?

  • $\begingroup$ Interesting... I suspected that _stack_dtor cannot be inlined because it jmps to free@PLT by tail call (in my view, inlining it requires that the call to _stack_dtor must be a tail call too, which is not satisfied in the call site). But changing it (tail call to simply call) and giving opt levels didn't work either. $\endgroup$
    – Bubbler
    Jun 15, 2023 at 2:34
  • $\begingroup$ I'll also note that _stack_ctor tail calls calloc, but the emitted assembly definitely doesn't have a tail call there. Similarly, _stack_pop, tail calls llvm.assume, which doesn't make any sense if interpreted literally. $\endgroup$
    – Bbrk24
    Jun 15, 2023 at 2:37
  • $\begingroup$ Have you tried running opt manually with inline and always_inline passes? Also, mark the functions as always_inline. $\endgroup$
    – SK-logic
    Jun 15, 2023 at 8:29
  • $\begingroup$ @SK-logic Admittedly no, but I'm not even sure I have that installed, given that I only have clang and not a standalone llc on my machine. Clang can still compile and link LLVM IR, so I haven't had any major problems with that. $\endgroup$
    – Bbrk24
    Jun 15, 2023 at 12:50
  • $\begingroup$ how do you produce LLVM IR then if you don't have the libraries? $\endgroup$
    – SK-logic
    Jun 15, 2023 at 13:35

1 Answer 1


Use clang instead of llc

Clang can handle LLVM IR files, though you may need to use the -xir flag for it to recognize them as such. When using clang, any optimization level besides -O0 causes inlining to occur: https://godbolt.org/z/6PvGezPsP

I'm still unsure as to why llc doesn't inline anything, but at least this serves as a workaround.


You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .