Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Missing line information after SROA pass at Og #49630

Open
cristianassaiante mannequin opened this issue May 10, 2021 · 4 comments
Open

Missing line information after SROA pass at Og #49630

cristianassaiante mannequin opened this issue May 10, 2021 · 4 comments
Labels
bugzilla Issues migrated from bugzilla confirmed Verified by a second party debuginfo

Comments

@cristianassaiante
Copy link
Mannequin

cristianassaiante mannequin commented May 10, 2021

Bugzilla Link 50286
Version trunk
OS Linux
Blocks #30616 #38116
CC @JDevlieghere,@jmorse,@jdm,@walkerkd,@OCHyams,@pogo59

Extended Description

The last assignment to a variable passed to an external function is not reached in debugging.
If we set a breakpoint on line 11, with a next operation we will end up on line 15, thus skipping line 14 where the last assignment is done.
From opt-bisect, the pass after which the line is not reached anymore is: SROA pass.

Beside this, upon calling the external function, the variable v_0 appears to be not available in lldb but we should see that its value is the same as v_1 from its last assignment.

From both asm and IR, we can see that after SROA pass the first two parameters to test_out are the same variable/register:
ASM ----------
400533: 89 df mov %ebx,%edi
400535: 89 de mov %ebx,%esi
400537: 89 ea mov %ebp,%edx
400539: e8 a2 ff ff ff callq 4004e0 <test_out>

IR -------------
call void @​test_out(i32 %6, i32 %6, i32 %3, i32 %10) #​3, !dbg !​26

Could it be possible to map this parameter passing to the last assignment line?

$ cat a.c
int test_in();
void test_out(int v_0, int v_1, int v_2, int v_3);

int main()
{
int v_0, v_1, v_2, v_3;
v_0 = test_in();
v_1 = test_in();
v_2 = test_in();
v_3 = test_in();
v_1 = (v_2 * ~(~v_0 + v_3));
v_0 = (v_2 >> (v_3 < (v_0 < v_1)));
v_0 = (v_2 * v_3);
v_0 = v_1;
v_3 = ((v_1 & (v_2 & v_3)) < v_0);
test_out(v_0, v_1, v_2, v_3);

return 0;

}

$ cat lib/test.c
#include <stdio.h>

int ctr = 0;

int test_in() {
return ctr++;
}

void test_out(int v_0, int v_1, int v_2, int v_3) {
printf("%d%d%d%d", v_0, v_1, v_2, v_3);
}

$ clang -v
clang version 13.0.0
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /usr/local/bin
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/7
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/7.5.0
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/8
Selected GCC installation: /usr/lib/gcc/x86_64-linux-gnu/7.5.0
Candidate multilib: .;@m64
Selected multilib: .;@m64

$ lldb -v
lldb version 13.0.0

clang revision c2c977c
lldb revision c2c977c

$ clang -g -Og -o opt lib/test.c a.c
$ lldb opt
(lldb) target create "opt"
Current executable set to '/home/stepping/test/opt' (x86_64).
(lldb) b 11
Breakpoint 1: where = opt`main + 35 at a.c:11:15, address = 0x0000000000400523
(lldb) r
Process 36 launched: '/home/stepping/test/opt' (x86_64)
Process 36 stopped

  • thread #​1, name = 'opt', stop reason = breakpoint 1.1
    frame #​0: 0x0000000000400523 opt`main at a.c:11:15
    8 v_1 = test_in();
    9 v_2 = test_in();
    10 v_3 = test_in();
    -> 11 v_1 = (v_2 * ~(~v_0 + v_3));
    12 v_0 = (v_2 >> (v_3 < (v_0 < v_1)));
    13 v_0 = (v_2 * v_3);
    14 v_0 = v_1;
    (lldb) n
    Process 36 stopped
  • thread #​1, name = 'opt', stop reason = step over
    frame #​0: 0x0000000000400528 opt`main at a.c:15:21
    12 v_0 = (v_2 >> (v_3 < (v_0 < v_1)));
    13 v_0 = (v_2 * v_3);
    14 v_0 = v_1;
    -> 15 v_3 = ((v_1 & (v_2 & v_3)) < v_0);
    16 test_out(v_0, v_1, v_2, v_3);
    17
    18 return 0;
    (lldb) frame var v_0
    (int) v_0 =

(lldb) frame var v_1
(int) v_1 = -6

@cristianassaiante
Copy link
Mannequin Author

cristianassaiante mannequin commented Jun 8, 2021

