Skip to content

Commit d709a73

Browse files
authored
JIT: Always intersect exception sets of defs (#116007)
The existing logic would only intersect the exception sets of subsequent defs if it had also seen a use. That meant for a list [DEF, DEF, USE] of CSE candidates we would only validate that the first def's exception sets were sufficient for the use.
1 parent c972a60 commit d709a73

File tree

3 files changed

+105
-45
lines changed

3 files changed

+105
-45
lines changed

src/coreclr/jit/optcse.cpp

Lines changed: 43 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1531,6 +1531,49 @@ void Compiler::optValnumCSE_Availability()
15311531
// This is the first time visited, so record this defs exception set
15321532
desc->defExcSetCurrent = theLiberalExcSet;
15331533
}
1534+
else if (desc->defExcSetCurrent != theLiberalExcSet)
1535+
{
1536+
// We will change the value of desc->defExcSetCurrent to be the intersection of
1537+
// these two sets.
1538+
// This is the set of exceptions that all CSE defs have (that we have visited so
1539+
// far)
1540+
//
1541+
ValueNum intersectionExcSet =
1542+
vnStore->VNExcSetIntersection(desc->defExcSetCurrent, theLiberalExcSet);
1543+
#ifdef DEBUG
1544+
if (this->verbose)
1545+
{
1546+
VNFuncApp excSeq;
1547+
1548+
vnStore->GetVNFunc(desc->defExcSetCurrent, &excSeq);
1549+
printf(">>> defExcSetCurrent is ");
1550+
vnStore->vnDumpExcSeq(this, &excSeq, true);
1551+
printf("\n");
1552+
1553+
vnStore->GetVNFunc(theLiberalExcSet, &excSeq);
1554+
printf(">>> theLiberalExcSet is ");
1555+
vnStore->vnDumpExcSeq(this, &excSeq, true);
1556+
printf("\n");
1557+
1558+
if (intersectionExcSet == vnStore->VNForEmptyExcSet())
1559+
{
1560+
printf(">>> the intersectionExcSet is the EmptyExcSet\n");
1561+
}
1562+
else
1563+
{
1564+
vnStore->GetVNFunc(intersectionExcSet, &excSeq);
1565+
printf(">>> the intersectionExcSet is ");
1566+
vnStore->vnDumpExcSeq(this, &excSeq, true);
1567+
printf("\n");
1568+
}
1569+
}
1570+
#endif // DEBUG
1571+
1572+
// Change the defExcSetCurrent to be a subset of its prior value
1573+
//
1574+
assert(vnStore->VNExcIsSubset(desc->defExcSetCurrent, intersectionExcSet));
1575+
desc->defExcSetCurrent = intersectionExcSet;
1576+
}
15341577

15351578
// Have we seen a CSE use and made a promise of an exception set?
15361579
//
@@ -1543,51 +1586,6 @@ void Compiler::optValnumCSE_Availability()
15431586
// This new def still satisfies any promise made to all the CSE uses that we have
15441587
// encountered
15451588
//
1546-
1547-
// no update is needed when these are the same VN
1548-
if (desc->defExcSetCurrent != theLiberalExcSet)
1549-
{
1550-
// We will change the value of desc->defExcSetCurrent to be the intersection of
1551-
// these two sets.
1552-
// This is the set of exceptions that all CSE defs have (that we have visited so
1553-
// far)
1554-
//
1555-
ValueNum intersectionExcSet =
1556-
vnStore->VNExcSetIntersection(desc->defExcSetCurrent, theLiberalExcSet);
1557-
#ifdef DEBUG
1558-
if (this->verbose)
1559-
{
1560-
VNFuncApp excSeq;
1561-
1562-
vnStore->GetVNFunc(desc->defExcSetCurrent, &excSeq);
1563-
printf(">>> defExcSetCurrent is ");
1564-
vnStore->vnDumpExcSeq(this, &excSeq, true);
1565-
printf("\n");
1566-
1567-
vnStore->GetVNFunc(theLiberalExcSet, &excSeq);
1568-
printf(">>> theLiberalExcSet is ");
1569-
vnStore->vnDumpExcSeq(this, &excSeq, true);
1570-
printf("\n");
1571-
1572-
if (intersectionExcSet == vnStore->VNForEmptyExcSet())
1573-
{
1574-
printf(">>> the intersectionExcSet is the EmptyExcSet\n");
1575-
}
1576-
else
1577-
{
1578-
vnStore->GetVNFunc(intersectionExcSet, &excSeq);
1579-
printf(">>> the intersectionExcSet is ");
1580-
vnStore->vnDumpExcSeq(this, &excSeq, true);
1581-
printf("\n");
1582-
}
1583-
}
1584-
#endif // DEBUG
1585-
1586-
// Change the defExcSetCurrent to be a subset of its prior value
1587-
//
1588-
assert(vnStore->VNExcIsSubset(desc->defExcSetCurrent, intersectionExcSet));
1589-
desc->defExcSetCurrent = intersectionExcSet;
1590-
}
15911589
}
15921590
else // This CSE def doesn't satisfy one of the exceptions already promised to a CSE use
15931591
{
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using System;
5+
using System.Runtime.CompilerServices;
6+
using Xunit;
7+
8+
namespace Runtime_112848;
9+
10+
public class BaseClass { }
11+
12+
public class TestClass : BaseClass
13+
{
14+
[MethodImpl(MethodImplOptions.NoInlining)]
15+
private static bool Test_LDLOC(object _obj, bool flag)
16+
{
17+
object obj = _obj;
18+
TestClass inst = null;
19+
if (flag)
20+
{
21+
inst = (TestClass)obj;
22+
return inst != null;
23+
}
24+
else
25+
{
26+
inst = (TestClass)obj;
27+
return obj == null;
28+
}
29+
}
30+
31+
[Fact]
32+
public static int TestEntryPoint()
33+
{
34+
try
35+
{
36+
if (!Test_LDLOC(new BaseClass(), false))
37+
{
38+
Console.WriteLine("Failed => 103");
39+
return 103;
40+
}
41+
42+
return 104;
43+
}
44+
catch (InvalidCastException)
45+
{
46+
Console.WriteLine("Caught InvalidCastException as expected");
47+
}
48+
Console.WriteLine("Done");
49+
return 100;
50+
}
51+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
<PropertyGroup>
3+
<Optimize>True</Optimize>
4+
<!-- Needed for CLRTestEnvironmentVariable -->
5+
<RequiresProcessIsolation>true</RequiresProcessIsolation>
6+
</PropertyGroup>
7+
<ItemGroup>
8+
<Compile Include="$(MSBuildProjectName).cs" />
9+
<CLRTestEnvironmentVariable Include="DOTNET_JitStressModeNames" Value="STRESS_LCL_FLDS" />
10+
</ItemGroup>
11+
</Project>

0 commit comments

Comments
 (0)