llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
27.6k stars 11.34k forks source link

Incorrect lexical scope information for local variable, with optimization #16259

Open llvmbot opened 11 years ago

llvmbot commented 11 years ago
Bugzilla Link 15887
Version 3.1
OS Linux
Reporter LLVM Bugzilla Contributor

Extended Description

Summary: Incorrect lexical scope information for local variable, with optimization

Steps to reproduce (just the options):

  1. clang -O0 -g -c -emit-llvm x.c -S
  2. opt x.s -mem2reg -loop-rotate -simplifycfg -o opt1
  3. opt -O1 opt1 -o opt2
  4. llc opt2

Description: I have used the patch on llvm3.1 file, llvm/lib/Transforms/Utils/Local.cpp to avoid multiple 'llvm.dbg.value' for a variable due to LowerDbgDeclare optimization in 'instruction combining'.

For the code snippet below:

62 int func(int dividend, int divisor, int rem) 63 { 64 int d_sign = 0; 65 int div_sign = 0; 66 unsigned int d, r; 67 68 if (dividend < 0) { d_sign = 1; dividend = -dividend; }; 69 if (divisor < 0) { div_sign = 1; divisor = -divisor ; }; 70 71 d = func1((unsigned int)dividend, (unsigned int)divisor, &r); 72 73 if (d_sign && div_sign) r = -r; 74 else if (d_sign) { d = -d; r = -r; } 75 else if (div_sign) { d = -d; }; 76 77 if (rem) rem = (signed int)r; 78 return (signed int)d; 79 }

The code generated code in .ll after 2nd optimization (opt tool execution) looks like below. @​entry: call void @​llvm.dbg.declare(metadata !{i32* %r}, metadata !​68), !dbg !​69

if.then6: ; preds = %entry call void @​llvm.dbg.value(metadata !{i32* %r}, i64 0, metadata !​68), !dbg !​80

if.then9: call void @​llvm.dbg.value(metadata !{i32 %sub10}, i64 0, metadata !​78), !dbg !​81 call void @​llvm.dbg.value(metadata !{i32 %r}, i64 0, metadata !​68), !dbg !​84 %3 = load i32 %r, align 4, !dbg !​84

if.then20: ; preds = %if.end18 call void @​llvm.dbg.value(metadata !{i32 %r}, i64 0, metadata !​68), !dbg !​88 %4 = load i32 %r, align 4, !dbg !​88

!​68 = metadata !{i32 786688, metadata !​64, metadata !"r", metadata !​6, i32 66, metadata !​9, i32 0, i32 0} ; [ DW_TAG_auto_variable ]

!​64 = metadata !{i32 786443, metadata !​13, i32 63, i32 1, metadata !​6, i32 4} ; [ DW_TAG_lexical_block ]

!​72 = metadata !{i32 786443, metadata !​64, i32 68, i32 21, metadata !​6, i32 5} ; [ DW_TAG_lexical_block ]

!​75 = metadata !{i32 786443, metadata !​64, i32 69, i32 20, metadata !​6, i32 6} ; [ DW_TAG_lexical_block ]

!​82 = metadata !{i32 786443, metadata !​64, i32 74, i32 20, metadata !​6, i32 7} ; [ DW_TAG_lexical_block ]

Scopes identified are: 63-78, 68-68, 69-69, 74-74.

The point to note here is all these variable point to same metadata. In this the 1st is 'llvm.dbg.declare' which ideally should be the real variable declaration and the rest of the 'llvm.dbg.value' too point to same metadata, which seems to be correct.

But when I try to retrieve the variables for the function 'func' with below code snippet,

I get 4 variables declared in the function using the llvm utility function MachineModuleInfo::VariableDbgInfoMapTy &VMap = MF->getMMI().getVariableDbgInfo(); . I iterate over these variables to find which scope they fit into. The problem lies here.

varlinenum  |  scope marked |  variable name
  1. 66 | 63-78 | r
  2. 77 | 63-78 | r
  3. 74 | 74-74 | r
  4. 73 | 63-78 | r

We can see here variable 'r' is identified to belong to same scope '63-78'. and moreover all 'llvm.dbg.declare' when it is checked while debugging.

Reference llvm-dev post: http://lists.cs.uiuc.edu/pipermail/llvmdev/2013-April/061703.html

llvmbot commented 11 years ago

As Adrian said, "we attach the debug location of the load/store instruction to the dbg.value (and thus it gets the enclosing scope of the use as scope), but we could attach the debug location of the original dbg.declare intrinsic to the dbg.value", I too feel, it should be fine to attach debug location of original dbg.declare intrinsic to dbg.value.

I get this problem because of a stack based architecture we have, where we expect local variables to be stored on stack. The scenario which I had described, for the optimization, it wouldn't have been a problem if we had the facility of making the same variables as 'register variables'. This is a architecture constraint though. Even with this constraint, user checking for 'debug information with optimized code', would like this optimized variable still to point to original dbg.declare.

