Skip to content

Commit a108d25

Browse files
authored
JIT: don't clone loops where init or limit is a cast local (#57602)
The loop cloner assumes all computations it introduces are compatible with TYP_INT, so don't allow cloning when the initial or final value are variables with incompatible types. Fixes #57535.
1 parent b4d75a0 commit a108d25

File tree

5 files changed

+98
-3
lines changed

5 files changed

+98
-3
lines changed

src/coreclr/jit/loopcloning.cpp

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -968,7 +968,14 @@ bool Compiler::optDeriveLoopCloningConditions(unsigned loopNum, LoopCloneContext
968968
else if (loop->lpFlags & LPFLG_VAR_INIT)
969969
{
970970
// initVar >= 0
971-
LC_Condition geZero(GT_GE, LC_Expr(LC_Ident(loop->lpVarInit, LC_Ident::Var)),
971+
const unsigned initLcl = loop->lpVarInit;
972+
if (!genActualTypeIsInt(lvaGetDesc(initLcl)))
973+
{
974+
JITDUMP("> Init var V%02u not compatible with TYP_INT\n", initLcl);
975+
return false;
976+
}
977+
978+
LC_Condition geZero(GT_GE, LC_Expr(LC_Ident(initLcl, LC_Ident::Var)),
972979
LC_Expr(LC_Ident(0, LC_Ident::Const)));
973980
context->EnsureConditions(loopNum)->Push(geZero);
974981
}
@@ -992,9 +999,14 @@ bool Compiler::optDeriveLoopCloningConditions(unsigned loopNum, LoopCloneContext
992999
}
9931000
else if (loop->lpFlags & LPFLG_VAR_LIMIT)
9941001
{
995-
unsigned limitLcl = loop->lpVarLimit();
996-
ident = LC_Ident(limitLcl, LC_Ident::Var);
1002+
const unsigned limitLcl = loop->lpVarLimit();
1003+
if (!genActualTypeIsInt(lvaGetDesc(limitLcl)))
1004+
{
1005+
JITDUMP("> Limit var V%02u not compatible with TYP_INT\n", limitLcl);
1006+
return false;
1007+
}
9971008

1009+
ident = LC_Ident(limitLcl, LC_Ident::Var);
9981010
LC_Condition geZero(GT_GE, LC_Expr(ident), LC_Expr(LC_Ident(0, LC_Ident::Const)));
9991011

10001012
context->EnsureConditions(loopNum)->Push(geZero);
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
using System;
2+
using System.Runtime.CompilerServices;
3+
4+
class Runtime_57535
5+
{
6+
static long z;
7+
8+
public static int Main()
9+
{
10+
z = 10;
11+
int[] a = F();
12+
long zz = z;
13+
int result = 0;
14+
for (int i = 0; i < (int) zz; i++)
15+
{
16+
result += a[i];
17+
}
18+
return result;
19+
}
20+
21+
[MethodImpl(MethodImplOptions.NoInlining)]
22+
static int[] F()
23+
{
24+
int[] result = new int[100];
25+
result[3] = 100;
26+
return result;
27+
}
28+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
<PropertyGroup>
3+
<OutputType>Exe</OutputType>
4+
</PropertyGroup>
5+
<PropertyGroup>
6+
<DebugType>None</DebugType>
7+
<Optimize>True</Optimize>
8+
</PropertyGroup>
9+
<ItemGroup>
10+
<Compile Include="$(MSBuildProjectName).cs" />
11+
</ItemGroup>
12+
</Project>
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
using System;
2+
using System.Runtime.CompilerServices;
3+
4+
class Runtime_57535_1
5+
{
6+
static long z;
7+
8+
public static int Main()
9+
{
10+
z = 2;
11+
int[] a = F();
12+
long zz = z;
13+
int result = 0;
14+
for (int i = (int) zz; i < a.Length; i++)
15+
{
16+
result += a[i];
17+
}
18+
Bar(zz);
19+
return result;
20+
}
21+
22+
[MethodImpl(MethodImplOptions.NoInlining)]
23+
static int[] F()
24+
{
25+
int[] result = new int[100];
26+
result[3] = 100;
27+
return result;
28+
}
29+
30+
static void Bar(long z) {}
31+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
<PropertyGroup>
3+
<OutputType>Exe</OutputType>
4+
</PropertyGroup>
5+
<PropertyGroup>
6+
<DebugType>None</DebugType>
7+
<Optimize>True</Optimize>
8+
</PropertyGroup>
9+
<ItemGroup>
10+
<Compile Include="$(MSBuildProjectName).cs" />
11+
</ItemGroup>
12+
</Project>

0 commit comments

Comments
 (0)