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

Some more precise debug info improvements #61419

Merged
merged 3 commits into from
Nov 11, 2021

Conversation

jakobbotsch
Copy link
Member

  • We were not recording precise info in inlinees except for at IL offset
    0 because most of the logic that handles determining when to attach
    debug info did not run for inlinees. There are no changes in what the
    EE sees since we were normalizing debug info back to the root anyway.

  • Propagate debug info even further than just until rationalization, to
    make it simpler to dump the precise debug info. This means we create
    some more GT_IL_OFFSET nodes, in particular when the inlinee debug
    info is valid but the root info is invalid. This is currently
    happening for newobj IL instructions when the constructor is inlined.
    We generate two statements:
    GT_ASG(GT_LCL_VAR(X), ALLOCOBJ(CLS));
    GT_CALL(CTOR, GT_LCL_VAR(X))
    and the first statement ends up "consuming" the debug info, meaning we
    end up with no debug info for the GT_CALL, which eventually propagates
    into the inline tree. I have held off on fixing this for now since it
    causes debug info diffs in the data reported back to the EE.

    The additional nodes in LIR result in 0.15% more memory use and 0.015%
    more instructions retired for SPMI over libraries.

There is also a small fix in gtlist.h for GT_BFIZ when
MEASURE_NODE_SIZES is defined.

No SPMI diffs.

* We were not recording precise info in inlinees except for at IL offset
  0 because most of the logic that handles determining when to attach
  debug info did not run for inlinees. There are no changes in what the
  EE sees since we were normalizing debug info back to the root anyway.

* Propagate debug info even further than just until rationalization, to
  make it simpler to dump the precise debug info. This means we create
  some more GT_IL_OFFSET nodes, in particular when the inlinee debug
  info is valid but the root info is invalid. This is currently
  happening for newobj IL instructions when the constructor is inlined.
  We generate two statements:
  GT_ASG(GT_LCL_VAR(X), ALLOCOBJ(CLS));
  GT_CALL(CTOR, GT_LCL_VAR(X))
  and the first statement ends up "consuming" the debug info, meaning we
  end up with no debug info for the GT_CALL, which eventually propagates
  into the inline tree. I have held off on fixing this for now since it
  causes debug info diffs in the data reported back to the EE.

  The additional nodes in LIR result in 0.15% more memory use and 0.015%
  more instructions retired for SPMI over libraries.

There is also a small fix in gtlist.h for GT_BFIZ when
MEASURE_NODE_SIZES is defined.

No SPMI diffs.
@dotnet-issue-labeler dotnet-issue-labeler bot added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Nov 10, 2021
@ghost
Copy link

ghost commented Nov 10, 2021

Tagging subscribers to this area: @JulieLeeMSFT
See info in area-owners.md if you want to be subscribed.

Issue Details
  • We were not recording precise info in inlinees except for at IL offset
    0 because most of the logic that handles determining when to attach
    debug info did not run for inlinees. There are no changes in what the
    EE sees since we were normalizing debug info back to the root anyway.

  • Propagate debug info even further than just until rationalization, to
    make it simpler to dump the precise debug info. This means we create
    some more GT_IL_OFFSET nodes, in particular when the inlinee debug
    info is valid but the root info is invalid. This is currently
    happening for newobj IL instructions when the constructor is inlined.
    We generate two statements:
    GT_ASG(GT_LCL_VAR(X), ALLOCOBJ(CLS));
    GT_CALL(CTOR, GT_LCL_VAR(X))
    and the first statement ends up "consuming" the debug info, meaning we
    end up with no debug info for the GT_CALL, which eventually propagates
    into the inline tree. I have held off on fixing this for now since it
    causes debug info diffs in the data reported back to the EE.

    The additional nodes in LIR result in 0.15% more memory use and 0.015%
    more instructions retired for SPMI over libraries.

There is also a small fix in gtlist.h for GT_BFIZ when
MEASURE_NODE_SIZES is defined.

No SPMI diffs.

Author: jakobbotsch
Assignees: -
Labels:

area-CodeGen-coreclr

Milestone: -

@jakobbotsch
Copy link
Member Author

jakobbotsch commented Nov 10, 2021

For

using System.Runtime.CompilerServices;

public class Program
{
    public static void Main()
    {
        System.Console.WriteLine(1);
        Foo();
        System.Console.WriteLine(6);
    }

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    private static void Foo()
    {
        System.Console.WriteLine(2);
        Bar();
        System.Console.WriteLine(5);
    }

    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    private static void Bar()
    {
        System.Console.WriteLine(3);
        System.Console.WriteLine(4);
    }
}

we now see

***** BB01
STMT00000 ( 0x000[E-] ... 0x011 )
               [000001] --C-G-------              ▌  CALL      void   System.Console.WriteLine
               [000000] ------------ arg0         └──▌  CNS_INT   int    1

***** BB01
STMT00004 ( INL01 @ 0x000[E-] ... ??? ) <- INLRT @ 0x006[E-]
               [000007] --C-G-------              ▌  CALL      void   System.Console.WriteLine
               [000006] ------------ arg0         └──▌  CNS_INT   int    2

