IR function pointers

I am coming up against a lot of function pointers in the IR, although the corresponding source code does not have indirect calls.

For example: call void %1608(%"struct.LRT::RGBAucharFrameBuffer"* %1604)

How can I resolve the targets of these? Also, why are they appearing as indirect calls in the IR, when they are direct calls in the source?

Thanks.
-Apala

Hi,

For example: call void %1608(%“struct.LRT::RGBAucharFrameBuffer”*
%1604)

How can I resolve the targets of these? Also, why are they appearing as
indirect calls in the IR, when they are direct calls in the source?

You don’t mention what language you’re trying to compile, though it looks plausibly C++. I’d guess these are virtual function calls. In general you can’t tell which actual function will be called at compile-time, since it will depend on the precise class of the object being used.

LLVM can unpick some of this (the optimistions go under the generic term of “devirtualisation”), but obviously not all.

If you as a reader just want to know what function’s being called in broad terms, I’d look at where that %1608 comes from: likely loaded from an offset in the vtable, stored in %1604. Very roughly for Unixy ABIs (and loosely typed):

%vtable = load i8** %1604
%fptr = getelementptr %vtable, NNN
%1608 = load %fptr

Work out where that NNN offset actually is and then look at RGBAucharFrameBuffer’s vtable definition (the global symbol @_ZTV3LRT20RGBAucharFrameBuffer, I believe: the _ZTV is the important bit) and see which function is put in that offset. Unfortunately, it’s all rather complicated and the vtable may not even be defined in the file you’re compiling.

Why are these calls bothering you? It’s possible there are better options for your use-case.

Tim.

Hi Tim,

This is C++ indeed. Basically, I am profiling the code. So, these edges that cannot be resolved at compile time present a problem.

Where can I find these devirtualization optimizations that you mentioned?

Thanks.
-Apala

We have some out-of-tree improvements to the profiling that makes it possible to build a complete call graph for programs that use function pointers. I intend to push these upstream soon, they just need a bit of tidying first.

David

Hi Apala,

Where can I find these devirtualization optimizations that you mentioned?

I believe it’s a little spread around. Clang can do some bits intentionally (see lib/CodeGen/CGClass.cpp, if it hasn’t been renamed). But other parts come from combinations of other perfectly routine optimisations that LLVM does on its IR (inlining, constant propagation, …).

Tim.