[llvm] [DwarfDebug] Associate subprogram DIEs with their Functions (PR #162852)

Vladislav Dzhidzhoev via llvm-commits llvm-commits at lists.llvm.org
Sat Oct 11 03:36:47 PDT 2025


dzhidzhoev wrote:

> So... I /think/ the original conversations were maybe of the form "we picked the function from one LTO input, but the class from another - and now they don't match" - are there actually cases where we pick /both/ functions (two functions survive LTO that both refer to conceptually the same DISubprogram?)? It sounds like that's what you're proposing supporting - and I'm not sure if that was discussed (if you've got pointers to prior discussions on this, please link it so I can catch back up -sorry for rehashing all this - the timelines are very long & it's hard to keep track of it all :/ ) - it'd be nice if we could avoid the complexity of that if possible.

Hmm, we haven't explicitly discussed the case when two functions survive LTO and get their DISubprograms merged, but I think it may happen. If it's not a concern, I'll be glad to skip these patches :)

If we consider a case when there is a header unique-type.h:
```c++
#pragma once
__attribute__((noinline))
static int bar(int x, int y) {
  return x + y;
}
```

and there are source files unique-type1.cpp:
```c++
#include "unique-type.h"
int bar1(int a, int b) {
  return bar(a, b);
}
```
and unique-type2.cpp:
```c++
#include "unique-type.h"
int bar2(int a, int b) {
  return bar(a, b);
}
```

After applying:
```zsh
clang unique-type1.cpp -o unique-type1.bc -flto=full -c -g -fstandalone-debug -O0
clang unique-type2.cpp -o unique-type2.bc -flto=full -c -g -fstandalone-debug -O0
llvm-link unique-type1.bc unique-type2.bc -o unique-type.bc -d -v
opt unique-type.bc -o unique-type.opt.bc --passes=mergefunc
```

unique-type.bc will contain two functions:
```llvm
define internal noundef i32 @_ZL3barii(i32 noundef %x, i32 noundef %y) #1 !dbg !24 {
...
}

define internal noundef i32 @_ZL3barii.1(i32 noundef %x, i32 noundef %y) #1 !dbg !43 {
...
}

!24 = distinct !DISubprogram(name: "bar", linkageName: "_ZL3barii", scope: !25, file: !25, line: 3, type: !12, scopeLine: 3, flags: DIFlagPrototyped, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition, unit: !0, retainedNodes: !15)
!43 = distinct !DISubprogram(name: "bar", linkageName: "_ZL3barii", scope: !25, file: !25, line: 3, type: !12, scopeLine: 3, flags: DIFlagPrototyped, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition, unit: !2, retainedNodes: !15)
```

After opt, they will indeed be merged. Should AsmPrinter rely on that?

Also, this example can be modified to prevent function merge: if unique-type1.cpp is compiled with -O0 (for any reason), and unique-type2.cpp is compiled with -O2, function merge doesn't happen, and in the resulting binary we have:
```zsh
$ clang -flto=full unique-type1.bc unique-type2.bc -g -o unique-type.dylib -dynamiclib -fstandalone-debug -v
$ objdump -t unique-type.dylib
...
0000000000000304      d  *UND* __ZL3barii
...
0000000000000328      d  *UND* __ZL3barii.1
...
```

https://github.com/llvm/llvm-project/pull/162852


More information about the llvm-commits mailing list