summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/jit/optimizer.cpp32
-rw-r--r--tests/src/JIT/Regression/JitBlue/GitHub_23739/GitHub_23739.cs212
-rw-r--r--tests/src/JIT/Regression/JitBlue/GitHub_23739/GitHub_23739.csproj18
3 files changed, 251 insertions, 11 deletions
diff --git a/src/jit/optimizer.cpp b/src/jit/optimizer.cpp
index 431f4d5ab1..7749e928ba 100644
--- a/src/jit/optimizer.cpp
+++ b/src/jit/optimizer.cpp
@@ -6885,26 +6885,36 @@ bool Compiler::optHoistLoopExprsForTree(GenTree* tree,
// Tree must be a suitable CSE candidate for us to be able to hoist it.
treeIsHoistable &= optIsCSEcandidate(tree);
- // If it's a call, it must be a helper call, and be pure.
- // Further, if it may run a cctor, it must be labeled as "Hoistable"
- // (meaning it won't run a cctor because the class is not precise-init).
- if (treeIsHoistable && tree->OperGet() == GT_CALL)
+ if (treeIsHoistable)
{
- GenTreeCall* call = tree->AsCall();
- if (call->gtCallType != CT_HELPER)
+ // We cannot hoist an r-value of TYP_STRUCT
+ // as they currently do not carry full descriptors of the struct type
+ if (tree->TypeGet() == TYP_STRUCT)
{
treeIsHoistable = false;
}
- else
+
+ // If it's a call, it must be a helper call, and be pure.
+ // Further, if it may run a cctor, it must be labeled as "Hoistable"
+ // (meaning it won't run a cctor because the class is not precise-init).
+ if (tree->OperGet() == GT_CALL)
{
- CorInfoHelpFunc helpFunc = eeGetHelperNum(call->gtCallMethHnd);
- if (!s_helperCallProperties.IsPure(helpFunc))
+ GenTreeCall* call = tree->AsCall();
+ if (call->gtCallType != CT_HELPER)
{
treeIsHoistable = false;
}
- else if (s_helperCallProperties.MayRunCctor(helpFunc) && (call->gtFlags & GTF_CALL_HOISTABLE) == 0)
+ else
{
- treeIsHoistable = false;
+ CorInfoHelpFunc helpFunc = eeGetHelperNum(call->gtCallMethHnd);
+ if (!s_helperCallProperties.IsPure(helpFunc))
+ {
+ treeIsHoistable = false;
+ }
+ else if (s_helperCallProperties.MayRunCctor(helpFunc) && (call->gtFlags & GTF_CALL_HOISTABLE) == 0)
+ {
+ treeIsHoistable = false;
+ }
}
}
}
diff --git a/tests/src/JIT/Regression/JitBlue/GitHub_23739/GitHub_23739.cs b/tests/src/JIT/Regression/JitBlue/GitHub_23739/GitHub_23739.cs
new file mode 100644
index 0000000000..b75bc51568
--- /dev/null
+++ b/tests/src/JIT/Regression/JitBlue/GitHub_23739/GitHub_23739.cs
@@ -0,0 +1,212 @@
+// 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;
+
+class GitHub_23739
+{
+ struct Struct1f
+ {
+ float a;
+ }
+
+ class Cls1f
+ {
+ public Struct1f sf;
+ }
+
+ struct Struct2f
+ {
+ float a, b;
+ }
+
+ class Cls2f
+ {
+ public Struct2f sf;
+ }
+
+ struct Struct3f
+ {
+ float a, b, c;
+ }
+
+ class Cls3f
+ {
+ public Struct3f sf;
+ }
+
+ struct Struct4f
+ {
+ float a, b, c, d;
+ }
+
+ class Cls4f
+ {
+ public Struct4f sf;
+ }
+
+ struct Struct5f
+ {
+ float a, b, c, d, e;
+ }
+
+ class Cls5f
+ {
+ public Struct5f sf;
+ }
+
+ struct Struct6f
+ {
+ float a, b, c, d, e, f;
+ }
+
+ class Cls6f
+ {
+ public Struct6f sf;
+ }
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ static void Sink<T>(ref T t)
+ {
+ }
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ static void Test1f(Cls1f c)
+ {
+ Struct1f l1 = default;
+ Struct1f l2 = default;
+ Struct1f l3 = default;
+
+ for (int i = 0; i < 10; i++)
+ {
+ l1 = c.sf;
+ l2 = c.sf;
+ l3 = c.sf;
+ }
+
+ Sink(ref l1);
+ Sink(ref l2);
+ Sink(ref l3);
+ }
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ static void Test2f(Cls2f c)
+ {
+ Struct2f l1 = default;
+ Struct2f l2 = default;
+ Struct2f l3 = default;
+
+ for (int i = 0; i < 10; i++)
+ {
+ l1 = c.sf;
+ l2 = c.sf;
+ l3 = c.sf;
+ }
+
+ Sink(ref l1);
+ Sink(ref l2);
+ Sink(ref l3);
+ }
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ static void Test3f(Cls3f c)
+ {
+ Struct3f l1 = default;
+ Struct3f l2 = default;
+ Struct3f l3 = default;
+
+ for (int i = 0; i < 10; i++)
+ {
+ l1 = c.sf;
+ l2 = c.sf;
+ l3 = c.sf;
+ }
+
+ Sink(ref l1);
+ Sink(ref l2);
+ Sink(ref l3);
+ }
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ static void Test4f(Cls4f c)
+ {
+ Struct4f l1 = default;
+ Struct4f l2 = default;
+ Struct4f l3 = default;
+
+ for (int i = 0; i < 10; i++)
+ {
+ l1 = c.sf;
+ l2 = c.sf;
+ l3 = c.sf;
+ }
+
+ Sink(ref l1);
+ Sink(ref l2);
+ Sink(ref l3);
+ }
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ static void Test5f(Cls5f c)
+ {
+ Struct5f l1 = default;
+ Struct5f l2 = default;
+ Struct5f l3 = default;
+
+ for (int i = 0; i < 10; i++)
+ {
+ l1 = c.sf;
+ l2 = c.sf;
+ l3 = c.sf;
+ }
+
+ Sink(ref l1);
+ Sink(ref l2);
+ Sink(ref l3);
+ }
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ static void Test6f(Cls6f c)
+ {
+ Struct6f l1 = default;
+ Struct6f l2 = default;
+ Struct6f l3 = default;
+
+ for (int i = 0; i < 10; i++)
+ {
+ l1 = c.sf;
+ l2 = c.sf;
+ l3 = c.sf;
+ }
+
+ Sink(ref l1);
+ Sink(ref l2);
+ Sink(ref l3);
+ }
+
+ static int Main()
+ {
+ Cls1f cls1f = new Cls1f();
+ Test1f(cls1f);
+
+ Cls2f cls2f = new Cls2f();
+ Test2f(cls2f);
+
+ Cls3f cls3f = new Cls3f();
+ Test3f(cls3f);
+
+ Cls4f cls4f = new Cls4f();
+ Test4f(cls4f);
+
+ Cls5f cls5f = new Cls5f();
+ Test5f(cls5f);
+
+ Cls6f cls6f = new Cls6f();
+ Test6f(cls6f);
+
+ return 100;
+ }
+}
diff --git a/tests/src/JIT/Regression/JitBlue/GitHub_23739/GitHub_23739.csproj b/tests/src/JIT/Regression/JitBlue/GitHub_23739/GitHub_23739.csproj
new file mode 100644
index 0000000000..fb6ae363eb
--- /dev/null
+++ b/tests/src/JIT/Regression/JitBlue/GitHub_23739/GitHub_23739.csproj
@@ -0,0 +1,18 @@
+<?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)' == '' ">Release</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <AssemblyName>$(MSBuildProjectName)</AssemblyName>
+ <OutputType>Exe</OutputType>
+ <DebugType></DebugType>
+ <Optimize>True</Optimize>
+ <AllowUnsafeBlocks>True</AllowUnsafeBlocks>
+ </PropertyGroup>
+ <ItemGroup>
+ <Compile Include="$(MSBuildProjectName).cs" />
+ </ItemGroup>
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+ <PropertyGroup Condition=" '$(MsBuildProjectDirOverride)' != '' "></PropertyGroup>
+</Project>