Skip to content

Commit

Permalink
Fix fgRemoveUnreachableBlocks to detect all changes
Browse files Browse the repository at this point in the history
When 'removing' a BBF_DONT_REMOVE block we change it to BBJ_THROW. After
this it is possible that other blocks become unreachable, so we should
keep looking for such blocks.

In dotnet#57061 that manifested in a case where the unreachable block did not
have SSA built for it, but downstream the compiler was relying on SSA
being built.

Fix dotnet#57061
  • Loading branch information
jakobbotsch committed Aug 11, 2021
1 parent e6e7ef9 commit 8332fa7
Show file tree
Hide file tree
Showing 3 changed files with 121 additions and 2 deletions.
9 changes: 7 additions & 2 deletions src/coreclr/jit/fgopt.cpp
Expand Up @@ -359,7 +359,7 @@ void Compiler::fgComputeEnterBlocksSet()
// are never considered unreachable.
//
// Return Value:
// Return true if any unreachable blocks were removed.
// Return true if changes were made that may cause additional blocks to be removable.
//
// Assumptions:
// The reachability sets must be computed and valid.
Expand All @@ -376,6 +376,7 @@ bool Compiler::fgRemoveUnreachableBlocks()

bool hasLoops = false;
bool hasUnreachableBlocks = false;
bool changed = false;

/* Record unreachable blocks */
for (BasicBlock* const block : Blocks())
Expand Down Expand Up @@ -419,6 +420,9 @@ bool Compiler::fgRemoveUnreachableBlocks()
/* Unmark the block as removed, */
/* clear BBF_INTERNAL as well and set BBJ_IMPORTED */

// The successors may be unreachable after this change.
changed |= block->NumSucc() > 0;

block->bbFlags &= ~(BBF_REMOVED | BBF_INTERNAL);
block->bbFlags |= BBF_IMPORTED;
block->bbJumpKind = BBJ_THROW;
Expand All @@ -438,6 +442,7 @@ bool Compiler::fgRemoveUnreachableBlocks()
{
/* We have to call fgRemoveBlock next */
hasUnreachableBlocks = true;
changed = true;
}
continue;

Expand Down Expand Up @@ -498,7 +503,7 @@ bool Compiler::fgRemoveUnreachableBlocks()
}
}

return hasUnreachableBlocks;
return changed;
}

//------------------------------------------------------------------------
Expand Down
102 changes: 102 additions & 0 deletions src/tests/JIT/Regression/JitBlue/Runtime_57061/Runtime_57061.cs
@@ -0,0 +1,102 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

// Generated by Fuzzlyn v1.2 on 2021-08-07 03:24:16
// Run on .NET 6.0.0-dev on Arm Linux
// Seed: 12756399625466979010
// Reduced from 798.7 KiB to 1.5 KiB in 03:42:20
// Crashes the runtime
using System.Runtime.CompilerServices;

struct S0
{
public bool F0;
public bool F1;
public uint F2;
public short F3;
public ulong F4;
public S0(bool f0, bool f1, uint f2, short f3, ulong f4): this()
{
F0 = f0;
F1 = f1;
F2 = f2;
F3 = f3;
F4 = f4;
}
}

class C0
{
public C0(S0 f7, S0 f8)
{
}
}

class C1
{
public S0 F1;
public ulong F5;
}

struct S2
{
public S2(C0 f4): this()
{
}
}

struct S3
{
public uint F0;
}

class C2
{
public C1 F3;
}

public class Program
{
static C2 s_23;
static C1 s_37;
static sbyte s_56;
static S3 s_60;
public static void Main()
{
uint vr2 = default(uint);
uint vr3;
bool vr4 = true;
if (!vr4)
{
try
{
System.Console.WriteLine(s_60.F0);
}
finally
{
var vr5 = new C0(new S0(false, true, 0, 0, 0), new S0(false, false, 0, 0, 0));
}

s_37.F5 = s_23.F3.F1.F4++;
}

vr4 = vr4;
for (int vr6 = 0; vr6 < Bound(); vr6++)
{
sbyte vr8 = s_56;
try
{
var vr7 = new S2(new C0(new S0(true, false, 0, 0, 0), new S0(true, true, 0, 0, 0)));
}
finally
{
vr3 = vr2;
}

vr3 = vr3;
}
}

[MethodImpl(MethodImplOptions.NoInlining)]
private static int Bound() => 0;
}
@@ -0,0 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
</PropertyGroup>
<PropertyGroup>
<DebugType>None</DebugType>
<Optimize>True</Optimize>
</PropertyGroup>
<ItemGroup>
<Compile Include="$(MSBuildProjectName).cs" />
</ItemGroup>
</Project>

0 comments on commit 8332fa7

Please sign in to comment.