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

JIT: remove GTF_INX_REFARR_LAYOUT #33098

Merged
merged 6 commits into from
Mar 7, 2020

Conversation

AndyAyersMS
Copy link
Member

When morphing GT_INDEX nodes, we were inadvertently also setting
GTF_IND_NONFAULTING for the GT_IND subtree for ref type arrays, because
GTF_IND_NONFAULTING has the same value as GTF_INX_REFARR_LAYOUT.

This turns out to be safe since in general there is an upstream bounds check to
cover the null check from the indexing operation, so the fact that we were
claiming the GT_IND can't fault is ok.

A no diff change would remove the GTF_INX_REFARR_LAYOUT flag and then modify
fgMorphArrayIndex to set GTF_IND_NONFAULTING for ref type arrays with bounds
checks:

    // If there's a bounds check, the the indir won't fault.
    if (bndsChk && (tree->gtType == TYP_REF))
    {
        tree->gtFlags |= GTF_IND_NONFAULTING;
    }

    tree->gtFlags |= GTF_EXCEPT;

But there's no good reason to limit the above change to ref type arrays and no
good reason to OR in GTF_EXCEPT when there are bounds checks.

Once we do the more general fix we see diffs, so we might as well further clean
up the related constraint in the importer found under REDO_RETURN_NODE.

Closes #32647.

When morphing `GT_INDEX` nodes, we were inadvertently also setting
`GTF_IND_NONFAULTING` for the `GT_IND` subtree for ref type arrays, because
`GTF_IND_NONFAULTING` has the same value as `GTF_INX_REFARR_LAYOUT`.

This turns out to be safe since in general there is an upstream bounds check to
cover the null check from the indexing operation, so the fact that we were
claiming the `GT_IND` can't fault is ok.

A no diff change would remove the `GTF_INX_REFARR_LAYOUT` flag and then modify
`fgMorphArrayIndex` to set `GTF_IND_NONFAULTING` for ref type arrays with bounds
checks:
```
    // If there's a bounds check, the the indir won't fault.
    if (bndsChk && (tree->gtType == TYP_REF))
    {
        tree->gtFlags |= GTF_IND_NONFAULTING;
    }

    tree->gtFlags |= GTF_EXCEPT;
```

But there's no good reason to limit the above change to ref type arrays and no
good reason to OR in `GTF_EXCEPT` when there are bounds checks.

Once we do the more general fix we see diffs, so we might as well further clean
up the related constraint in the importer found under `REDO_RETURN_NODE`.

Closes dotnet#32647.
@maryamariyan maryamariyan added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Mar 3, 2020
@AndyAyersMS
Copy link
Member Author

cc @dotnet/jit-contrib

This causes a small regression. I sampled a few of the more prominent ones, and in those we do extra CSEs and loop hoists and then often see different allocation patterns.

Some of the regressions might be fixable by renumbering blocks before LSRA, because late flow graph updates after liveness cause divergence between the block number order and flow order. I know I've seen this before... will look at it as a separate issue.

Summary of Code Size diffs:
(Lower is better)

Total bytes of diff: 1095 (0.00% of base)
    diff is a regression.

Top file regressions (bytes):
         699 : System.Data.Common.dasm (0.05% of base)
         117 : System.Data.Odbc.dasm (0.06% of base)
         109 : Microsoft.CodeAnalysis.CSharp.dasm (0.00% of base)
          69 : System.Linq.Parallel.dasm (0.00% of base)
          48 : System.Data.OleDb.dasm (0.02% of base)
          37 : System.ComponentModel.Composition.dasm (0.01% of base)
          28 : Newtonsoft.Json.dasm (0.00% of base)
          27 : System.Collections.Immutable.dasm (0.00% of base)
          14 : ILCompiler.Reflection.ReadyToRun.dasm (0.01% of base)
          12 : System.Management.dasm (0.00% of base)
          10 : Microsoft.CSharp.dasm (0.00% of base)
          10 : System.Reflection.Metadata.dasm (0.00% of base)
          10 : System.Security.Cryptography.Cng.dasm (0.01% of base)
          10 : System.Text.Json.dasm (0.00% of base)
           7 : System.Drawing.Common.dasm (0.00% of base)
           7 : System.Net.Http.dasm (0.00% of base)
           5 : System.Text.RegularExpressions.dasm (0.00% of base)
           4 : System.Net.Http.WinHttpHandler.dasm (0.00% of base)
           4 : System.Private.Xml.dasm (0.00% of base)
           3 : Microsoft.VisualBasic.Core.dasm (0.00% of base)

Top file improvements (bytes):
         -56 : System.Private.CoreLib.dasm (-0.00% of base)
         -26 : Microsoft.CodeAnalysis.dasm (-0.00% of base)
         -18 : System.Runtime.Serialization.Formatters.dasm (-0.02% of base)
         -13 : System.Reflection.MetadataLoadContext.dasm (-0.01% of base)
         -12 : System.Text.Encodings.Web.dasm (-0.04% of base)
          -7 : System.IO.IsolatedStorage.dasm (-0.04% of base)
          -5 : xunit.execution.dotnet.dasm (-0.00% of base)
          -5 : xunit.runner.utility.netcoreapp10.dasm (-0.00% of base)
          -3 : Microsoft.Diagnostics.Tracing.TraceEvent.dasm (-0.00% of base)

33 total files with Code Size differences (9 improved, 24 regressed), 198 unchanged.