From further analysis, we discovered another problem in this testcase that may be more interesting. By setting a breakpoint on line 11 and checking frame var on it, we can see that variable v_1 is not available but after a next command its value shows up.

  • thread #​1, name = 'opt', stop reason = breakpoint 1.1
    frame #​0: 0x0000000000400523 opt`main at a.c:11:15
    8 v_1 = test_in();
    9 v_2 = test_in();
    10 v_3 = test_in();
    -> 11 v_1 = (v_2 * ~(~v_0 + v_3));
    12 v_0 = (v_2 >> (v_3 < (v_0 < v_1)));
    13 v_0 = (v_2 * v_3);
    14 v_0 = v_1;
    (lldb) frame var
    (int) v_0 = 0
    (int) v_1 =
    (int) v_2 = 2
    (int) v_3 = 3
    (lldb) n
    Process 23 stopped
  • thread #​1, name = 'opt', stop reason = step over
    frame #​0: 0x0000000000400528 opt`main at a.c:15:21
    12 v_0 = (v_2 >> (v_3 < (v_0 < v_1)));
    13 v_0 = (v_2 * v_3);
    14 v_0 = v_1;
    -> 15 v_3 = ((v_1 & (v_2 & v_3)) < v_0);
    16 test_out(v_0, v_1, v_2, v_3);
    17
    18 return 0;
    (lldb) frame var
    (int) v_0 =
    (int) v_1 = -6
    (int) v_2 = 2
    (int) v_3 = 3

From the dwarf DIE of the variable v_1 we can see how the location field changes after SROA pass:

----- BEFORE
0x00000051: DW_TAG_variable
DW_AT_location (DW_OP_fbreg +16)
DW_AT_name ("v_1")
DW_AT_decl_file ("/home/stepping/debuginfo-analysis/issues/issue7/bug_submission/a.c")
DW_AT_decl_line (6)
DW_AT_type (0x000000ca "int")

----- AFTER
0x00000070: DW_TAG_variable
DW_AT_location (0x0000008f:
[0x0000000000400500, 0x000000000040051b): DW_OP_reg5 RDI)
DW_AT_name ("v_1")
DW_AT_decl_file ("/home/stepping/debuginfo-analysis/issues/issue7/bug_submission/a.c")
DW_AT_decl_line (6)
DW_AT_type (0x000000ce "int")

From the IR it looks like the problem appears upon lowering from dbg.declare to dbg.value:

----- BEFORE
call void @​llvm.lifetime.start.p0i8(i64 4, i8* %7) #​4, !dbg !​16
call void @​llvm.dbg.declare(metadata i32* %3, metadata !​13, metadata !DIExpression()), !dbg !​18

----- AFTER
%2 = call i32 (...) @​test_in(), !dbg !​18
call void @​llvm.dbg.value(metadata i32 %2, metadata !​13, metadata !DIExpression()), !dbg !​17

@cristianassaiante
Copy link
Mannequin Author

cristianassaiante mannequin commented Jun 8, 2021

Jeremy/Orlando, any comment?

@jmorse
Copy link
Member

jmorse commented Jun 9, 2021

I think the second problem is a "variable locations and line numbers" don't line up, however the first one is much more interesting, here's the IR pre-isel, slightly edited:

call void @​llvm.dbg.value(metadata i32 %mul, metadata !​13 ('v_1'),
call void @​llvm.dbg.value(metadata i32 undef, metadata !​12 ('v_0'),
call void @​llvm.dbg.value(metadata i32 undef, metadata !​12 ('v_0'),
call void @​llvm.dbg.value(metadata i32 %mul, metadata !​12 ('v_0'),

Where you can see that the intermediate assignments to v_0 are optimised out and the assignment values replaced with undef. After passing through isel though:

DBG_VALUE %7:gr32, $noreg, !"v_1", !DIExpression(), debug-location !​17
DBG_VALUE %7:gr32, $noreg, !"v_0", !DIExpression(), debug-location !​17
DBG_VALUE $noreg, $noreg, !"v_0", !DIExpression(), debug-location !​17
DBG_VALUE $noreg, $noreg, !"v_0", !DIExpression(), debug-location !​17

The undef assignments are re-ordered to go after the "real" final assignment. The DBG_VALUEs for v_0 get compressed by later passes into a single DBG_VALUE $noreg, because the last assignment to it appears to be undef.

This is almost certainly because of the existing limitations in instruction scheduling, and the simplistic approach we take towards it. See also:

https://lists.llvm.org/pipermail/llvm-dev/2021-June/150846.html

Which is the same limitation applied to a different pass (in a slightly different context).

In terms of my / our (the Sony bunch)'s priorities this is probably in the middle: it's too hard to fix with DBG_VALUEs, but instruction referencing / DBG_INSTR_REF will make it much easier to solve, sometime soon.

@cristianassaiante
Copy link
Mannequin Author

cristianassaiante mannequin commented Nov 27, 2021

mentioned in issue llvm/llvm-bugzilla-archive#50475

@llvmbot llvmbot transferred this issue from llvm/llvm-bugzilla-archive Dec 11, 2021
@llvmbot llvmbot added the confirmed Verified by a second party label Jan 26, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bugzilla Issues migrated from bugzilla confirmed Verified by a second party debuginfo
Projects
None yet
Development

No branches or pull requests

2 participants