diff options
-rw-r--r-- | src/jit/assertionprop.cpp | 19 | ||||
-rw-r--r-- | src/jit/compiler.h | 9 | ||||
-rw-r--r-- | src/jit/gentree.cpp | 35 | ||||
-rw-r--r-- | src/jit/optcse.cpp | 3 | ||||
-rw-r--r-- | tests/src/JIT/Regression/JitBlue/GitHub_24185/GitHub_24185.cs | 36 | ||||
-rw-r--r-- | tests/src/JIT/Regression/JitBlue/GitHub_24185/GitHub_24185.csproj | 33 |
6 files changed, 114 insertions, 21 deletions
diff --git a/src/jit/assertionprop.cpp b/src/jit/assertionprop.cpp index cd1b90ffa2..5b62e88303 100644 --- a/src/jit/assertionprop.cpp +++ b/src/jit/assertionprop.cpp @@ -3901,11 +3901,22 @@ GenTree* Compiler::optAssertionProp_Update(GenTree* newTree, GenTree* tree, GenT // locate our parent node and update it so that it points to newTree. if (newTree != tree) { - GenTree** link = gtFindLink(stmt, tree); - noway_assert(link != nullptr); + FindLinkData linkData = gtFindLink(stmt, tree); + GenTree** useEdge = linkData.result; + GenTree* parent = linkData.parent; + noway_assert(useEdge != nullptr); - // Replace the old operand with the newTree - *link = newTree; + if (parent != nullptr) + { + parent->ReplaceOperand(useEdge, newTree); + } + else + { + // If there's no parent, the tree being replaced is the root of the + // statement. + assert((stmt->gtStmtExpr == tree) && (&stmt->gtStmtExpr == useEdge)); + stmt->gtStmtExpr = newTree; + } // We only need to ensure that the gtNext field is set as it is used to traverse // to the next node in the tree. We will re-morph this entire statement in diff --git a/src/jit/compiler.h b/src/jit/compiler.h index b091c929c9..fed7003faa 100644 --- a/src/jit/compiler.h +++ b/src/jit/compiler.h @@ -2994,7 +2994,14 @@ public: static fgWalkPreFn gtMarkColonCond; static fgWalkPreFn gtClearColonCond; - GenTree** gtFindLink(GenTreeStmt* stmt, GenTree* node); + struct FindLinkData + { + GenTree* nodeToFind; + GenTree** result; + GenTree* parent; + }; + + FindLinkData gtFindLink(GenTreeStmt* stmt, GenTree* node); bool gtHasCatchArg(GenTree* tree); typedef ArrayStack<GenTree*> GenTreeStack; diff --git a/src/jit/gentree.cpp b/src/jit/gentree.cpp index f0dfbc7ee5..df6b324a06 100644 --- a/src/jit/gentree.cpp +++ b/src/jit/gentree.cpp @@ -7931,23 +7931,32 @@ bool Compiler::gtCompareTree(GenTree* op1, GenTree* op2) GenTree* Compiler::gtGetThisArg(GenTreeCall* call) { - if (call->gtCallObjp != nullptr) + GenTree* thisArg = call->gtCallObjp; + if (thisArg != nullptr) { - if (call->gtCallObjp->gtOper != GT_NOP && call->gtCallObjp->gtOper != GT_ASG) + if (thisArg->OperIs(GT_NOP, GT_ASG) == false) { - if (!(call->gtCallObjp->gtFlags & GTF_LATE_ARG)) + if ((thisArg->gtFlags & GTF_LATE_ARG) == 0) { return call->gtCallObjp; } } - if (call->gtCallLateArgs) + if (call->gtCallLateArgs != nullptr) { unsigned argNum = 0; fgArgTabEntry* thisArgTabEntry = gtArgEntryByArgNum(call, argNum); GenTree* result = thisArgTabEntry->node; + // Assert if we used DEBUG_DESTROY_NODE. + assert(result->gtOper != GT_COUNT); + #if !FEATURE_FIXED_OUT_ARGS && defined(DEBUG) + // Check that call->fgArgInfo used in gtArgEntryByArgNum was not + // left outdated by assertion propogation updates. + // There is no information about registers of late args for platforms + // with FEATURE_FIXED_OUT_ARGS that is why this debug check is under + // !FEATURE_FIXED_OUT_ARGS. regNumber thisReg = REG_ARG_0; GenTree* lateArgs = call->gtCallLateArgs; regList list = call->regArgList; @@ -7966,6 +7975,7 @@ GenTree* Compiler::gtGetThisArg(GenTreeCall* call) index++; } #endif // !FEATURE_FIXED_OUT_ARGS && defined(DEBUG) + return result; } } @@ -15156,42 +15166,37 @@ Compiler::fgWalkResult Compiler::gtClearColonCond(GenTree** pTree, fgWalkData* d return WALK_CONTINUE; } -struct FindLinkData -{ - GenTree* nodeToFind; - GenTree** result; -}; - /***************************************************************************** * * Callback used by the tree walker to implement fgFindLink() */ static Compiler::fgWalkResult gtFindLinkCB(GenTree** pTree, Compiler::fgWalkData* cbData) { - FindLinkData* data = (FindLinkData*)cbData->pCallbackData; + Compiler::FindLinkData* data = (Compiler::FindLinkData*)cbData->pCallbackData; if (*pTree == data->nodeToFind) { data->result = pTree; + data->parent = cbData->parent; return Compiler::WALK_ABORT; } return Compiler::WALK_CONTINUE; } -GenTree** Compiler::gtFindLink(GenTreeStmt* stmt, GenTree* node) +Compiler::FindLinkData Compiler::gtFindLink(GenTreeStmt* stmt, GenTree* node) { - FindLinkData data = {node, nullptr}; + FindLinkData data = {node, nullptr, nullptr}; fgWalkResult result = fgWalkTreePre(&stmt->gtStmtExpr, gtFindLinkCB, &data); if (result == WALK_ABORT) { assert(data.nodeToFind == *data.result); - return data.result; + return data; } else { - return nullptr; + return {node, nullptr, nullptr}; } } diff --git a/src/jit/optcse.cpp b/src/jit/optcse.cpp index 9dc421b3fd..a25e17c4fa 100644 --- a/src/jit/optcse.cpp +++ b/src/jit/optcse.cpp @@ -2364,7 +2364,8 @@ public: // Walk the statement 'stmt' and find the pointer // in the tree is pointing to 'exp' // - GenTree** link = m_pCompiler->gtFindLink(stmt, exp); + Compiler::FindLinkData linkData = m_pCompiler->gtFindLink(stmt, exp); + GenTree** link = linkData.result; #ifdef DEBUG if (link == nullptr) diff --git a/tests/src/JIT/Regression/JitBlue/GitHub_24185/GitHub_24185.cs b/tests/src/JIT/Regression/JitBlue/GitHub_24185/GitHub_24185.cs new file mode 100644 index 0000000000..3695ab2a8f --- /dev/null +++ b/tests/src/JIT/Regression/JitBlue/GitHub_24185/GitHub_24185.cs @@ -0,0 +1,36 @@ +// 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.Threading; +using System.Threading.Tasks; + +// The test shows recursive assertion propogation in one statement. + +namespace GitHub_24185 +{ + public class Program + { + static int Main(string[] args) + { + try + { + throw new AggregateException(new Exception("A random exception1"), new Exception("A random exception2")); + } + catch (Exception e) + { + // Each expression in this condition checks that `e` is not null and checks its type. + // This information should be calculated once and propogated by assertion propogation. + if (!(e is AggregateException) || + !((((AggregateException)e).InnerExceptions[0] is ArgumentException) + || ((AggregateException)e).InnerExceptions[0] is AggregateException)) + { + return 100; + } + + } + return 0; + } + } +} diff --git a/tests/src/JIT/Regression/JitBlue/GitHub_24185/GitHub_24185.csproj b/tests/src/JIT/Regression/JitBlue/GitHub_24185/GitHub_24185.csproj new file mode 100644 index 0000000000..cc72c511df --- /dev/null +++ b/tests/src/JIT/Regression/JitBlue/GitHub_24185/GitHub_24185.csproj @@ -0,0 +1,33 @@ +<?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> + <SchemaVersion>2.0</SchemaVersion> + <ProjectGuid>{95DFC527-4DC1-495E-97D7-E94EE1F7140D}</ProjectGuid> + <OutputType>Exe</OutputType> + <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids> + <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir> + </PropertyGroup> + <!-- Default configurations to help VS understand the configurations --> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "></PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' " /> + <ItemGroup> + <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies"> + <Visible>False</Visible> + </CodeAnalysisDependentAssemblyPaths> + </ItemGroup> + <PropertyGroup> + <DebugType>None</DebugType> + <Optimize>True</Optimize> + </PropertyGroup> + <ItemGroup> + <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" /> + </ItemGroup> + <ItemGroup> + <Compile Include="$(MSBuildProjectName).cs" /> + </ItemGroup> + <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" /> + <PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' "></PropertyGroup> +</Project>
\ No newline at end of file |