Preserving Call to Intrinsic function

Hello everyone,

Consider we have this following set of code:

int foo() {

int a,b;

a = __builtin_XX(0x11);

b = __builtin_XX(0x11);

return a+b;
}

The problem currently is that LLVM eliminated the second call and copied the result from the first call into a new set of registers. Is there is a way to force LLVM to generate two explicit calls to a builtin function. The builtin takes in an integer type, and also returns back an integer type:

def int_XX : GCCBuiltin<“__builtin_XX”>, Intrinsic<[llvm_i32_ty], [llvm_i32_ty]>;

Is there some flag that I’m missing? Your help will be really appreciated.

Hi Kumail,

There is a flag that does what you are looking for (see Intrinsics.td for definitions):

// IntrNoduplicate - Calls to this intrinsic cannot be duplicated.
// Parallels the noduplicate attribute on LLVM IR functions.
def IntrNoDuplicate : IntrinsicProperty;

Another thing to check is whether your intrinsic is marked as having side-effects or not. Intrinsics with no side effects may be optimized by LLVM. If you inspect the DAG using llc, an intrinsic with side-effects should have a chain (blue dashed edge) going to and coming from its node:

llc -O1 foo.ll -view-isel-dags

If it doesn’t, you can mark it as having side-effects using one of the following attributes:

// IntrReadMem - This intrinsic only reads from memory. It does not write to
// memory and has no other side effects. Therefore, it cannot be moved across
// potentially aliasing stores. However, it can be reordered otherwise and can
// be deleted if dead.
def IntrReadMem : IntrinsicProperty;

// IntrWriteMem - This intrinsic only writes to memory, but does not read from
// memory, and has no other side effects. This means dead stores before calls
// to this intrinsics may be removed.
def IntrWriteMem : IntrinsicProperty;

By default intrinsics returning void are assumed to have side effects.

Pierre-Andre

Hi Pierre,

Thank you for your swift response!

I’ve tried almost everything that you mentioned, but it seems like LLVM simply doesn’t care about the flags I pass to it.

Best regards,

Kumail Ahmed

Hi Kumail,

That’s strange.

When you are generating the .ll file from clang, do you have two intrinsic calls in the IR?

If that’s the case, I’d run llc with -print-after-all to identify which LLVM pass removes the second call, and then debug the pass to see what is going on.

Pierre-Andre