Quuxplusone / LLVMBugzillaTest

0 stars 0 forks source link

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

Open Quuxplusone opened 11 years ago

Quuxplusone commented 11 years ago
Bugzilla Link PR15887
Status NEW
Importance P normal
Reported by pankaj (godepankaj@yahoo.com)
Reported on 2013-05-01 09:08:27 -0700
Last modified on 2013-05-17 01:09:41 -0700
Version 3.1
Hardware PC Linux
CC llvm-bugs@lists.llvm.org, rafael@espindo.la
Fixed by commit(s)
Attachments
Blocks
Blocked by
See also
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
Quuxplusone 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.