Top method regressions (bytes):
         114 (17.09% of base) : Microsoft.CodeAnalysis.CSharp.dasm - NamedTypeSymbol:EqualsComplicatedCases(NamedTypeSymbol,bool,bool):bool:this
          75 ( 6.26% of base) : System.Data.Common.dasm - DoubleStorage:Aggregate(ref,int):Object:this
          75 ( 6.15% of base) : System.Data.Common.dasm - SingleStorage:Aggregate(ref,int):Object:this
          69 ( 3.67% of base) : System.Data.Odbc.dasm - OdbcDataReader:RetrieveKeyInfoFromStatistics(QualifiedTableName,bool):int:this
          69 ( 2.14% of base) : System.Linq.Parallel.dasm - SortHelper`2:QuickSortIndicesInPlace(GrowingArray`1,List`1,ubyte):this (7 methods)
          68 ( 4.46% of base) : System.Data.Common.dasm - UInt64Storage:Aggregate(ref,int):Object:this
          68 ( 4.47% of base) : System.Data.Common.dasm - Int64Storage:Aggregate(ref,int):Object:this
          47 ( 3.45% of base) : System.Data.Common.dasm - Int32Storage:Aggregate(ref,int):Object:this
          47 ( 3.47% of base) : System.Data.Common.dasm - UInt16Storage:Aggregate(ref,int):Object:this
          47 ( 3.46% of base) : System.Data.Common.dasm - UInt32Storage:Aggregate(ref,int):Object:this
          45 ( 3.27% of base) : System.Data.Common.dasm - Int16Storage:Aggregate(ref,int):Object:this
          42 ( 3.33% of base) : System.Data.Common.dasm - ByteStorage:Aggregate(ref,int):Object:this
          40 ( 3.12% of base) : System.Data.Common.dasm - SByteStorage:Aggregate(ref,int):Object:this
          37 ( 4.15% of base) : System.ComponentModel.Composition.dasm - GenericServices:Reorder(ref,ref):ref (7 methods)
          34 ( 2.43% of base) : System.Private.CoreLib.dasm - StringBuilder:AppendJoinCore(long,int,ref):StringBuilder:this (7 methods)
          27 ( 0.71% of base) : System.Collections.Immutable.dasm - Builder:AddRange(ref,int):this (20 methods)
          24 ( 4.44% of base) : System.Data.Common.dasm - BooleanStorage:Aggregate(ref,int):Object:this
          24 ( 8.33% of base) : System.Data.Common.dasm - SqlGuidStorage:Aggregate(ref,int):Object:this
          24 ( 8.33% of base) : System.Data.Common.dasm - SqlBinaryStorage:Aggregate(ref,int):Object:this
          24 ( 4.03% of base) : System.Data.Odbc.dasm - DbBuffer:ReadDateTime(int):DateTime:this

Top method improvements (bytes):
         -27 (-1.07% of base) : Microsoft.CodeAnalysis.dasm - <DescendantNodesAndTokensIntoTrivia>d__159:MoveNext():bool:this
         -26 (-3.76% of base) : System.Private.CoreLib.dasm - Sha1ForNonSecretPurposes:Drain():this
         -21 (-4.12% of base) : Microsoft.Diagnostics.Tracing.TraceEvent.dasm - PathUtil:PathRelativeTo(String,String):String
         -18 (-1.06% of base) : Microsoft.CodeAnalysis.dasm - <DescendantTriviaIntoTrivia>d__161:MoveNext():bool:this
         -18 (-6.64% of base) : System.Private.CoreLib.dasm - ObjectEqualityComparer`1:IndexOf(ref,short,int,int):int:this
         -16 (-5.99% of base) : System.Private.CoreLib.dasm - ObjectEqualityComparer`1:IndexOf(ref,long,int,int):int:this
         -15 (-6.00% of base) : System.Runtime.Serialization.Formatters.dasm - ObjectIDGenerator:GetId(Object,byref):long:this
         -14 (-5.36% of base) : System.Private.CoreLib.dasm - ObjectEqualityComparer`1:IndexOf(ref,int,int,int):int:this
         -13 (-1.05% of base) : System.Reflection.MetadataLoadContext.dasm - DefaultBinder:FindMostSpecific(ref,ref,Type,ref,ref,Type,ref,ref):int
          -9 (-6.62% of base) : System.Private.CoreLib.dasm - ObjectEqualityComparer`1:LastIndexOf(ref,short,int,int):int:this
          -9 (-6.16% of base) : System.Private.CoreLib.dasm - ObjectEqualityComparer`1:IndexOf(ref,double,int,int):int:this
          -9 (-6.08% of base) : System.Private.CoreLib.dasm - ObjectEqualityComparer`1:LastIndexOf(ref,double,int,int):int:this
          -8 (-6.11% of base) : System.Private.CoreLib.dasm - ObjectEqualityComparer`1:IndexOf(ref,ubyte,int,int):int:this
          -8 (-6.02% of base) : System.Private.CoreLib.dasm - ObjectEqualityComparer`1:LastIndexOf(ref,ubyte,int,int):int:this
          -8 (-5.97% of base) : System.Private.CoreLib.dasm - ObjectEqualityComparer`1:LastIndexOf(ref,long,int,int):int:this
          -7 (-3.47% of base) : Microsoft.CodeAnalysis.CSharp.dasm - PEModuleSymbol:HasAnyCustomAttributes(EntityHandle):bool:this
          -7 (-1.61% of base) : System.Data.Common.dasm - DataSet:MarkModifiedRows(ref,int):this
          -7 (-5.11% of base) : System.IO.IsolatedStorage.dasm - IsolatedStorageFile:GetFullPath(String):String:this
          -7 (-0.60% of base) : System.Private.CoreLib.dasm - DefaultBinder:FindMostSpecific(ref,ref,Type,ref,ref,Type,ref,ref):int
          -7 (-5.38% of base) : System.Private.CoreLib.dasm - ObjectEqualityComparer`1:LastIndexOf(ref,int,int,int):int:this

Top method regressions (percentages):
          10 (17.86% of base) : Microsoft.CSharp.dasm - <PrivateImplementationDetails>:ComputeStringHash(String):int
          10 (17.86% of base) : System.Data.Common.dasm - <PrivateImplementationDetails>:ComputeStringHash(String):int
          10 (17.86% of base) : System.Net.Http.dasm - <PrivateImplementationDetails>:ComputeStringHash(String):int
          10 (17.86% of base) : System.Private.CoreLib.dasm - <PrivateImplementationDetails>:ComputeStringHash(String):int
          10 (17.86% of base) : System.Private.Xml.dasm - <PrivateImplementationDetails>:ComputeStringHash(String):int
          10 (17.86% of base) : System.Reflection.Metadata.dasm - <PrivateImplementationDetails>:ComputeStringHash(String):int
          10 (17.86% of base) : System.Security.Cryptography.Algorithms.dasm - <PrivateImplementationDetails>:ComputeStringHash(String):int
          10 (17.86% of base) : System.Security.Cryptography.Cng.dasm - <PrivateImplementationDetails>:ComputeStringHash(String):int
          10 (17.86% of base) : System.Text.Json.dasm - <PrivateImplementationDetails>:ComputeStringHash(String):int
         114 (17.09% of base) : Microsoft.CodeAnalysis.CSharp.dasm - NamedTypeSymbol:EqualsComplicatedCases(NamedTypeSymbol,bool,bool):bool:this
           7 ( 9.46% of base) : Microsoft.CodeAnalysis.dasm - StringTable:TextEqualsCore(String,ref,int):bool
          24 ( 8.33% of base) : System.Data.Common.dasm - SqlGuidStorage:Aggregate(ref,int):Object:this
          24 ( 8.33% of base) : System.Data.Common.dasm - SqlBinaryStorage:Aggregate(ref,int):Object:this
           8 ( 8.25% of base) : Newtonsoft.Json.dasm - JPath:Match(String):bool:this
          12 ( 8.11% of base) : System.Data.Odbc.dasm - DbBuffer:ReadTime(int):TimeSpan:this
          12 ( 8.11% of base) : System.Data.OleDb.dasm - DbBuffer:ReadTime(int):TimeSpan:this
           7 ( 8.05% of base) : Microsoft.CodeAnalysis.dasm - StringTable:TextEquals(String,String,int,int):bool
           7 ( 8.05% of base) : System.Private.Xml.dasm - NameTable:TextEquals(String,ref,int,int):bool
           8 ( 7.62% of base) : Newtonsoft.Json.dasm - StringReferenceExtensions:EndsWith(StringReference,String):bool
           7 ( 7.00% of base) : Newtonsoft.Json.dasm - StringReferenceExtensions:StartsWith(StringReference,String):bool

Top method improvements (percentages):
         -18 (-6.64% of base) : System.Private.CoreLib.dasm - ObjectEqualityComparer`1:IndexOf(ref,short,int,int):int:this
          -9 (-6.62% of base) : System.Private.CoreLib.dasm - ObjectEqualityComparer`1:LastIndexOf(ref,short,int,int):int:this
          -9 (-6.16% of base) : System.Private.CoreLib.dasm - ObjectEqualityComparer`1:IndexOf(ref,double,int,int):int:this
          -8 (-6.11% of base) : System.Private.CoreLib.dasm - ObjectEqualityComparer`1:IndexOf(ref,ubyte,int,int):int:this
          -9 (-6.08% of base) : System.Private.CoreLib.dasm - ObjectEqualityComparer`1:LastIndexOf(ref,double,int,int):int:this
          -8 (-6.02% of base) : System.Private.CoreLib.dasm - ObjectEqualityComparer`1:LastIndexOf(ref,ubyte,int,int):int:this
         -15 (-6.00% of base) : System.Runtime.Serialization.Formatters.dasm - ObjectIDGenerator:GetId(Object,byref):long:this
         -16 (-5.99% of base) : System.Private.CoreLib.dasm - ObjectEqualityComparer`1:IndexOf(ref,long,int,int):int:this
          -8 (-5.97% of base) : System.Private.CoreLib.dasm - ObjectEqualityComparer`1:LastIndexOf(ref,long,int,int):int:this
          -7 (-5.38% of base) : System.Private.CoreLib.dasm - ObjectEqualityComparer`1:LastIndexOf(ref,int,int,int):int:this
         -14 (-5.36% of base) : System.Private.CoreLib.dasm - ObjectEqualityComparer`1:IndexOf(ref,int,int,int):int:this
          -7 (-5.11% of base) : System.IO.IsolatedStorage.dasm - IsolatedStorageFile:GetFullPath(String):String:this
          -7 (-4.27% of base) : System.Security.Cryptography.Algorithms.dasm - Helpers:FixupKeyParity(ref):ref
         -21 (-4.12% of base) : Microsoft.Diagnostics.Tracing.TraceEvent.dasm - PathUtil:PathRelativeTo(String,String):String
          -6 (-4.03% of base) : System.Private.CoreLib.dasm - GenericArraySortHelper`1:BinarySearch(ref,int,int,double):int
         -26 (-3.76% of base) : System.Private.CoreLib.dasm - Sha1ForNonSecretPurposes:Drain():this
          -6 (-3.73% of base) : System.Text.Encodings.Web.dasm - TextEncoderSettings:AllowCharacters(ref):this
          -6 (-3.64% of base) : System.Text.Encodings.Web.dasm - TextEncoderSettings:ForbidCharacters(ref):this
          -7 (-3.47% of base) : Microsoft.CodeAnalysis.CSharp.dasm - PEModuleSymbol:HasAnyCustomAttributes(EntityHandle):bool:this
          -7 (-3.14% of base) : System.Private.Xml.dasm - BinXmlSqlDecimal:TrimTrailingZeros():this

118 total methods with Code Size differences (35 improved, 83 regressed), 239924 unchanged.

Copy link
Member

@erozenfeld erozenfeld left a comment

Choose a reason for hiding this comment

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

LGTM

@AndyAyersMS
Copy link
Member Author

Test failures look like they're caused by this change; investigating.

@AndyAyersMS
Copy link
Member Author

Turns out this simplification is not safe to enable more broadly, but not for the reasons stated in the comment:

// We will fold away OBJ/ADDR
// except for OBJ/ADDR/INDEX
// as the array type influences the array element's offset
// Later in this method we change op->gtType to info.compRetNativeType
// This is not correct when op is a GT_INDEX as the starting offset
// for the array elements 'elemOffs' is different for an array of
// TYP_REF than an array of TYP_STRUCT (which simply wraps a TYP_REF)
// Also refer to the GTF_INX_REFARR_LAYOUT flag
//
if ((op1->gtOper == GT_ADDR) && (op1->AsOp()->gtOp1->gtOper != GT_INDEX))
{
// Change '*(&X)' to 'X' and see if we can do better
op = op1->AsOp()->gtOp1;
goto REDO_RETURN_NODE;
}
op->ChangeOperUnchecked(GT_IND);
op->gtFlags |= GTF_IND_TGTANYWHERE;
}

