Optimized code analysis problems

Hi all,

I am trying to do an analysis of a parallelized code using sse optimizations. The problem I am encountering is that I need to do some matching based on the analysis and I would like to extract the names of the functions as is rather than llvm intrinsics with an llvm. representation. Essentially I would like to extract the control flow graph representation with function names (eg. _mm_cvtsi32_si128) instead of the functions being replaced by ‘llvm.*’

Is there anyway to extract these names directly as function calls?

I have included the sample code below.

I get the function call names as llvm.x86 something instead of getting function names(eg. _mm_cvtsi32_si128)

#include <pmmintrin.h>

#include<sys/time.h>

#include

void foo_opt(unsigned char output[64], int Yc[64], int S_BITS)

{

__m128i XMM1, XMM2, XMM3, XMM4;

__m128i xmm1 = (__m128i)Yc;

__m128i XMM5 = _mm_cvtsi32_si128(S_BITS + 3) ;

XMM2 = _mm_set1_epi32(S_BITS + 2);

for (int l = 0; l < 8; l++) {

XMM1 = _mm_loadu_si128(xmm1++);

XMM3 = _mm_add_epi32(XMM1, XMM2);

XMM1 = _mm_cmplt_epi32(XMM1, _mm_setzero_si128());

XMM1 = _mm_srli_epi32(XMM1, 31);

XMM3 = _mm_sub_epi32(XMM3, XMM1);

XMM3 = _mm_srl_epi32(XMM3, XMM5);

XMM1 = _mm_loadu_si128(xmm1++);

XMM4 = _mm_add_epi32(XMM1, XMM2);

XMM1 = _mm_cmplt_epi32(XMM1, _mm_setzero_si128());

XMM1 = _mm_srli_epi32(XMM1, 31);

XMM4 = _mm_sub_epi32(XMM4, XMM1);

XMM4 = _mm_srl_epi32(XMM4, XMM5);

XMM3 = _mm_packs_epi32(XMM3, XMM4);

XMM3 = _mm_packus_epi16(XMM3, XMM3);

_mm_storel_epi64((__m128i*)(output+8*l), XMM3);

}

}

The names disappear in an unrecoverable way once the first inlining
pass runs to take care of always_inline. You might be able to hack
the code to sneak in before then, though.

-Eli

Hii,

Thanks for the response, yes I couldn’t find any way to extract the names through any of the passes.
Where could I potentially insert a hack so that any function call to intrinsic functions or library functions can be retrieved?
Could you gimme any ideas for the start?

-Nipun

Basically, there is no mapping from the llvm.* names to the _mm_*
names; the transformation is lossy.

You have a couple options here: one is to manipulate the source to let
you see the _mm_ names, and the other is to catch the _mm_ names
before the inliner runs.

Manipulating the source isn't actually very hard, although it's a
non-trivial amount of work; basically, you create your own xmmintrin.h
that doesn't have inline implementations, and mess with the include
paths so the compiler picks your version rather than the builtin
version. That way, once you transform to IL, the _mm_ calls will stay
as _mm_ calls.

If you're using the standard headers, the _mm_ function are defined as
inline functions, so at least in trunk LLVM builds, they exist in the
IL at some point. They're gone by the time llvm-gcc outputs the IL,
though, because the inliner unconditionally inlines them. So to get
the _mm_ names, you'll have to hack the llvm-gcc source to disable the
inlining pass.

-Eli

Hi Eli,

Well I think a way to hack it might be better for my purposes, can you suggest any ways of getting started on that and where.

Essentially I’m developing an IDE and need to extract the dependency graphs while retaining the actual function names rather than them being converted to llvm.* names. If I go for the other option you suggested. I’d have to do a one-to one mapping of all possible optimized function calls that could be made from different libraries imported by the user.

Thanks
Nipun

Assuming you're using llvm-gcc for the analysis, look for
NeedAlwaysInliner in llvm-backend.cpp.

On a side note, depending on what exactly you're doing, a source-level
analysis tool might be more convenient than LLVM; a couple
possibilities are Dehydra (https://developer.mozilla.org/en/Dehydra)
and clang (http://clang.llvm.org/).

-Eli