Skip to content

Commit a08818e

Browse files
authored
JIT: Handle GT_RETFILT in fgInsertStmtNearEnd (#85420)
Also add some logging for read backs in physical promotion. Fix #85088
1 parent 64bd3b1 commit a08818e

File tree

4 files changed

+77
-12
lines changed

4 files changed

+77
-12
lines changed

src/coreclr/jit/fgstmt.cpp

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ Statement* Compiler::fgNewStmtAtEnd(BasicBlock* block, GenTree* tree, const Debu
171171

172172
//------------------------------------------------------------------------
173173
// fgInsertStmtNearEnd: Insert the given statement at the end of the given basic block,
174-
// but before the GT_JTRUE, if present.
174+
// but before the terminating node, if present.
175175
//
176176
// Arguments:
177177
// block - the block into which 'stmt' will be inserted;
@@ -182,7 +182,7 @@ void Compiler::fgInsertStmtNearEnd(BasicBlock* block, Statement* stmt)
182182
// This routine can only be used when in tree order.
183183
assert(fgOrder == FGOrderTree);
184184

185-
if (block->KindIs(BBJ_COND, BBJ_SWITCH, BBJ_RETURN))
185+
if (block->KindIs(BBJ_EHFINALLYRET, BBJ_EHFAULTRET, BBJ_EHFILTERRET, BBJ_COND, BBJ_SWITCH, BBJ_RETURN))
186186
{
187187
Statement* firstStmt = block->firstStmt();
188188
noway_assert(firstStmt != nullptr);
@@ -191,24 +191,28 @@ void Compiler::fgInsertStmtNearEnd(BasicBlock* block, Statement* stmt)
191191
Statement* insertionPoint = lastStmt->GetPrevStmt();
192192

193193
#if DEBUG
194-
if (block->bbJumpKind == BBJ_COND)
194+
if (block->KindIs(BBJ_COND))
195195
{
196-
assert(lastStmt->GetRootNode()->gtOper == GT_JTRUE);
196+
assert(lastStmt->GetRootNode()->OperIs(GT_JTRUE));
197197
}
198-
else if (block->bbJumpKind == BBJ_RETURN)
198+
else if (block->KindIs(BBJ_RETURN))
199199
{
200-
assert((lastStmt->GetRootNode()->gtOper == GT_RETURN) || (lastStmt->GetRootNode()->gtOper == GT_JMP) ||
200+
assert((lastStmt->GetRootNode()->OperIs(GT_RETURN, GT_JMP)) ||
201201
// BBJ_RETURN blocks in functions returning void do not get a GT_RETURN node if they
202202
// have a .tail prefix (even if canTailCall returns false for these calls)
203203
// code:Compiler::impImportBlockCode (search for the RET: label)
204204
// Ditto for real tail calls (all code after them has been removed)
205-
((lastStmt->GetRootNode()->gtOper == GT_CALL) &&
205+
(lastStmt->GetRootNode()->OperIs(GT_CALL) &&
206206
((info.compRetType == TYP_VOID) || lastStmt->GetRootNode()->AsCall()->IsTailCall())));
207207
}
208+
else if (block->KindIs(BBJ_EHFINALLYRET, BBJ_EHFAULTRET, BBJ_EHFILTERRET))
209+
{
210+
assert(lastStmt->GetRootNode()->OperIs(GT_RETFILT));
211+
}
208212
else
209213
{
210-
assert(block->bbJumpKind == BBJ_SWITCH);
211-
assert(lastStmt->GetRootNode()->gtOper == GT_SWITCH);
214+
assert(block->KindIs(BBJ_SWITCH));
215+
assert(lastStmt->GetRootNode()->OperIs(GT_SWITCH));
212216
}
213217
#endif // DEBUG
214218

src/coreclr/jit/promotion.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1770,11 +1770,13 @@ PhaseStatus Promotion::Run()
17701770
assert(!rep.NeedsReadBack || !rep.NeedsWriteBack);
17711771
if (rep.NeedsReadBack)
17721772
{
1773-
JITDUMP("Reading back replacement V%02u.[%03u..%03u) -> V%02u at the end of " FMT_BB "\n", i,
1773+
JITDUMP("Reading back replacement V%02u.[%03u..%03u) -> V%02u near the end of " FMT_BB ":\n", i,
17741774
rep.Offset, rep.Offset + genTypeSize(rep.AccessType), rep.LclNum, bb->bbNum);
17751775

1776-
GenTree* readBack = replacer.CreateReadBack(i, rep);
1777-
m_compiler->fgInsertStmtNearEnd(bb, m_compiler->fgNewStmtFromTree(readBack));
1776+
GenTree* readBack = replacer.CreateReadBack(i, rep);
1777+
Statement* stmt = m_compiler->fgNewStmtFromTree(readBack);
1778+
DISPSTMT(stmt);
1779+
m_compiler->fgInsertStmtNearEnd(bb, stmt);
17781780
rep.NeedsReadBack = false;
17791781
}
17801782

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
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+
public class Runtime_85088
9+
{
10+
[Fact]
11+
public static int Test()
12+
{
13+
Foo f = new();
14+
try
15+
{
16+
try
17+
{
18+
throw new Exception();
19+
}
20+
finally
21+
{
22+
f.X = 15;
23+
f.Y = 20;
24+
f.X += f.Y;
25+
f.Y *= f.X;
26+
27+
// f will be physically promoted and will require a read back after this call.
28+
// Since this is a finally, some platforms will have a GT_RETFILT that we were
29+
// inserting IR after instead of before.
30+
f = Call(f);
31+
}
32+
}
33+
catch
34+
{
35+
}
36+
37+
return f.X + f.Y;
38+
}
39+
40+
[MethodImpl(MethodImplOptions.NoInlining)]
41+
private static Foo Call(Foo f)
42+
{
43+
return new Foo { X = 75, Y = 25 };
44+
}
45+
46+
private struct Foo
47+
{
48+
public short X, Y;
49+
}
50+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
<PropertyGroup>
3+
<Optimize>True</Optimize>
4+
</PropertyGroup>
5+
<ItemGroup>
6+
<Compile Include="$(MSBuildProjectName).cs" />
7+
<CLRTestEnvironmentVariable Include="DOTNET_JitStressModeNames" Value="STRESS_PHYSICAL_PROMOTION STRESS_PHYSICAL_PROMOTION_COST STRESS_NO_OLD_PROMOTION" />
8+
</ItemGroup>
9+
</Project>

0 commit comments

Comments
 (0)