***** BB01
-STMT00007 ( INL02 @ 0x000[E-] ... ??? ) <- INL01 @ ??? <- INLRT @ 0x006[E-]
+STMT00007 ( INL02 @ 0x000[E-] ... ??? ) <- INL01 @ 0x006[E-] <- INLRT @ 0x006[E-]
               [000013] --C-G-------              ▌  CALL      void   System.Console.WriteLine
               [000012] ------------ arg0         └──▌  CNS_INT   int    3

***** BB01
-STMT00008 ( INL02 @ ??? ... ??? ) <- INL01 @ ??? <- INLRT @ 0x006[E-]
+STMT00008 ( INL02 @ 0x006[E-] ... ??? ) <- INL01 @ 0x006[E-] <- INLRT @ 0x006[E-]
               [000015] --C-G-------              ▌  CALL      void   System.Console.WriteLine
               [000014] ------------ arg0         └──▌  CNS_INT   int    4

***** BB01
-STMT00006 ( INL01 @ ??? ... ??? ) <- INLRT @ 0x006[E-]
+STMT00006 ( INL01 @ 0x00B[E-] ... ??? ) <- INLRT @ 0x006[E-]
               [000010] --C-G-------              ▌  CALL      void   System.Console.WriteLine
               [000009] ------------ arg0         └──▌  CNS_INT   int    5

***** BB01
STMT00002 ( 0x00B[E-] ... ??? )
               [000004] --C-G-------              ▌  CALL      void   System.Console.WriteLine
               [000003] ------------ arg0         └──▌  CNS_INT   int    6

***** BB01
STMT00003 ( 0x011[E-] ... ??? )
               [000005] ------------              ▌  RETURN    void  

and as a bonus, we get the following in LIR dump output:

 ------------ BB01 [000..012) (return), preds={} succs={}
-               [000023] ------------                 IL_OFFSET void   IL offset: 0x0
+               [000023] ------------                 IL_OFFSET void   INLRT @ 0x000[E-]
 N002 (  1,  1) [000000] ------------         t0 =    CNS_INT   int    1 $41
                                                   ┌──▌  t0     int    arg0 in rcx
 N003 ( 15,  7) [000001] --CXG-------              ▌  CALL      void   System.Console.WriteLine $VN.Void
-               [000024] ------------                 IL_OFFSET void   IL offset: 0x6
+               [000024] ------------                 IL_OFFSET void   INL01 @ 0x000[E-] <- INLRT @ 0x006[E-]
 N002 (  1,  1) [000006] ------------         t6 =    CNS_INT   int    2 $42
                                                   ┌──▌  t6     int    arg0 in rcx
 N003 ( 15,  7) [000007] --CXG-------              ▌  CALL      void   System.Console.WriteLine $VN.Void
-               [000025] ------------                 IL_OFFSET void   IL offset: 0x6
+               [000025] ------------                 IL_OFFSET void   INL02 @ 0x000[E-] <- INL01 @ 0x006[E-] <- INLRT @ 0x006[E-]
 N002 (  1,  1) [000012] ------------        t12 =    CNS_INT   int    3 $43
                                                   ┌──▌  t12    int    arg0 in rcx
 N003 ( 15,  7) [000013] --CXG-------              ▌  CALL      void   System.Console.WriteLine $VN.Void
-               [000026] ------------                 IL_OFFSET void   IL offset: 0x6
+               [000026] ------------                 IL_OFFSET void   INL02 @ 0x006[E-] <- INL01 @ 0x006[E-] <- INLRT @ 0x006[E-]
 N002 (  1,  1) [000014] ------------        t14 =    CNS_INT   int    4 $44
                                                   ┌──▌  t14    int    arg0 in rcx
 N003 ( 15,  7) [000015] --CXG-------              ▌  CALL      void   System.Console.WriteLine $VN.Void
-               [000027] ------------                 IL_OFFSET void   IL offset: 0x6
+               [000027] ------------                 IL_OFFSET void   INL01 @ 0x00B[E-] <- INLRT @ 0x006[E-]
 N002 (  1,  1) [000009] ------------         t9 =    CNS_INT   int    5 $45
                                                   ┌──▌  t9     int    arg0 in rcx
 N003 ( 15,  7) [000010] --CXG-------              ▌  CALL      void   System.Console.WriteLine $VN.Void
-               [000028] ------------                 IL_OFFSET void   IL offset: 0xb
+               [000028] ------------                 IL_OFFSET void   INLRT @ 0x00B[E-]
 N002 (  1,  1) [000003] ------------         t3 =    CNS_INT   int    6 $46
                                                   ┌──▌  t3     int    arg0 in rcx
 N003 ( 15,  7) [000004] --CXG-------              ▌  CALL      void   System.Console.WriteLine $VN.Void
-               [000029] ------------                 IL_OFFSET void   IL offset: 0x11
+               [000029] ------------                 IL_OFFSET void   INLRT @ 0x011[E-]
 N001 (  0,  0) [000005] ------------                 RETURN    void   $100

cc @dotnet/jit-contrib

{
nxtStmtOffs =
(nxtStmtIndex < info.compStmtOffsetsCount) ? info.compStmtOffsets[nxtStmtIndex] : BAD_IL_OFFSET;
nxtStmtOffs =
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW I've always though the logic in this bit of code was convoluted. But it looks like all that's happened here is that you removed the exclusion for inlinees?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that's the only change here (it's easier to see if you check "Hide whitespace" under the review settings).

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants