summaryrefslogtreecommitdiff
path: root/packaging/0019-JIT-Fix-value-type-box-optimization.patch
diff options
context:
space:
mode:
Diffstat (limited to 'packaging/0019-JIT-Fix-value-type-box-optimization.patch')
-rw-r--r--packaging/0019-JIT-Fix-value-type-box-optimization.patch1215
1 files changed, 1215 insertions, 0 deletions
diff --git a/packaging/0019-JIT-Fix-value-type-box-optimization.patch b/packaging/0019-JIT-Fix-value-type-box-optimization.patch
new file mode 100644
index 0000000000..db31e3ff8f
--- /dev/null
+++ b/packaging/0019-JIT-Fix-value-type-box-optimization.patch
@@ -0,0 +1,1215 @@
+From dc2e9cc4c21e0cf565dbb1b4d4f029157779ddcc Mon Sep 17 00:00:00 2001
+From: Andy Ayers <andya@microsoft.com>
+Date: Sat, 22 Jul 2017 09:16:29 -0700
+Subject: [PATCH 19/47] JIT: Fix value type box optimization
+
+Boxing a value type produces a non-null result. If the result of the box is
+only used to feed a compare against null, the jit tries to optimize the box
+away entirely since the result of the comparison is known. Such idiomatic
+expressions arise fairly often in generics instantiated over value types.
+
+In the current implementation the box expands into two parts. The first is
+an upstream statement to allocate a boxed object and assign a reference to
+the boxed object to a local var known as the "box temp". The second is an
+expression tree whose value is the box temp that also contains an an
+encapsulated copy from the value being boxed to the payload section of the
+boxed object. The box node also contains a pointer back to the first
+statement (more on this later).
+
+In the examples being discussed here this second tree is a child of a compare
+node whose other child is a null pointer. When the optimization fires, the
+upstream allocation statement is located via the pointer in the box node and
+removed, and the entire compare is replaced with a constant 0 or 1 as
+appropriate. Unfortunately the encapsulated copy in the box subtree may
+include side effects that should be preserved, and so this transformation is
+unsafe.
+
+Note that the copy subtree as a whole will always contain side effects, since
+the copy is storing values into the heap, and that copy now will not happen.
+But the side effects that happen when producing the value to box must remain.
+
+In the initial example from #12949 the side effects in question were
+introduced by the jit's optimizer to capure a CSE definition. #13016 gives
+several other examples where the side effects are present in the initial user
+code. For instance the value being boxed might come from an array, in which
+case the encapsulated copy in the box expression tree would contain the array
+null check and bounds check. So removing the entire tree can alter behavior.
+
+This fix attempts to carefully preserve the important side effects by
+reworking how a box is imported. The copy is now moved out from under the box
+into a second upstream statement. The box itself is then just a trivial
+side-effect-free reference to the box temp. To ensure proper ordering of side
+effects the jit spills the evaluation stack before appending the copy
+statement.
+
+When the optimization fires the jit removes the upstream heap allocation
+as before, as well as the now-trivial compare tree. It analyzes the source
+side of the upstream copy. If it is side effect free, the copy is removed
+entirely. If not, the jit modifies the copy into a minimal load of the
+boxed value, and this load should reproduce the necessary side effects.
+
+The optimization is only performed when the tree shape of the copy matches
+expected patterns.
+
+There are some expected cases where the tree won't match, for instance if the
+optimization is invoked while the jit is inlining. Because this optimization
+runs at several points the jit can catch these cases once inlining completes.
+There is one case that is not handled that could be -- if the assignment part
+of the copy is itself a subtree of a comma. This doesn't happen often.
+
+The optimization is now also extended to handle the case where the comparision
+operation is `cgt.un`. This doesn't catch any new cases but causes the
+optimization to happen earlier, typically during importation, which should
+reduce jit time slightly.
+
+Generally the split of the box into two upstream statements reduces code size,
+especially when the box expression is incorporated into a larger tree -- for
+example a call. However in some cases where the value being boxed comes from
+an array, preserving the array bounds check now causes loop cloning to kick
+in and increase code size. Hence the overall size impact on the jit-diff set is
+essentially zero.
+
+Added a number of new test cases showing the variety of situations that must
+be handled and the need to spill before appending the copy statement.
+
+Fixes #12949.
+---
+ src/jit/gentree.cpp | 167 +++++++++++++++++++--
+ src/jit/gentree.h | 13 +-
+ src/jit/importer.cpp | 15 +-
+ .../JitBlue/GitHub_12949/GitHub_12949_1.cs | 51 +++++++
+ .../JitBlue/GitHub_12949/GitHub_12949_1.csproj | 43 ++++++
+ .../JitBlue/GitHub_12949/GitHub_12949_2.cs | 43 ++++++
+ .../JitBlue/GitHub_12949/GitHub_12949_2.csproj | 43 ++++++
+ .../JitBlue/GitHub_12949/GitHub_12949_3.cs | 41 +++++
+ .../JitBlue/GitHub_12949/GitHub_12949_3.csproj | 43 ++++++
+ .../JitBlue/GitHub_12949/GitHub_12949_4.cs | 41 +++++
+ .../JitBlue/GitHub_12949/GitHub_12949_4.csproj | 43 ++++++
+ .../JitBlue/GitHub_12949/GitHub_12949_5.cs | 46 ++++++
+ .../JitBlue/GitHub_12949/GitHub_12949_5.csproj | 43 ++++++
+ .../JitBlue/GitHub_12949/GitHub_12949_6.cs | 60 ++++++++
+ .../JitBlue/GitHub_12949/GitHub_12949_6.csproj | 43 ++++++
+ .../JitBlue/GitHub_12949/GitHub_12949_7.cs | 58 +++++++
+ .../JitBlue/GitHub_12949/GitHub_12949_7.csproj | 43 ++++++
+ .../JitBlue/GitHub_12949/GitHub_12949_8.cs | 42 ++++++
+ .../JitBlue/GitHub_12949/GitHub_12949_8.csproj | 43 ++++++
+ 19 files changed, 902 insertions(+), 19 deletions(-)
+ create mode 100644 tests/src/JIT/Regression/JitBlue/GitHub_12949/GitHub_12949_1.cs
+ create mode 100644 tests/src/JIT/Regression/JitBlue/GitHub_12949/GitHub_12949_1.csproj
+ create mode 100644 tests/src/JIT/Regression/JitBlue/GitHub_12949/GitHub_12949_2.cs
+ create mode 100644 tests/src/JIT/Regression/JitBlue/GitHub_12949/GitHub_12949_2.csproj
+ create mode 100644 tests/src/JIT/Regression/JitBlue/GitHub_12949/GitHub_12949_3.cs
+ create mode 100644 tests/src/JIT/Regression/JitBlue/GitHub_12949/GitHub_12949_3.csproj
+ create mode 100644 tests/src/JIT/Regression/JitBlue/GitHub_12949/GitHub_12949_4.cs
+ create mode 100644 tests/src/JIT/Regression/JitBlue/GitHub_12949/GitHub_12949_4.csproj
+ create mode 100644 tests/src/JIT/Regression/JitBlue/GitHub_12949/GitHub_12949_5.cs
+ create mode 100644 tests/src/JIT/Regression/JitBlue/GitHub_12949/GitHub_12949_5.csproj
+ create mode 100644 tests/src/JIT/Regression/JitBlue/GitHub_12949/GitHub_12949_6.cs
+ create mode 100644 tests/src/JIT/Regression/JitBlue/GitHub_12949/GitHub_12949_6.csproj
+ create mode 100644 tests/src/JIT/Regression/JitBlue/GitHub_12949/GitHub_12949_7.cs
+ create mode 100644 tests/src/JIT/Regression/JitBlue/GitHub_12949/GitHub_12949_7.csproj
+ create mode 100644 tests/src/JIT/Regression/JitBlue/GitHub_12949/GitHub_12949_8.cs
+ create mode 100644 tests/src/JIT/Regression/JitBlue/GitHub_12949/GitHub_12949_8.csproj
+
+diff --git a/src/jit/gentree.cpp b/src/jit/gentree.cpp
+index 25e9e10..3736f7a 100644
+--- a/src/jit/gentree.cpp
++++ b/src/jit/gentree.cpp
+@@ -8050,7 +8050,8 @@ GenTreePtr Compiler::gtCloneExpr(
+
+ case GT_BOX:
+ copy = new (this, GT_BOX)
+- GenTreeBox(tree->TypeGet(), tree->gtOp.gtOp1, tree->gtBox.gtAsgStmtWhenInlinedBoxValue);
++ GenTreeBox(tree->TypeGet(), tree->gtOp.gtOp1, tree->gtBox.gtAsgStmtWhenInlinedBoxValue,
++ tree->gtBox.gtCopyStmtWhenInlinedBoxValue);
+ break;
+
+ case GT_INTRINSIC:
+@@ -12459,32 +12460,168 @@ GenTreePtr Compiler::gtFoldExprSpecial(GenTreePtr tree)
+
+ switch (oper)
+ {
+-
+ case GT_EQ:
+ case GT_NE:
++ case GT_GT:
+ // Optimize boxed value classes; these are always false. This IL is
+ // generated when a generic value is tested against null:
+ // <T> ... foo(T x) { ... if ((object)x == null) ...
+ if (val == 0 && op->IsBoxedValue())
+ {
+- // Change the assignment node so we don't generate any code for it.
++ // The tree under the box must be side effect free
++ // since we drop it if we optimize the compare.
++ assert(!gtTreeHasSideEffects(op->gtBox.gtOp.gtOp1, GTF_SIDE_EFFECT));
+
++ // grab related parts for the optimization
+ GenTreePtr asgStmt = op->gtBox.gtAsgStmtWhenInlinedBoxValue;
+ assert(asgStmt->gtOper == GT_STMT);
+- GenTreePtr asg = asgStmt->gtStmt.gtStmtExpr;
+- assert(asg->gtOper == GT_ASG);
++ GenTreePtr copyStmt = op->gtBox.gtCopyStmtWhenInlinedBoxValue;
++ assert(copyStmt->gtOper == GT_STMT);
+ #ifdef DEBUG
+ if (verbose)
+ {
+- printf("Bashing ");
+- printTreeID(asg);
+- printf(" to NOP as part of dead box operation\n");
++ printf("\nAttempting to optimize BOX(valueType) %s null\n", GenTree::OpName(oper));
+ gtDispTree(tree);
++ printf("\nWith assign\n");
++ gtDispTree(asgStmt);
++ printf("\nAnd copy\n");
++ gtDispTree(copyStmt);
+ }
+ #endif
++
++ // We don't expect GT_GT with signed compares, and we
++ // can't predict the result if we do see it, since the
++ // boxed object addr could have its high bit set.
++ if ((oper == GT_GT) && !tree->IsUnsigned())
++ {
++ JITDUMP(" bailing; unexpected signed compare via GT_GT\n");
++ goto FAIL;
++ }
++
++ // If we don't recognize the form of the assign, bail.
++ GenTreePtr asg = asgStmt->gtStmt.gtStmtExpr;
++ if (asg->gtOper != GT_ASG)
++ {
++ JITDUMP(" bailing; unexpected assignment op %s\n", GenTree::OpName(asg->gtOper));
++ goto FAIL;
++ }
++
++ // If we don't recognize the form of the copy, bail.
++ GenTree* copy = copyStmt->gtStmt.gtStmtExpr;
++ if (copy->gtOper != GT_ASG)
++ {
++ // GT_RET_EXPR is a tolerable temporary failure.
++ // The jit will revisit this optimization after
++ // inlining is done.
++ if (copy->gtOper == GT_RET_EXPR)
++ {
++ JITDUMP(" bailing; must wait for replacement of copy %s\n", GenTree::OpName(copy->gtOper));
++ }
++ else
++ {
++ // Anything else is a missed case we should
++ // figure out how to handle. One known case
++ // is GT_COMMAs enclosing the GT_ASG we are
++ // looking for.
++ JITDUMP(" bailing; unexpected copy op %s\n", GenTree::OpName(copy->gtOper));
++ }
++ goto FAIL;
++ }
++
++ // If the copy is a struct copy, make sure we know how to isolate
++ // any source side effects.
++ GenTreePtr copySrc = copy->gtOp.gtOp2;
++
++ // If the copy source is from a pending inline, wait for it to resolve.
++ if (copySrc->gtOper == GT_RET_EXPR)
++ {
++ JITDUMP(" bailing; must wait for replacement of copy source %s\n",
++ GenTree::OpName(copySrc->gtOper));
++ goto FAIL;
++ }
++
++ bool hasSrcSideEffect = false;
++ bool isStructCopy = false;
++
++ if (gtTreeHasSideEffects(copySrc, GTF_SIDE_EFFECT))
++ {
++ hasSrcSideEffect = true;
++
++ if (copySrc->gtType == TYP_STRUCT)
++ {
++ isStructCopy = true;
++
++ if ((copySrc->gtOper != GT_OBJ) && (copySrc->gtOper != GT_IND) && (copySrc->gtOper != GT_FIELD))
++ {
++ // We don't know how to handle other cases, yet.
++ JITDUMP(" bailing; unexpected copy source struct op with side effect %s\n",
++ GenTree::OpName(copySrc->gtOper));
++ goto FAIL;
++ }
++ }
++ }
++
++ // Proceed with the optimization
++ //
++ // Change the assignment expression to a NOP.
++ JITDUMP("\nBashing NEWOBJ [%06u] to NOP\n", dspTreeID(asg));
+ asg->gtBashToNOP();
+
+- op = gtNewIconNode(oper == GT_NE);
++ // Change the copy expression so it preserves key
++ // source side effects.
++ JITDUMP("\nBashing COPY [%06u]", dspTreeID(copy));
++
++ if (!hasSrcSideEffect)
++ {
++ // If there were no copy source side effects just bash
++ // the copy to a NOP.
++ copy->gtBashToNOP();
++ JITDUMP(" to NOP\n");
++ }
++ else if (!isStructCopy)
++ {
++ // For scalar types, go ahead and produce the
++ // value as the copy is fairly cheap and likely
++ // the optimizer can trim things down to just the
++ // minimal side effect parts.
++ copyStmt->gtStmt.gtStmtExpr = copySrc;
++ JITDUMP(" to scalar read via [%06u]\n", dspTreeID(copySrc));
++ }
++ else
++ {
++ // For struct types read the first byte of the
++ // source struct; there's no need to read the
++ // entire thing, and no place to put it.
++ assert(copySrc->gtOper == GT_OBJ || copySrc->gtOper == GT_IND || copySrc->gtOper == GT_FIELD);
++ copySrc->ChangeOper(GT_IND);
++ copySrc->gtType = TYP_BYTE;
++ copyStmt->gtStmt.gtStmtExpr = copySrc;
++ JITDUMP(" to read first byte of struct via modified [%06u]\n", dspTreeID(copySrc));
++ }
++
++ // Set up the result of the compare.
++ int compareResult = 0;
++ if (oper == GT_GT)
++ {
++ // GT_GT(null, box) == false
++ // GT_GT(box, null) == true
++ compareResult = (op1 == op);
++ }
++ else if (oper == GT_EQ)
++ {
++ // GT_EQ(box, null) == false
++ // GT_EQ(null, box) == false
++ compareResult = 0;
++ }
++ else
++ {
++ assert(oper == GT_NE);
++ // GT_NE(box, null) == true
++ // GT_NE(null, box) == true
++ compareResult = 1;
++ }
++ op = gtNewIconNode(compareResult);
++
+ if (fgGlobalMorph)
+ {
+ if (!fgIsInlining())
+@@ -12497,9 +12634,15 @@ GenTreePtr Compiler::gtFoldExprSpecial(GenTreePtr tree)
+ op->gtNext = tree->gtNext;
+ op->gtPrev = tree->gtPrev;
+ }
+- fgSetStmtSeq(asgStmt);
++
++ if (fgStmtListThreaded)
++ {
++ fgSetStmtSeq(asgStmt);
++ fgSetStmtSeq(copyStmt);
++ }
+ return op;
+ }
++
+ break;
+
+ case GT_ADD:
+@@ -12667,7 +12810,9 @@ GenTreePtr Compiler::gtFoldExprSpecial(GenTreePtr tree)
+ break;
+ }
+
+- /* The node is not foldable */
++/* The node is not foldable */
++
++FAIL:
+
+ return tree;
+
+diff --git a/src/jit/gentree.h b/src/jit/gentree.h
+index 1833a39..41f65f0 100644
+--- a/src/jit/gentree.h
++++ b/src/jit/gentree.h
+@@ -2848,9 +2848,16 @@ struct GenTreeBox : public GenTreeUnOp
+ // This is the statement that contains the assignment tree when the node is an inlined GT_BOX on a value
+ // type
+ GenTreePtr gtAsgStmtWhenInlinedBoxValue;
+-
+- GenTreeBox(var_types type, GenTreePtr boxOp, GenTreePtr asgStmtWhenInlinedBoxValue)
+- : GenTreeUnOp(GT_BOX, type, boxOp), gtAsgStmtWhenInlinedBoxValue(asgStmtWhenInlinedBoxValue)
++ // And this is the statement that copies from the value being boxed to the box payload
++ GenTreePtr gtCopyStmtWhenInlinedBoxValue;
++
++ GenTreeBox(var_types type,
++ GenTreePtr boxOp,
++ GenTreePtr asgStmtWhenInlinedBoxValue,
++ GenTreePtr copyStmtWhenInlinedBoxValue)
++ : GenTreeUnOp(GT_BOX, type, boxOp)
++ , gtAsgStmtWhenInlinedBoxValue(asgStmtWhenInlinedBoxValue)
++ , gtCopyStmtWhenInlinedBoxValue(copyStmtWhenInlinedBoxValue)
+ {
+ }
+ #if DEBUGGABLE_GENTREE
+diff --git a/src/jit/importer.cpp b/src/jit/importer.cpp
+index 62f1c13..b4ee1d0 100644
+--- a/src/jit/importer.cpp
++++ b/src/jit/importer.cpp
+@@ -5225,7 +5225,7 @@ void Compiler::impImportAndPushBox(CORINFO_RESOLVED_TOKEN* pResolvedToken)
+ gtNewArgList(op2));
+ }
+
+- /* Remember that this basic block contains 'new' of an array */
++ /* Remember that this basic block contains 'new' of an object */
+ compCurBB->bbFlags |= BBF_HAS_NEWOBJ;
+
+ GenTreePtr asg = gtNewTempAssign(impBoxTemp, op1);
+@@ -5267,11 +5267,16 @@ void Compiler::impImportAndPushBox(CORINFO_RESOLVED_TOKEN* pResolvedToken)
+ op1 = gtNewAssignNode(gtNewOperNode(GT_IND, lclTyp, op1), exprToBox);
+ }
+
+- op2 = gtNewLclvNode(impBoxTemp, TYP_REF);
+- op1 = gtNewOperNode(GT_COMMA, TYP_REF, op1, op2);
++ // Spill eval stack to flush out any pending side effects.
++ impSpillSideEffects(true, (unsigned)CHECK_SPILL_ALL DEBUGARG("impImportAndPushBox"));
+
+- // Record that this is a "box" node.
+- op1 = new (this, GT_BOX) GenTreeBox(TYP_REF, op1, asgStmt);
++ // Set up this copy as a second assignment.
++ GenTreePtr copyStmt = impAppendTree(op1, (unsigned)CHECK_SPILL_NONE, impCurStmtOffs);
++
++ op1 = gtNewLclvNode(impBoxTemp, TYP_REF);
++
++ // Record that this is a "box" node and keep track of the matching parts.
++ op1 = new (this, GT_BOX) GenTreeBox(TYP_REF, op1, asgStmt, copyStmt);
+
+ // If it is a value class, mark the "box" node. We can use this information
+ // to optimise several cases:
+diff --git a/tests/src/JIT/Regression/JitBlue/GitHub_12949/GitHub_12949_1.cs b/tests/src/JIT/Regression/JitBlue/GitHub_12949/GitHub_12949_1.cs
+new file mode 100644
+index 0000000..c436802
+--- /dev/null
++++ b/tests/src/JIT/Regression/JitBlue/GitHub_12949/GitHub_12949_1.cs
+@@ -0,0 +1,51 @@
++// Licensed to the .NET Foundation under one or more agreements.
++// The .NET Foundation licenses this file to you under the MIT license.
++// See the LICENSE file in the project root for more information.
++
++using System;
++
++public struct S<K>
++{
++ public int x;
++ public int y;
++ public K val;
++}
++
++public class X<K,V>
++{
++ public X(K k)
++ {
++ a = new S<K>[2];
++ a[1].val = k;
++ a[1].x = 3;
++ a[1].y = 4;
++ }
++
++ public void Assert(bool b)
++ {
++ if (!b) throw new Exception("bad!");
++ }
++
++ public int Test()
++ {
++ int r = 0;
++ for (int i = 0; i < a.Length; i++)
++ {
++ Assert(a[i].val != null);
++ r += a[i].val.GetHashCode();
++ }
++ return r;
++ }
++
++ S<K>[] a;
++}
++
++class B
++{
++ public static int Main()
++ {
++ var a = new X<int, string>(11);
++ int z = a.Test();
++ return (z == 11 ? 100 : 0);
++ }
++}
+diff --git a/tests/src/JIT/Regression/JitBlue/GitHub_12949/GitHub_12949_1.csproj b/tests/src/JIT/Regression/JitBlue/GitHub_12949/GitHub_12949_1.csproj
+new file mode 100644
+index 0000000..5cd573d
+--- /dev/null
++++ b/tests/src/JIT/Regression/JitBlue/GitHub_12949/GitHub_12949_1.csproj
+@@ -0,0 +1,43 @@
++<?xml version="1.0" encoding="utf-8"?>
++<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
++ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
++ <PropertyGroup>
++ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
++ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
++ <AssemblyName>$(MSBuildProjectName)</AssemblyName>
++ <SchemaVersion>2.0</SchemaVersion>
++ <ProjectGuid>{7B521917-193E-48BB-86C6-FE013F3DFF35}</ProjectGuid>
++ <OutputType>Exe</OutputType>
++ <AppDesignerFolder>Properties</AppDesignerFolder>
++ <FileAlignment>512</FileAlignment>
++ <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
++ <ReferencePath>$(ProgramFiles)\Common Files\microsoft shared\VSTT\11.0\UITestExtensionPackages</ReferencePath>
++ <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
++
++ <NuGetPackageImportStamp>7a9bfb7d</NuGetPackageImportStamp>
++ </PropertyGroup>
++ <!-- Default configurations to help VS understand the configurations -->
++ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
++ </PropertyGroup>
++ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
++ </PropertyGroup>
++ <ItemGroup>
++ <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
++ <Visible>False</Visible>
++ </CodeAnalysisDependentAssemblyPaths>
++ </ItemGroup>
++ <PropertyGroup>
++ <DebugType></DebugType>
++ <Optimize>True</Optimize>
++ <AllowUnsafeBlocks>True</AllowUnsafeBlocks>
++ </PropertyGroup>
++ <ItemGroup>
++ <Compile Include="$(MSBuildProjectName).cs" />
++ </ItemGroup>
++ <ItemGroup>
++ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
++ </ItemGroup>
++ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
++ <PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' ">
++ </PropertyGroup>
++</Project>
+diff --git a/tests/src/JIT/Regression/JitBlue/GitHub_12949/GitHub_12949_2.cs b/tests/src/JIT/Regression/JitBlue/GitHub_12949/GitHub_12949_2.cs
+new file mode 100644
+index 0000000..bbdc67d
+--- /dev/null
++++ b/tests/src/JIT/Regression/JitBlue/GitHub_12949/GitHub_12949_2.cs
+@@ -0,0 +1,43 @@
++// Licensed to the .NET Foundation under one or more agreements.
++// The .NET Foundation licenses this file to you under the MIT license.
++// See the LICENSE file in the project root for more information.
++
++using System;
++using System.Runtime.CompilerServices;
++
++public class X<K>
++{
++ public X(K k1)
++ {
++ k = k1;
++ }
++
++ [MethodImpl(MethodImplOptions.NoInlining)]
++ public K Get()
++ {
++ Console.WriteLine("Get called");
++ count++;
++ return k;
++ }
++
++ public bool Test()
++ {
++ bool x = Get() != null;
++ bool y = (count == 1);
++ return x && y;
++ }
++
++ K k;
++ int count;
++}
++
++class B
++{
++ public static int Main()
++ {
++ var a = new X<int>(11);
++ bool result = a.Test();
++ Console.WriteLine("Passed: {0}", result);
++ return result ? 100 : 0;
++ }
++}
+diff --git a/tests/src/JIT/Regression/JitBlue/GitHub_12949/GitHub_12949_2.csproj b/tests/src/JIT/Regression/JitBlue/GitHub_12949/GitHub_12949_2.csproj
+new file mode 100644
+index 0000000..5cd573d
+--- /dev/null
++++ b/tests/src/JIT/Regression/JitBlue/GitHub_12949/GitHub_12949_2.csproj
+@@ -0,0 +1,43 @@
++<?xml version="1.0" encoding="utf-8"?>
++<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
++ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
++ <PropertyGroup>
++ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
++ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
++ <AssemblyName>$(MSBuildProjectName)</AssemblyName>
++ <SchemaVersion>2.0</SchemaVersion>
++ <ProjectGuid>{7B521917-193E-48BB-86C6-FE013F3DFF35}</ProjectGuid>
++ <OutputType>Exe</OutputType>
++ <AppDesignerFolder>Properties</AppDesignerFolder>
++ <FileAlignment>512</FileAlignment>
++ <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
++ <ReferencePath>$(ProgramFiles)\Common Files\microsoft shared\VSTT\11.0\UITestExtensionPackages</ReferencePath>
++ <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
++
++ <NuGetPackageImportStamp>7a9bfb7d</NuGetPackageImportStamp>
++ </PropertyGroup>
++ <!-- Default configurations to help VS understand the configurations -->
++ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
++ </PropertyGroup>
++ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
++ </PropertyGroup>
++ <ItemGroup>
++ <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
++ <Visible>False</Visible>
++ </CodeAnalysisDependentAssemblyPaths>
++ </ItemGroup>
++ <PropertyGroup>
++ <DebugType></DebugType>
++ <Optimize>True</Optimize>
++ <AllowUnsafeBlocks>True</AllowUnsafeBlocks>
++ </PropertyGroup>
++ <ItemGroup>
++ <Compile Include="$(MSBuildProjectName).cs" />
++ </ItemGroup>
++ <ItemGroup>
++ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
++ </ItemGroup>
++ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
++ <PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' ">
++ </PropertyGroup>
++</Project>
+diff --git a/tests/src/JIT/Regression/JitBlue/GitHub_12949/GitHub_12949_3.cs b/tests/src/JIT/Regression/JitBlue/GitHub_12949/GitHub_12949_3.cs
+new file mode 100644
+index 0000000..b7247c1
+--- /dev/null
++++ b/tests/src/JIT/Regression/JitBlue/GitHub_12949/GitHub_12949_3.cs
+@@ -0,0 +1,41 @@
++// Licensed to the .NET Foundation under one or more agreements.
++// The .NET Foundation licenses this file to you under the MIT license.
++// See the LICENSE file in the project root for more information.
++
++using System;
++using System.Runtime.CompilerServices;
++
++public class X<K>
++{
++ public X(K k1)
++ {
++ k = k1;
++ }
++
++ [MethodImpl(MethodImplOptions.NoInlining)]
++ public static bool Test(X<K> a)
++ {
++ return (a.k != null);
++ }
++
++ public K k;
++}
++
++class B
++{
++ public static int Main()
++ {
++ X<int> a = null;
++ bool result = false;
++ try
++ {
++ X<int>.Test(a);
++ }
++ catch (Exception)
++ {
++ result = true;
++ }
++ Console.WriteLine("Passed: {0}", result);
++ return result ? 100 : 0;
++ }
++}
+diff --git a/tests/src/JIT/Regression/JitBlue/GitHub_12949/GitHub_12949_3.csproj b/tests/src/JIT/Regression/JitBlue/GitHub_12949/GitHub_12949_3.csproj
+new file mode 100644
+index 0000000..5cd573d
+--- /dev/null
++++ b/tests/src/JIT/Regression/JitBlue/GitHub_12949/GitHub_12949_3.csproj
+@@ -0,0 +1,43 @@
++<?xml version="1.0" encoding="utf-8"?>
++<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
++ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
++ <PropertyGroup>
++ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
++ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
++ <AssemblyName>$(MSBuildProjectName)</AssemblyName>
++ <SchemaVersion>2.0</SchemaVersion>
++ <ProjectGuid>{7B521917-193E-48BB-86C6-FE013F3DFF35}</ProjectGuid>
++ <OutputType>Exe</OutputType>
++ <AppDesignerFolder>Properties</AppDesignerFolder>
++ <FileAlignment>512</FileAlignment>
++ <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
++ <ReferencePath>$(ProgramFiles)\Common Files\microsoft shared\VSTT\11.0\UITestExtensionPackages</ReferencePath>
++ <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
++
++ <NuGetPackageImportStamp>7a9bfb7d</NuGetPackageImportStamp>
++ </PropertyGroup>
++ <!-- Default configurations to help VS understand the configurations -->
++ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
++ </PropertyGroup>
++ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
++ </PropertyGroup>
++ <ItemGroup>
++ <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
++ <Visible>False</Visible>
++ </CodeAnalysisDependentAssemblyPaths>
++ </ItemGroup>
++ <PropertyGroup>
++ <DebugType></DebugType>
++ <Optimize>True</Optimize>
++ <AllowUnsafeBlocks>True</AllowUnsafeBlocks>
++ </PropertyGroup>
++ <ItemGroup>
++ <Compile Include="$(MSBuildProjectName).cs" />
++ </ItemGroup>
++ <ItemGroup>
++ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
++ </ItemGroup>
++ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
++ <PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' ">
++ </PropertyGroup>
++</Project>
+diff --git a/tests/src/JIT/Regression/JitBlue/GitHub_12949/GitHub_12949_4.cs b/tests/src/JIT/Regression/JitBlue/GitHub_12949/GitHub_12949_4.cs
+new file mode 100644
+index 0000000..126cdb9
+--- /dev/null
++++ b/tests/src/JIT/Regression/JitBlue/GitHub_12949/GitHub_12949_4.cs
+@@ -0,0 +1,41 @@
++// Licensed to the .NET Foundation under one or more agreements.
++// The .NET Foundation licenses this file to you under the MIT license.
++// See the LICENSE file in the project root for more information.
++
++using System;
++using System.Runtime.CompilerServices;
++
++public class X<K>
++{
++ public X(K k1)
++ {
++ k = k1;
++ }
++
++ [MethodImpl(MethodImplOptions.NoInlining)]
++ public static bool Test(X<K> a)
++ {
++ return (a.k == null);
++ }
++
++ public K k;
++}
++
++class B
++{
++ public static int Main()
++ {
++ X<int> a = null;
++ bool result = false;
++ try
++ {
++ X<int>.Test(a);
++ }
++ catch (Exception)
++ {
++ result = true;
++ }
++ Console.WriteLine("Passed: {0}", result);
++ return result ? 100 : 0;
++ }
++}
+diff --git a/tests/src/JIT/Regression/JitBlue/GitHub_12949/GitHub_12949_4.csproj b/tests/src/JIT/Regression/JitBlue/GitHub_12949/GitHub_12949_4.csproj
+new file mode 100644
+index 0000000..5cd573d
+--- /dev/null
++++ b/tests/src/JIT/Regression/JitBlue/GitHub_12949/GitHub_12949_4.csproj
+@@ -0,0 +1,43 @@
++<?xml version="1.0" encoding="utf-8"?>
++<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
++ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
++ <PropertyGroup>
++ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
++ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
++ <AssemblyName>$(MSBuildProjectName)</AssemblyName>
++ <SchemaVersion>2.0</SchemaVersion>
++ <ProjectGuid>{7B521917-193E-48BB-86C6-FE013F3DFF35}</ProjectGuid>
++ <OutputType>Exe</OutputType>
++ <AppDesignerFolder>Properties</AppDesignerFolder>
++ <FileAlignment>512</FileAlignment>
++ <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
++ <ReferencePath>$(ProgramFiles)\Common Files\microsoft shared\VSTT\11.0\UITestExtensionPackages</ReferencePath>
++ <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
++
++ <NuGetPackageImportStamp>7a9bfb7d</NuGetPackageImportStamp>
++ </PropertyGroup>
++ <!-- Default configurations to help VS understand the configurations -->
++ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
++ </PropertyGroup>
++ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
++ </PropertyGroup>
++ <ItemGroup>
++ <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
++ <Visible>False</Visible>
++ </CodeAnalysisDependentAssemblyPaths>
++ </ItemGroup>
++ <PropertyGroup>
++ <DebugType></DebugType>
++ <Optimize>True</Optimize>
++ <AllowUnsafeBlocks>True</AllowUnsafeBlocks>
++ </PropertyGroup>
++ <ItemGroup>
++ <Compile Include="$(MSBuildProjectName).cs" />
++ </ItemGroup>
++ <ItemGroup>
++ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
++ </ItemGroup>
++ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
++ <PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' ">
++ </PropertyGroup>
++</Project>
+diff --git a/tests/src/JIT/Regression/JitBlue/GitHub_12949/GitHub_12949_5.cs b/tests/src/JIT/Regression/JitBlue/GitHub_12949/GitHub_12949_5.cs
+new file mode 100644
+index 0000000..95a8945
+--- /dev/null
++++ b/tests/src/JIT/Regression/JitBlue/GitHub_12949/GitHub_12949_5.cs
+@@ -0,0 +1,46 @@
++// Licensed to the .NET Foundation under one or more agreements.
++// The .NET Foundation licenses this file to you under the MIT license.
++// See the LICENSE file in the project root for more information.
++
++using System;
++using System.Runtime.CompilerServices;
++
++struct R
++{
++ int a;
++}
++
++public class X<K>
++{
++ public X(K k1)
++ {
++ k = k1;
++ }
++
++ [MethodImpl(MethodImplOptions.NoInlining)]
++ public static bool Test(X<K> a)
++ {
++ return (a.k != null);
++ }
++
++ public K k;
++}
++
++class B
++{
++ public static int Main()
++ {
++ X<R> a = null;
++ bool result = false;
++ try
++ {
++ X<R>.Test(a);
++ }
++ catch (Exception)
++ {
++ result = true;
++ }
++ Console.WriteLine("Passed: {0}", result);
++ return result ? 100 : 0;
++ }
++}
+diff --git a/tests/src/JIT/Regression/JitBlue/GitHub_12949/GitHub_12949_5.csproj b/tests/src/JIT/Regression/JitBlue/GitHub_12949/GitHub_12949_5.csproj
+new file mode 100644
+index 0000000..5cd573d
+--- /dev/null
++++ b/tests/src/JIT/Regression/JitBlue/GitHub_12949/GitHub_12949_5.csproj
+@@ -0,0 +1,43 @@
++<?xml version="1.0" encoding="utf-8"?>
++<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
++ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
++ <PropertyGroup>
++ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
++ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
++ <AssemblyName>$(MSBuildProjectName)</AssemblyName>
++ <SchemaVersion>2.0</SchemaVersion>
++ <ProjectGuid>{7B521917-193E-48BB-86C6-FE013F3DFF35}</ProjectGuid>
++ <OutputType>Exe</OutputType>
++ <AppDesignerFolder>Properties</AppDesignerFolder>
++ <FileAlignment>512</FileAlignment>
++ <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
++ <ReferencePath>$(ProgramFiles)\Common Files\microsoft shared\VSTT\11.0\UITestExtensionPackages</ReferencePath>
++ <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
++
++ <NuGetPackageImportStamp>7a9bfb7d</NuGetPackageImportStamp>
++ </PropertyGroup>
++ <!-- Default configurations to help VS understand the configurations -->
++ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
++ </PropertyGroup>
++ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
++ </PropertyGroup>
++ <ItemGroup>
++ <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
++ <Visible>False</Visible>
++ </CodeAnalysisDependentAssemblyPaths>
++ </ItemGroup>
++ <PropertyGroup>
++ <DebugType></DebugType>
++ <Optimize>True</Optimize>
++ <AllowUnsafeBlocks>True</AllowUnsafeBlocks>
++ </PropertyGroup>
++ <ItemGroup>
++ <Compile Include="$(MSBuildProjectName).cs" />
++ </ItemGroup>
++ <ItemGroup>
++ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
++ </ItemGroup>
++ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
++ <PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' ">
++ </PropertyGroup>
++</Project>
+diff --git a/tests/src/JIT/Regression/JitBlue/GitHub_12949/GitHub_12949_6.cs b/tests/src/JIT/Regression/JitBlue/GitHub_12949/GitHub_12949_6.cs
+new file mode 100644
+index 0000000..1371dbb
+--- /dev/null
++++ b/tests/src/JIT/Regression/JitBlue/GitHub_12949/GitHub_12949_6.cs
+@@ -0,0 +1,60 @@
++// Licensed to the .NET Foundation under one or more agreements.
++// The .NET Foundation licenses this file to you under the MIT license.
++// See the LICENSE file in the project root for more information.
++
++using System;
++using System.Runtime.CompilerServices;
++
++public interface IGet
++{
++ int Get();
++}
++
++public struct R : IGet
++{
++ public double d;
++ public int a;
++
++ public int Get() { return a; }
++}
++
++public class X<K> where K: IGet
++{
++ public X(K r)
++ {
++ a = new K[2];
++ a[0] = r;
++ }
++
++ public void Assert(bool b)
++ {
++ if (!b) throw new Exception("bad!");
++ }
++
++ public int Test()
++ {
++ int r = 0;
++ for (int i = 0; i < a.Length; i++)
++ {
++ Assert(a[i] != null);
++ r += a[i].Get();
++ }
++ return r;
++ }
++
++ K[] a;
++}
++
++class B
++{
++ public static int Main()
++ {
++ var r = new R();
++ r.a = 3;
++ var a = new X<R>(r);
++ int result = a.Test();
++ bool passed = result == 3;
++ Console.WriteLine("Passed: {0}", passed);
++ return passed ? 100 : 0;
++ }
++}
+diff --git a/tests/src/JIT/Regression/JitBlue/GitHub_12949/GitHub_12949_6.csproj b/tests/src/JIT/Regression/JitBlue/GitHub_12949/GitHub_12949_6.csproj
+new file mode 100644
+index 0000000..5cd573d
+--- /dev/null
++++ b/tests/src/JIT/Regression/JitBlue/GitHub_12949/GitHub_12949_6.csproj
+@@ -0,0 +1,43 @@
++<?xml version="1.0" encoding="utf-8"?>
++<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
++ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
++ <PropertyGroup>
++ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
++ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
++ <AssemblyName>$(MSBuildProjectName)</AssemblyName>
++ <SchemaVersion>2.0</SchemaVersion>
++ <ProjectGuid>{7B521917-193E-48BB-86C6-FE013F3DFF35}</ProjectGuid>
++ <OutputType>Exe</OutputType>
++ <AppDesignerFolder>Properties</AppDesignerFolder>
++ <FileAlignment>512</FileAlignment>
++ <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
++ <ReferencePath>$(ProgramFiles)\Common Files\microsoft shared\VSTT\11.0\UITestExtensionPackages</ReferencePath>
++ <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
++
++ <NuGetPackageImportStamp>7a9bfb7d</NuGetPackageImportStamp>
++ </PropertyGroup>
++ <!-- Default configurations to help VS understand the configurations -->
++ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
++ </PropertyGroup>
++ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
++ </PropertyGroup>
++ <ItemGroup>
++ <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
++ <Visible>False</Visible>
++ </CodeAnalysisDependentAssemblyPaths>
++ </ItemGroup>
++ <PropertyGroup>
++ <DebugType></DebugType>
++ <Optimize>True</Optimize>
++ <AllowUnsafeBlocks>True</AllowUnsafeBlocks>
++ </PropertyGroup>
++ <ItemGroup>
++ <Compile Include="$(MSBuildProjectName).cs" />
++ </ItemGroup>
++ <ItemGroup>
++ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
++ </ItemGroup>
++ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
++ <PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' ">
++ </PropertyGroup>
++</Project>
+diff --git a/tests/src/JIT/Regression/JitBlue/GitHub_12949/GitHub_12949_7.cs b/tests/src/JIT/Regression/JitBlue/GitHub_12949/GitHub_12949_7.cs
+new file mode 100644
+index 0000000..3ba6cd2
+--- /dev/null
++++ b/tests/src/JIT/Regression/JitBlue/GitHub_12949/GitHub_12949_7.cs
+@@ -0,0 +1,58 @@
++// Licensed to the .NET Foundation under one or more agreements.
++// The .NET Foundation licenses this file to you under the MIT license.
++// See the LICENSE file in the project root for more information.
++
++using System;
++
++public struct V
++{
++ public V(int x)
++ {
++ Token = x;
++ }
++
++ public int Token;
++}
++
++class M
++{
++ static int F(int x, object a)
++ {
++ int result = 0;
++
++ if (a is V)
++ {
++ int token = ((V)a).Token;
++ Console.WriteLine("F: Token is {0}", token);
++ result = x + token;
++ }
++
++ return result;
++ }
++
++ static int G(object a, int x)
++ {
++ return F(x, a);
++ }
++
++ static int Trouble(ref V v)
++ {
++ Console.WriteLine("T: Token is {0}", v.Token);
++ int result = v.Token;
++ v.Token++;
++ return result;
++ }
++
++ public static int Main()
++ {
++ // Ensure we get right order of side effects from boxes
++ // now that we are splitting them into multiple statments.
++ V v1 = new V(11);
++ int result1 = F(Trouble(ref v1), v1);
++ V v2 = new V(11);
++ int result2 = G(v2, Trouble(ref v2));
++ Console.WriteLine("Result1 = {0}; Result2 = {1}", result1, result2);
++ return result1 + result2 + 55;
++ }
++}
++
+diff --git a/tests/src/JIT/Regression/JitBlue/GitHub_12949/GitHub_12949_7.csproj b/tests/src/JIT/Regression/JitBlue/GitHub_12949/GitHub_12949_7.csproj
+new file mode 100644
+index 0000000..5cd573d
+--- /dev/null
++++ b/tests/src/JIT/Regression/JitBlue/GitHub_12949/GitHub_12949_7.csproj
+@@ -0,0 +1,43 @@
++<?xml version="1.0" encoding="utf-8"?>
++<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
++ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
++ <PropertyGroup>
++ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
++ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
++ <AssemblyName>$(MSBuildProjectName)</AssemblyName>
++ <SchemaVersion>2.0</SchemaVersion>
++ <ProjectGuid>{7B521917-193E-48BB-86C6-FE013F3DFF35}</ProjectGuid>
++ <OutputType>Exe</OutputType>
++ <AppDesignerFolder>Properties</AppDesignerFolder>
++ <FileAlignment>512</FileAlignment>
++ <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
++ <ReferencePath>$(ProgramFiles)\Common Files\microsoft shared\VSTT\11.0\UITestExtensionPackages</ReferencePath>
++ <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
++
++ <NuGetPackageImportStamp>7a9bfb7d</NuGetPackageImportStamp>
++ </PropertyGroup>
++ <!-- Default configurations to help VS understand the configurations -->
++ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
++ </PropertyGroup>
++ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
++ </PropertyGroup>
++ <ItemGroup>
++ <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
++ <Visible>False</Visible>
++ </CodeAnalysisDependentAssemblyPaths>
++ </ItemGroup>
++ <PropertyGroup>
++ <DebugType></DebugType>
++ <Optimize>True</Optimize>
++ <AllowUnsafeBlocks>True</AllowUnsafeBlocks>
++ </PropertyGroup>
++ <ItemGroup>
++ <Compile Include="$(MSBuildProjectName).cs" />
++ </ItemGroup>
++ <ItemGroup>
++ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
++ </ItemGroup>
++ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
++ <PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' ">
++ </PropertyGroup>
++</Project>
+diff --git a/tests/src/JIT/Regression/JitBlue/GitHub_12949/GitHub_12949_8.cs b/tests/src/JIT/Regression/JitBlue/GitHub_12949/GitHub_12949_8.cs
+new file mode 100644
+index 0000000..d5daa43
+--- /dev/null
++++ b/tests/src/JIT/Regression/JitBlue/GitHub_12949/GitHub_12949_8.cs
+@@ -0,0 +1,42 @@
++// Licensed to the .NET Foundation under one or more agreements.
++// The .NET Foundation licenses this file to you under the MIT license.
++// See the LICENSE file in the project root for more information.
++
++using System;
++using System.Runtime.CompilerServices;
++using System.Numerics;
++
++public class X<K>
++{
++ public X(K k1)
++ {
++ k = k1;
++ }
++
++ [MethodImpl(MethodImplOptions.NoInlining)]
++ public static bool Test(X<K> a)
++ {
++ return (a.k != null);
++ }
++
++ public K k;
++}
++
++class B
++{
++ public static int Main()
++ {
++ X<Vector3> a = null;
++ bool result = false;
++ try
++ {
++ X<Vector3>.Test(a);
++ }
++ catch (Exception)
++ {
++ result = true;
++ }
++ Console.WriteLine("Passed: {0}", result);
++ return result ? 100 : 0;
++ }
++}
+diff --git a/tests/src/JIT/Regression/JitBlue/GitHub_12949/GitHub_12949_8.csproj b/tests/src/JIT/Regression/JitBlue/GitHub_12949/GitHub_12949_8.csproj
+new file mode 100644
+index 0000000..5cd573d
+--- /dev/null
++++ b/tests/src/JIT/Regression/JitBlue/GitHub_12949/GitHub_12949_8.csproj
+@@ -0,0 +1,43 @@
++<?xml version="1.0" encoding="utf-8"?>
++<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
++ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
++ <PropertyGroup>
++ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
++ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
++ <AssemblyName>$(MSBuildProjectName)</AssemblyName>
++ <SchemaVersion>2.0</SchemaVersion>
++ <ProjectGuid>{7B521917-193E-48BB-86C6-FE013F3DFF35}</ProjectGuid>
++ <OutputType>Exe</OutputType>
++ <AppDesignerFolder>Properties</AppDesignerFolder>
++ <FileAlignment>512</FileAlignment>
++ <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
++ <ReferencePath>$(ProgramFiles)\Common Files\microsoft shared\VSTT\11.0\UITestExtensionPackages</ReferencePath>
++ <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
++
++ <NuGetPackageImportStamp>7a9bfb7d</NuGetPackageImportStamp>
++ </PropertyGroup>
++ <!-- Default configurations to help VS understand the configurations -->
++ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
++ </PropertyGroup>
++ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
++ </PropertyGroup>
++ <ItemGroup>
++ <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
++ <Visible>False</Visible>
++ </CodeAnalysisDependentAssemblyPaths>
++ </ItemGroup>
++ <PropertyGroup>
++ <DebugType></DebugType>
++ <Optimize>True</Optimize>
++ <AllowUnsafeBlocks>True</AllowUnsafeBlocks>
++ </PropertyGroup>
++ <ItemGroup>
++ <Compile Include="$(MSBuildProjectName).cs" />
++ </ItemGroup>
++ <ItemGroup>
++ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
++ </ItemGroup>
++ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
++ <PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' ">
++ </PropertyGroup>
++</Project>
+--
+2.7.4
+