It can lose information about the type of the array elements and so hit an assert in value numbering.

;; x64 Linux 
;;
;; JIT/SIMD/CircleInConvex_ro
;; ClassLibrary.test:convex_hull(System.Collections.Generic.List`1[Vector2])

impFixupStructReturnType: retyping

[000346] ---XG-------   *  OBJ       simd8 <System.Numerics.Vector2>
[000345] ---XG-------   \--*  ADDR      byref 
[000344] ---XG-------      \--*  INDEX     struct
[000342] ---XG-------         +--*  FIELD     ref    _items
[000341] ------------         |  \--*  LCL_VAR   ref    V00 this         
[000343] ------------         \--*  CNS_INT   int    0

;; baseline 
impFixupStructReturnType: result of retyping is

[000346] *--XG-------   *  IND       double
[000345] ---XG-------   \--*  ADDR      byref 
[000344] ---XG-------      \--*  INDEX     struct
[000342] ---XG-------         +--*  FIELD     ref    _items
[000341] ------------         |  \--*  LCL_VAR   ref    V00 this         
[000343] ------------         \--*  CNS_INT   int    0

;; this PR, currently
impFixupStructReturnType: result of retyping is

[000344] ---XG-------   *  INDEX     double
[000342] ---XG-------   +--*  FIELD     ref    _items
[000341] ------------   |  \--*  LCL_VAR   ref    V00 this         
[000343] ------------   \--*  CNS_INT   int    0

so will undo the code change and update the comment.

1 similar comment
@AndyAyersMS

This comment has been minimized.

@AndyAyersMS
Copy link
Member Author

Now hitting an assert on some x86 library tests:

Assert failure(PID 4604 [0x000011fc], Thread: 920 [0x0398]): 
Assertion failed 'IsCompatibleType(cseLclVarTyp, expTyp)' 
 in 'System.Collections.Generic.Stack`1[RefAsValueType`1][System.Collections.Immutable.RefAsValueType`1[System.__Canon]]:Pop():System.Collections.Immutable.RefAsValueType`1[__Canon]:this' 
during 'Optimize Valnum CSEs' (IL size 82)

    File: F:\workspace\_work\1\s\src\coreclr\src\jit\optcse.cpp Line: 2768

Will investigate.

@AndyAyersMS
Copy link
Member Author

Having some trouble reproing the failure above.... since an earlier commit didn't hit this, am going to try merging up locally to see if that's what is needed.

@AndyAyersMS
Copy link
Member Author

Still not able to repro, am going to try rerunning these...

@AndyAyersMS
Copy link
Member Author

Got a repro, finally. Looks like the CSE code is running into trouble with GT_INDs that should be CSEs but have different types, here TYP_STRUCT and TYP_REF.

N015 ( 20, 22) CSE #02 (def)[000124] ---XG-------              \--*  IND       ref    <l:$341, c:$204>
N013 (  9,  9)              [000115] ----G-------                    \--*  ADDR      byref  $300

N012 (  5,  5) CSE #02 (use)[000149] a---G-------              |        \--*  IND       struct <l:$340, c:$381>
N011 (  4,  4)              [000150] -------N----              |           \--*  ADD       byref  $300

We can legitimately see this lind of IR for cases where structs are returned as various native types (say a struct-wrapped TYP_REF) and we inline.

This PR enables more array element CSEs because we mark more array accesses as nonfaulting, so not too surprising we're hitting this here (previously only TYP_REF accesses were so blessed so we weren't seeing so many mixed cases).

I think the fix is along the lines of the following: adjust CSE's "guess the handle" rules so that if one tree is TYP_STRUCT and another is TYP_REF we just forgo CSEing them for now.

@AndyAyersMS
Copy link
Member Author

Simple repro for the failure (release x86)

using System;
using System.Collections.Generic;

struct RefAsValueType<T>
{
    public T Value;
    public RefAsValueType(T value)
    {
        this.Value = value;
    }
}

class X
{
    public static int Main()
    {
        string a = "hello, world!";
        var av = new RefAsValueType<string>(a);
        var stack = new Stack<RefAsValueType<string>>();
        stack.Push(av);
        string b = stack.Pop().Value;
        return a == b ? 100 : -1;
    }
}

@sandreenko
Copy link
Contributor

I think the fix is along the lines of the following: adjust CSE's "guess the handle" rules so that if one tree is TYP_STRUCT and another is TYP_REF we just forgo CSEing them for now.

In theory, we don't have type information on indirection node themselves, it is contained in the child trees. Note that it is different for OBJ, BLK nodes that are usually in the same case statements as IND. So if children of two IND have the same VN then we should be able to cse them.
However, that check in IsCompatibleType was shown useful in the past because it was catching issues with missed structHnd or FldSeq, so I don't want to see it relaxed too much. Could you give me the jitDump for the method please?

@AndyAyersMS
Copy link
Member Author

IR Dumps for base jit and diff jit.

This seems to be related to your change to not eagerly retype return values, since that's where part of the divergence comes in, one of the CSE trees (TYP_REF) is retyped, the other (TYP_STRUCT) is not.

In the baseline jit, we don't mark the TYP_STRUCT indir as nonfaulting -- we just do it (inadvertently) for the TYP_REF indir. So this causes CSE to back away.

 NO_CSE - This use has an exception set item that isn't contained in the defs!

but with this PR both INDs are nonfaulting, CSE tries to carry on, and blows up with incompatible types.

@AndyAyersMS
Copy link
Member Author

Maybe this is related: morph is putting a field sequence on a COMMA, perhaps it was meant for the underlying ADDR.

               [000143] ---XG-------              |  \--*  COMMA     byref  Zero Fseq[Value]

@sandreenko
Copy link
Contributor

I do not think that it is related to return-call-retyping. From what I see [000124] is correctly typed as ref because we got it from struct = struct asg by doing field by field assignment and in this case RefAsValueType.Value type is ref. Check that by looking where Fseq[Value] is located, it is under that IND tree.

[000149] is different, in this case we are talking about the whole struct, not about its only field, you can see this by searching for Fseq[Value] that is located above that IND.

So I think the real issue is in GT_INDEX morphing, we should create OBJ struct instead of IND struct nodes there. However, if you change that you might see many regressions.

fgMorphTree BB03, STMT00012 (before)
               [000079] ---XG-------              +--*  INDEX     struct
               [000072] ------------              |  +--*  LCL_VAR   ref    V02 loc1         
               [000073] ------------              |  \--*  LCL_VAR   int    V01 loc0  
fgMorphCopyBlock:block assignment to morph:
               [000142] ---XG+------              +--*  OBJ       struct<RefAsValueType`1, 4>
               [000140] ---XG+------              |  \--*  COMMA     byref 
               [000134] ---X-+------              |     +--*  ARR_BOUNDS_CHECK_Rng void  
               [000073] -----+------              |     |  +--*  LCL_VAR   int    V01 loc0         
               [000133] ---X-+------              |     |  \--*  ARR_LENGTH int   
               [000072] -----+------              |     |     \--*  LCL_VAR   ref    V02 loc1         
               [000141] ----G+------              |     \--*  ADDR      byref 
               [000079] a---G+------              |        \--*  IND       struct
               [000139] -----+------              |           \--*  ADD       byref 
               [000131] -----+------              |              +--*  LCL_VAR   ref    V02 loc1         
               [000138] -----+------              |              \--*  ADD       int   
               [000136] -----+------              |                 +--*  LSH       int   
               [000132] i----+------              |                 |  +--*  LCL_VAR   int    V01 loc0         
               [000135] -----+-N----              |                 |  \--*  CNS_INT   int    2
               [000137] -----+------              |                 \--*  CNS_INT   int    8 Fseq[#FirstElem]

if you ask for [000079] struct handle you won't get one and it doesn't look correct.
Our CodeGen is fine with that now because later rationalize will delete ADDR(IND()) pairs.
Probably we should not create these pairs in the first place.

I want to take a closer look at this case, but right now my enlistment is screwed with the latest build changes.

@AndyAyersMS
Copy link
Member Author

I could be getting confused, I guess it was the first version of this PR that had a return-retyping issue.

Changing morph so that the field seq ends up on the ADDR instead of the COMMA fixes this latest issue.

@AndyAyersMS
Copy link
Member Author

Now we're attempting some redundant annotations.

Assert failure(PID 400 [0x00000190], Thread: 8600 [0x2198]): Assertion failed 'a != b' in 'System.Decimal:.cctor()' during 'Optimize Valnum CSEs' (IL size 64)
 
     File: F:\workspace\_work\1\s\src\coreclr\src\jit\gentree.cpp Line: 18145
     Image: F:\workspace\_work\1\s\artifacts\bin\coreclr\Windows_NT.x64.Checked\crossgen.exe

@sandreenko
Copy link
Contributor

That looks similar to https://github.com/dotnet/runtime/pull/32085/files#diff-8ed3af14b61694b641239e8e88b1a762.
does the assert happen here

FieldSeqNode* zeroOffsetFldSeq = nullptr;
if (GetZeroOffsetFieldMap()->Lookup(arg, &zeroOffsetFldSeq))
{
fldSeq = GetFieldSeqStore()->Append(fldSeq, zeroOffsetFldSeq);
}

?

@AndyAyersMS
Copy link
Member Author

Haven't debugged yet; will let you know soon.

@AndyAyersMS
Copy link
Member Author

No, not the same issue.

CSE is checking if it needs to add a zero offset field seq, and so now also needs to tunnel through commas to get at the actual node of interest.

Assert failure(PID 37296 [0x000091b0], Thread: 14936 [0x3a58]): Assertion failed 'a != b' in 'System.Decimal:.cctor()' during 'Optimize Valnum CSEs' (IL size 64)

    File: C:\repos\runtime4\src\coreclr\src\jit\gentree.cpp Line: 18107
    Image: C:\repos\runtime4\artifacts\bin\coreclr\Windows_NT.x86.Checked\crossgen.exe

                            [000522] -ACXG-------              *  COMMA     byref  $240
                            [000520] -ACXG-------              +--*  ASG       byref  $VN.Void
                            [000519] D------N----              |  +--*  LCL_VAR   byref  V33 cse0         d:1 $240
N001 ( 14,  5)              [000293] H-CXG-------              |  \--*  CALL help r2r_ind byref  HELPER.CORINFO_HELP_READYTORUN_STATIC_BASE Zero Fseq[Zero] $240
                            [000521] ------------              \--*  LCL_VAR   byref  V33 cse0         u:1 Zero Fseq[Zero] $240

bool hasZeroMapAnnotation = m_pCompiler->GetZeroOffsetFieldMap()->Lookup(exp, &fldSeq);
bool commaOnly = true;
GenTree* effectiveExp = exp->gtEffectiveVal(commaOnly);
const bool hasZeroMapAnnotation = m_pCompiler->GetZeroOffsetFieldMap()->Lookup(effectiveExp, &fldSeq);
Copy link
Contributor

Choose a reason for hiding this comment

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

It looks like you deleted the place below that uses this bool, is that intentional?

if (hasZeroMapAnnotation)
{
m_pCompiler->fgAddFieldSeqForZeroOffset(ref, fldSeq);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Deleting this?

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, originally there were two places the zero map annotation got added -- in the def case, and below the join of the use/def. So it was possible to try and add the zero map annotation to the def twice.

Now we just rely on the common one below the join.

@AndyAyersMS
Copy link
Member Author

x86 test failure seems to be an instance of #33276.

@AndyAyersMS
Copy link
Member Author

Updated diffs, similar to before..

PMI CodeSize Diffs for System.Private.CoreLib.dll, framework assemblies for x64 default jit
Summary of Code Size diffs:
(Lower is better)
Total bytes of diff: 1072 (0.00% of base)
    diff is a regression.
Top file regressions (bytes):
         769 : System.Data.Common.dasm (0.05% of base)
         117 : System.Data.Odbc.dasm (0.06% of base)
          69 : System.Linq.Parallel.dasm (0.00% of base)
          48 : System.Data.OleDb.dasm (0.02% of base)
          37 : System.ComponentModel.Composition.dasm (0.01% of base)
          28 : Newtonsoft.Json.dasm (0.00% of base)
          27 : System.Collections.Immutable.dasm (0.00% of base)
          14 : ILCompiler.Reflection.ReadyToRun.dasm (0.01% of base)
          14 : System.Diagnostics.EventLog.dasm (0.02% of base)
          12 : System.Management.dasm (0.00% of base)
          10 : Microsoft.CSharp.dasm (0.00% of base)
          10 : System.Reflection.Metadata.dasm (0.00% of base)
          10 : System.Security.Cryptography.Cng.dasm (0.01% of base)
          10 : System.Text.Json.dasm (0.00% of base)
           9 : System.Security.Principal.Windows.dasm (0.02% of base)
           7 : System.Drawing.Common.dasm (0.00% of base)
           7 : System.Net.Http.dasm (0.00% of base)
           5 : System.Text.RegularExpressions.dasm (0.00% of base)
           4 : System.Net.Http.WinHttpHandler.dasm (0.00% of base)
           4 : System.Private.Xml.dasm (0.00% of base)
Top file improvements (bytes):
         -56 : System.Private.CoreLib.dasm (-0.00% of base)
         -26 : Microsoft.CodeAnalysis.dasm (-0.00% of base)
         -18 : System.Runtime.Serialization.Formatters.dasm (-0.02% of base)
         -13 : System.Reflection.MetadataLoadContext.dasm (-0.01% of base)
         -12 : System.Text.Encodings.Web.dasm (-0.04% of base)
          -7 : System.IO.IsolatedStorage.dasm (-0.04% of base)
          -5 : Microsoft.CodeAnalysis.CSharp.dasm (-0.00% of base)
          -5 : xunit.execution.dotnet.dasm (-0.00% of base)
          -5 : xunit.runner.utility.netcoreapp10.dasm (-0.00% of base)
          -3 : Microsoft.Diagnostics.Tracing.TraceEvent.dasm (-0.00% of base)
          -2 : System.Linq.Expressions.dasm (-0.00% of base)
36 total files with Code Size differences (11 improved, 25 regressed), 196 unchanged.
Top method regressions (bytes):
          75 ( 6.26% of base) : System.Data.Common.dasm - DoubleStorage:Aggregate(ref,int):Object:this
          75 ( 6.15% of base) : System.Data.Common.dasm - SingleStorage:Aggregate(ref,int):Object:this
          69 ( 3.67% of base) : System.Data.Odbc.dasm - OdbcDataReader:RetrieveKeyInfoFromStatistics(QualifiedTableName,bool):int:this
          69 ( 2.13% of base) : System.Linq.Parallel.dasm - SortHelper`2:QuickSortIndicesInPlace(GrowingArray`1,List`1,ubyte):this (7 methods)
          68 ( 4.46% of base) : System.Data.Common.dasm - UInt64Storage:Aggregate(ref,int):Object:this
          68 ( 4.47% of base) : System.Data.Common.dasm - Int64Storage:Aggregate(ref,int):Object:this
          47 ( 3.45% of base) : System.Data.Common.dasm - Int32Storage:Aggregate(ref,int):Object:this
          47 ( 3.47% of base) : System.Data.Common.dasm - UInt16Storage:Aggregate(ref,int):Object:this
          47 ( 3.46% of base) : System.Data.Common.dasm - UInt32Storage:Aggregate(ref,int):Object:this
          45 ( 3.27% of base) : System.Data.Common.dasm - Int16Storage:Aggregate(ref,int):Object:this
          42 ( 3.33% of base) : System.Data.Common.dasm - ByteStorage:Aggregate(ref,int):Object:this
          40 ( 3.12% of base) : System.Data.Common.dasm - SByteStorage:Aggregate(ref,int):Object:this
          37 ( 4.15% of base) : System.ComponentModel.Composition.dasm - GenericServices:Reorder(ref,ref):ref (7 methods)
          34 ( 2.43% of base) : System.Private.CoreLib.dasm - StringBuilder:AppendJoinCore(long,int,ref):StringBuilder:this (7 methods)
          32 ( 5.48% of base) : System.Data.Common.dasm - SqlBooleanStorage:Aggregate(ref,int):Object:this
          27 ( 0.71% of base) : System.Collections.Immutable.dasm - Builder:AddRange(ref,int):this (20 methods)
          24 ( 4.44% of base) : System.Data.Common.dasm - BooleanStorage:Aggregate(ref,int):Object:this
          24 ( 6.72% of base) : System.Data.Common.dasm - DateTimeStorage:SetStorage(Object,BitArray):this
          24 ( 8.33% of base) : System.Data.Common.dasm - SqlGuidStorage:Aggregate(ref,int):Object:this
          24 ( 8.33% of base) : System.Data.Common.dasm - SqlBinaryStorage:Aggregate(ref,int):Object:this
Top method improvements (bytes):
         -27 (-1.07% of base) : Microsoft.CodeAnalysis.dasm - <DescendantNodesAndTokensIntoTrivia>d__159:MoveNext():bool:this
         -26 (-3.76% of base) : System.Private.CoreLib.dasm - Sha1ForNonSecretPurposes:Drain():this
         -21 (-4.12% of base) : Microsoft.Diagnostics.Tracing.TraceEvent.dasm - PathUtil:PathRelativeTo(String,String):String
         -18 (-1.06% of base) : Microsoft.CodeAnalysis.dasm - <DescendantTriviaIntoTrivia>d__161:MoveNext():bool:this
         -18 (-6.64% of base) : System.Private.CoreLib.dasm - ObjectEqualityComparer`1:IndexOf(ref,short,int,int):int:this
         -16 (-5.99% of base) : System.Private.CoreLib.dasm - ObjectEqualityComparer`1:IndexOf(ref,long,int,int):int:this
         -15 (-6.00% of base) : System.Runtime.Serialization.Formatters.dasm - ObjectIDGenerator:GetId(Object,byref):long:this
         -14 (-5.36% of base) : System.Private.CoreLib.dasm - ObjectEqualityComparer`1:IndexOf(ref,int,int,int):int:this
         -13 (-1.05% of base) : System.Reflection.MetadataLoadContext.dasm - DefaultBinder:FindMostSpecific(ref,ref,Type,ref,ref,Type,ref,ref):int
          -9 (-6.62% of base) : System.Private.CoreLib.dasm - ObjectEqualityComparer`1:LastIndexOf(ref,short,int,int):int:this
          -9 (-6.16% of base) : System.Private.CoreLib.dasm - ObjectEqualityComparer`1:IndexOf(ref,double,int,int):int:this
          -9 (-6.08% of base) : System.Private.CoreLib.dasm - ObjectEqualityComparer`1:LastIndexOf(ref,double,int,int):int:this
          -8 (-6.11% of base) : System.Private.CoreLib.dasm - ObjectEqualityComparer`1:IndexOf(ref,ubyte,int,int):int:this
          -8 (-6.02% of base) : System.Private.CoreLib.dasm - ObjectEqualityComparer`1:LastIndexOf(ref,ubyte,int,int):int:this
          -8 (-5.97% of base) : System.Private.CoreLib.dasm - ObjectEqualityComparer`1:LastIndexOf(ref,long,int,int):int:this
          -7 (-3.47% of base) : Microsoft.CodeAnalysis.CSharp.dasm - PEModuleSymbol:HasAnyCustomAttributes(EntityHandle):bool:this
          -7 (-1.61% of base) : System.Data.Common.dasm - DataSet:MarkModifiedRows(ref,int):this
          -7 (-5.11% of base) : System.IO.IsolatedStorage.dasm - IsolatedStorageFile:GetFullPath(String):String:this
          -7 (-0.60% of base) : System.Private.CoreLib.dasm - DefaultBinder:FindMostSpecific(ref,ref,Type,ref,ref,Type,ref,ref):int
          -7 (-5.38% of base) : System.Private.CoreLib.dasm - ObjectEqualityComparer`1:LastIndexOf(ref,int,int,int):int:this
Top method regressions (percentages):
          10 (17.86% of base) : Microsoft.CSharp.dasm - <PrivateImplementationDetails>:ComputeStringHash(String):int
          10 (17.86% of base) : System.Data.Common.dasm - <PrivateImplementationDetails>:ComputeStringHash(String):int
          10 (17.86% of base) : System.Net.Http.dasm - <PrivateImplementationDetails>:ComputeStringHash(String):int
          10 (17.86% of base) : System.Private.CoreLib.dasm - <PrivateImplementationDetails>:ComputeStringHash(String):int
          10 (17.86% of base) : System.Private.Xml.dasm - <PrivateImplementationDetails>:ComputeStringHash(String):int
          10 (17.86% of base) : System.Reflection.Metadata.dasm - <PrivateImplementationDetails>:ComputeStringHash(String):int
          10 (17.86% of base) : System.Security.Cryptography.Algorithms.dasm - <PrivateImplementationDetails>:ComputeStringHash(String):int
          10 (17.86% of base) : System.Security.Cryptography.Cng.dasm - <PrivateImplementationDetails>:ComputeStringHash(String):int
          10 (17.86% of base) : System.Text.Json.dasm - <PrivateImplementationDetails>:ComputeStringHash(String):int
           7 ( 9.46% of base) : Microsoft.CodeAnalysis.dasm - StringTable:TextEqualsCore(String,ref,int):bool
          24 ( 8.33% of base) : System.Data.Common.dasm - SqlGuidStorage:Aggregate(ref,int):Object:this
          24 ( 8.33% of base) : System.Data.Common.dasm - SqlBinaryStorage:Aggregate(ref,int):Object:this
           8 ( 8.25% of base) : Newtonsoft.Json.dasm - JPath:Match(String):bool:this
          12 ( 8.11% of base) : System.Data.Odbc.dasm - DbBuffer:ReadTime(int):TimeSpan:this
          12 ( 8.11% of base) : System.Data.OleDb.dasm - DbBuffer:ReadTime(int):TimeSpan:this
           7 ( 8.05% of base) : Microsoft.CodeAnalysis.dasm - StringTable:TextEquals(String,String,int,int):bool
           7 ( 8.05% of base) : System.Private.Xml.dasm - NameTable:TextEquals(String,ref,int,int):bool
           8 ( 7.62% of base) : Newtonsoft.Json.dasm - StringReferenceExtensions:EndsWith(StringReference,String):bool
           7 ( 7.00% of base) : Newtonsoft.Json.dasm - StringReferenceExtensions:StartsWith(StringReference,String):bool
          24 ( 6.72% of base) : System.Data.Common.dasm - DateTimeStorage:SetStorage(Object,BitArray):this
Top method improvements (percentages):
         -18 (-6.64% of base) : System.Private.CoreLib.dasm - ObjectEqualityComparer`1:IndexOf(ref,short,int,int):int:this
          -9 (-6.62% of base) : System.Private.CoreLib.dasm - ObjectEqualityComparer`1:LastIndexOf(ref,short,int,int):int:this
          -9 (-6.16% of base) : System.Private.CoreLib.dasm - ObjectEqualityComparer`1:IndexOf(ref,double,int,int):int:this
          -8 (-6.11% of base) : System.Private.CoreLib.dasm - ObjectEqualityComparer`1:IndexOf(ref,ubyte,int,int):int:this
          -9 (-6.08% of base) : System.Private.CoreLib.dasm - ObjectEqualityComparer`1:LastIndexOf(ref,double,int,int):int:this
          -8 (-6.02% of base) : System.Private.CoreLib.dasm - ObjectEqualityComparer`1:LastIndexOf(ref,ubyte,int,int):int:this
         -15 (-6.00% of base) : System.Runtime.Serialization.Formatters.dasm - ObjectIDGenerator:GetId(Object,byref):long:this
         -16 (-5.99% of base) : System.Private.CoreLib.dasm - ObjectEqualityComparer`1:IndexOf(ref,long,int,int):int:this
          -8 (-5.97% of base) : System.Private.CoreLib.dasm - ObjectEqualityComparer`1:LastIndexOf(ref,long,int,int):int:this
          -7 (-5.38% of base) : System.Private.CoreLib.dasm - ObjectEqualityComparer`1:LastIndexOf(ref,int,int,int):int:this
         -14 (-5.36% of base) : System.Private.CoreLib.dasm - ObjectEqualityComparer`1:IndexOf(ref,int,int,int):int:this
          -7 (-5.11% of base) : System.IO.IsolatedStorage.dasm - IsolatedStorageFile:GetFullPath(String):String:this
          -7 (-4.27% of base) : System.Security.Cryptography.Algorithms.dasm - Helpers:FixupKeyParity(ref):ref
         -21 (-4.12% of base) : Microsoft.Diagnostics.Tracing.TraceEvent.dasm - PathUtil:PathRelativeTo(String,String):String
          -6 (-4.03% of base) : System.Private.CoreLib.dasm - GenericArraySortHelper`1:BinarySearch(ref,int,int,double):int
         -26 (-3.76% of base) : System.Private.CoreLib.dasm - Sha1ForNonSecretPurposes:Drain():this
          -6 (-3.73% of base) : System.Text.Encodings.Web.dasm - TextEncoderSettings:AllowCharacters(ref):this
          -6 (-3.64% of base) : System.Text.Encodings.Web.dasm - TextEncoderSettings:ForbidCharacters(ref):this
          -7 (-3.47% of base) : Microsoft.CodeAnalysis.CSharp.dasm - PEModuleSymbol:HasAnyCustomAttributes(EntityHandle):bool:this
          -7 (-3.14% of base) : System.Private.Xml.dasm - BinXmlSqlDecimal:TrimTrailingZeros():this
125 total methods with Code Size differences (36 improved, 89 regressed), 240169 unchanged.

@dotnet/jit-contrib anyone else have feedback? Think this is ready to merge.

Copy link
Member

@erozenfeld erozenfeld left a comment

Choose a reason for hiding this comment

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

LGTM
Just spotted one comment typo.

@@ -5552,8 +5552,15 @@ GenTree* Compiler::fgMorphArrayIndex(GenTree* tree)
// This is an array index expression.
tree->gtFlags |= GTF_IND_ARR_INDEX;

/* An indirection will cause a GPF if the address is null */
tree->gtFlags |= GTF_EXCEPT;
// If there's a bounds check, the the indir won't fault.
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
// If there's a bounds check, the the indir won't fault.
// If there's a bounds check, then the indir won't fault.

Copy link
Contributor

@briansull briansull left a comment

Choose a reason for hiding this comment

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

LGTM

@AndyAyersMS
Copy link
Member Author

Can revisit the REDO_RETURN_NODE cleanup once we're no longer retyping small struct returns in the importer (#33225).

@AndyAyersMS AndyAyersMS merged commit 5c981af into dotnet:master Mar 7, 2020
@AndyAyersMS AndyAyersMS deleted the RemoveGtfInxRefArrLayout branch March 7, 2020 18:34
@ghost ghost locked as resolved and limited conversation to collaborators Dec 10, 2020
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.

Delete GTF_INX_REFARR_LAYOUT
5 participants