I also observed that after 'inilinng optimization', the debug location information is not updated for the inlined instructions. A case. func() { struct some some1; func1( &some1); }

func1(struct some *this) { return func2( this); //just this call }

func2( struct some *this) { //some code which can be inlined }

For the optimized code, one expects the debug information reflects optimization.

llvmbot commented 9 months ago

@llvm/issue-subscribers-debuginfo

Author: None (llvmbot)

| | | | --- | --- | | Bugzilla Link | [15887](https://llvm.org/bz15887) | | Version | 3.1 | | OS | Linux | | Reporter | LLVM Bugzilla Contributor | ## Extended Description Summary: Incorrect lexical scope information for local variable, with optimization Steps to reproduce (just the options): 1. clang -O0 -g -c -emit-llvm x.c -S 2. opt x.s -mem2reg -loop-rotate -simplifycfg -o opt1 3. opt -O1 opt1 -o opt2 4. llc opt2 Description: I have used the patch on llvm3.1 file, llvm/lib/Transforms/Utils/Local.cpp to avoid multiple 'llvm.dbg.value' for a variable due to LowerDbgDeclare optimization in 'instruction combining'. For the code snippet below: 62 int func(int dividend, int divisor, int *rem) 63 { 64 int d_sign = 0; 65 int div_sign = 0; 66 unsigned int d, r; 67 68 if (dividend < 0) { d_sign = 1; dividend = -dividend; }; 69 if (divisor < 0) { div_sign = 1; divisor = -divisor ; }; 70 71 d = func1((unsigned int)dividend, (unsigned int)divisor, &r); 72 73 if (d_sign && div_sign) r = -r; 74 else if (d_sign) { d = -d; r = -r; } 75 else if (div_sign) { d = -d; }; 76 77 if (rem) *rem = (signed int)r; 78 return (signed int)d; 79 } The code generated code in .ll after 2nd optimization (opt tool execution) looks like below. @&#8203;entry: call void @&#8203;llvm.dbg.declare(metadata !{i32* %r}, metadata !&#8203;68), !dbg !&#8203;69 if.then6: ; preds = %entry call void @&#8203;llvm.dbg.value(metadata !{i32* %r}, i64 0, metadata !&#8203;68), !dbg !&#8203;80 if.then9: call void @&#8203;llvm.dbg.value(metadata !{i32 %sub10}, i64 0, metadata !&#8203;78), !dbg !&#8203;81 call void @&#8203;llvm.dbg.value(metadata !{i32* %r}, i64 0, metadata !&#8203;68), !dbg !&#8203;84 %3 = load i32* %r, align 4, !dbg !&#8203;84 if.then20: ; preds = %if.end18 call void @&#8203;llvm.dbg.value(metadata !{i32* %r}, i64 0, metadata !&#8203;68), !dbg !&#8203;88 %4 = load i32* %r, align 4, !dbg !&#8203;88 !&#8203;68 = metadata !{i32 786688, metadata !&#8203;64, metadata !"r", metadata !&#8203;6, i32 66, metadata !&#8203;9, i32 0, i32 0} ; [ DW_TAG_auto_variable ] !&#8203;64 = metadata !{i32 786443, metadata !&#8203;13, i32 63, i32 1, metadata !&#8203;6, i32 4} ; [ DW_TAG_lexical_block ] !&#8203;72 = metadata !{i32 786443, metadata !&#8203;64, i32 68, i32 21, metadata !&#8203;6, i32 5} ; [ DW_TAG_lexical_block ] !&#8203;75 = metadata !{i32 786443, metadata !&#8203;64, i32 69, i32 20, metadata !&#8203;6, i32 6} ; [ DW_TAG_lexical_block ] !&#8203;82 = metadata !{i32 786443, metadata !&#8203;64, i32 74, i32 20, metadata !&#8203;6, i32 7} ; [ DW_TAG_lexical_block ] Scopes identified are: 63-78, 68-68, 69-69, 74-74. The point to note here is all these variable point to same metadata. In this the 1st is 'llvm.dbg.declare' which ideally should be the real variable declaration and the rest of the 'llvm.dbg.value' too point to same metadata, which seems to be correct. But when I try to retrieve the variables for the function 'func' with below code snippet, I get 4 variables declared in the function using the llvm utility function MachineModuleInfo::VariableDbgInfoMapTy &VMap = MF->getMMI().getVariableDbgInfo(); . I iterate over these variables to find which scope they fit into. The problem lies here. varlinenum | scope marked | variable name 1. 66 | 63-78 | r 2. 77 | 63-78 | r 3. 74 | 74-74 | r 4. 73 | 63-78 | r We can see here variable 'r' is identified to belong to same scope '63-78'. and moreover all 'llvm.dbg.declare' when it is checked while debugging. Reference llvm-dev post: http://lists.cs.uiuc.edu/pipermail/llvmdev/2013-April/061703.html