Debug Info and MergeFunctions Transform

Hi Stepan,

After discovering several bugs in ArgumentPromotion and DeadArgumentElimination where llvm::Functions were replaced with similar functions (with the same name) to transform their type in some way, I started looking at all calls to llvm::Function::takeName to see if there were any other debug info quality bugs in similar callers.

One such caller is MergeFunctions, and I don’t see any debug info tests for this so I’m wondering what /should/ happen here.

In the case where the functions are internal I’m not sure there’s anything we can do, we simply remove one function and keep the other - the debug info can only be ascribed to one of the two and this probably comes out naturally (whichever name we choose to keep). I don’t think we can have the debug info for one function reference a global alias, while the debug info for another function references the thing that alias refers to. So be it.

But in the case of MergeFunctions::writeThunk we can probably do better - by updating the debug info for the thunk’d function so we at least describe this trivial function in the debug info.

Does that sound about right?

Could you provide any C/C++ source examples where MergeFunctions fires fairly reliably so I could play around with the debug info behavior (& fixes) here?

Thanks,

  • David

Hi David,
Thanks for attention to MergeFunctions! I have read your mail briefly, tomorrow I'll provide you with detailed information. By now you could use tests from $LLVM/test/Transforms/MergeFunc/ as examples.

Cheers!
-Stepan

David Blaikie wrote:

Hi David,

After merging we always remove body of "G" (function we want to merge with "existing" one).
In case with "writeThunk" we could add such info for "G", but it would be just a single string: reference to first string of "G".

Ideal way here, is to merge debug information itself, and provide "F" with information for "G" and "F", but I think it's unreal :frowning: Since debugger should check function name it entered, and then filter such debug information with this name. Though I'm not that familiar with Debug Info, perhaps there are still possible ways to provide single body with two debug infos.

-Stepan

Hi David,

After merging we always remove body of "G" (function we want to merge with
"existing" one).
In case with "writeThunk" we could add such info for "G", but it would be
just a single string: reference to first string of "G".

I don't think that's completely unreasonable - actually it's probably about
the most right thing we can do (in this way the user would've seen "caller
-> G -> etc... " and will now see "caller -> G -> F -> etc..." which might
be a bit confusing, but that's the nature of optimization, really).

Do you have a small C++/clang example of function merging firing, and using
a thunk?

Ideal way here, is to merge debug information itself, and provide "F" with
information for "G" and "F", but I think it's unreal :frowning: Since debugger
should check function name it entered, and then filter such debug
information with this name. Though I'm not that familiar with Debug Info,
perhaps there are still possible ways to provide single body with two debug
infos.

Yeah, I suspect we'd confuse debug info consumers if we produced two
function descriptions describing the same function... for a bunch of
reasons (& adding the plumbing to do that in LLVM's debug info emission
wouldn't be easy either) so I'll probably leave that alone for now.

- David

Hi David.

You could follow simple rule: void* is equal to i64 on x86_64 machines.

This one works:


#include <stdio.h>

void foo0(unsigned long p0) {
printf("p0 = 0x%x\n", p0);
}

void foo1(void* p0) {
printf("p0 = 0x%x\n", p0);
}

int main() {
foo0(123);
foo1((void*)456);
return 0;
}

// How to build:
// step1: clang -emit-llvm -c -o test.bc test.c
// step2: opt -mergefunc test.bc -o test.mf.bc
// step3: llc test.mf.bc -o test.s
// step4: clang test.s
// step5: ./a.out

// On step #1 you could use -S, and get human readable files
// On step #2 you also could use -stats, and see -mergefunc statistics
// On step #4 you could use any other compatible assembler instead of clang (e.g. gcc)

Good luck!

  • Stepan