Rewriting LLVM IR intrinsic functions


I can see the occurrences of several LLVM intrinsic functions in the LLVM IR generated by llvm-dis disassembler. Is there any means to rewrite these functions reliably using basic LLVM IR statements?

You can use `LowerIntrinsicCall` from "llvm/CodeGen/IntrinsicLowering.h"
to do so.

It doesn't seem to be designed to be called from a pass, but with a few
checks it does the job right.

This will lower intrinsics to (target-specific) function calls that implement the underlying functionality, which is almost certainly not what you want to do.

The question doesn’t really make sense. Intrinsics *are* ‘basic LLVM IR statements’. The distinction between things that are intrinsics and things that are instructions is quite fuzzy. Many intrinsics are intended to be operations that map to a single instruction on (at least some) targets and are all things that are not (or, at least, not easily) representable with LLVM IR instructions.

To answer your question properly, it would help to understand what you’re actually trying to do.


Hi David,

I think you people can help me better if I explain what I am trying to achieve.

  1. I have compiled gmp with LLVM 2.9

  2. Linked the library statically with a stub program (gmp_demo.bc)

  3. Transformed the bitcode to LLVM IR: llvm-dis gmp_demo.bc -o gmp_demo.ll

  4. Trying to convert the IR to high-level C code: llc -march=c gmp_demo.ll
    Though I know that llc C backend has many issues and has been removed from LLVM >=3.1, still I am desperate to make it work. The error I receive in the last step is the following: “LLVM ERROR: Code generator does not support intrinsic function ‘llvm.uadd.with.overflow.i64’!”

I was planning to rewrite LLVM intrinsics not supported by llc to equivalent LLVM IR supported by llc. Is this approach feasible?

It would still help to understand exactly why you’re trying to do this. It sounds as if you’re using LLVM as a source-to-source translator, with C as the input and output language. If this is the case, then the Clang rewriter infrastructure might be more useful to you.

The intrinsic that it is currently failing on is (as its name implies) an overflow-checked addition. The reason that the C backed does not understand this builtin is simple: There is no way of (directly) expressing this in C, without extensions.

You could potentially expand this in IR to a signed addition and a check that the sign bit had not changed, but it would be cleaner to simply modify the C backend to emit the Clang / GCC __builtin function that corresponds to the intrinsic. You’re likely to find a number of other intrinsics that are not supported: the reason that the C backend was removed was that it never worked very well. For example, anything involving exceptions can’t be implemented in C, so the C backend lowers it to setjmp / longjmp, which gives you a different ABI.


Hi David,

If you convert from binary to LLVM IR, then from LLVM IR to source code, the source code that you get out will look nothing like the original, so there is no chance that your changes would be useful when applied to the original sources. This sort of transformation would be better done in the LLVM IR (a representation designed for transformation), rather than in generated source code (a representation designed for human editing).