Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/coreclr/jit/assertionprop.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -675,6 +675,8 @@ void Compiler::optAssertionInit(bool isLocalProp)
{
optMaxAssertionCount = (AssertionIndex)min(maxTrackedLocals, ((3 * lvaTrackedCount / 128) + 1) * 64);
}

JITDUMP("Cross-block table size %u (for %u tracked locals)\n", optMaxAssertionCount, lvaTrackedCount);
}
else
{
Expand Down
41 changes: 30 additions & 11 deletions src/coreclr/jit/objectalloc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,7 @@ void ObjectAllocator::MarkLclVarAsEscaping(unsigned int lclNum)
void ObjectAllocator::MarkLclVarAsPossiblyStackPointing(unsigned int lclNum)
{
const unsigned bvIndex = LocalToIndex(lclNum);
JITDUMP("Marking V%02u (0x%02x) as possibly stack-pointing\n", lclNum, bvIndex);
BitVecOps::AddElemD(&m_bitVecTraits, m_PossiblyStackPointingPointers, bvIndex);
}

Expand Down Expand Up @@ -839,6 +840,11 @@ void ObjectAllocator::ComputeEscapingNodes(BitVecTraits* bitVecTraits, BitVec& e

void ObjectAllocator::ComputeStackObjectPointers(BitVecTraits* bitVecTraits)
{
// Keep track of locals that we know may point at the heap
//
BitVec possiblyHeapPointingPointers = BitVecOps::MakeEmpty(&m_bitVecTraits);
BitVecOps::AddElemD(bitVecTraits, possiblyHeapPointingPointers, m_unknownSourceIndex);

bool changed = true;
unsigned pass = 0;
while (changed)
Expand All @@ -859,23 +865,36 @@ void ObjectAllocator::ComputeStackObjectPointers(BitVecTraits* bitVecTraits)
m_ConnGraphAdjacencyMatrix[lclIndex]))
{
// We discovered a new pointer that may point to the stack.
JITDUMPEXEC(DumpIndex(lclIndex));
JITDUMP(" may point to the stack\n");
MarkLclVarAsPossiblyStackPointing(lclNum);
changed = true;
}

// If all locals assignable to this local are stack pointing, so is this local.
//
const bool isStackPointing = BitVecOps::IsSubset(bitVecTraits, m_ConnGraphAdjacencyMatrix[lclIndex],
m_DefinitelyStackPointingPointers);

if (isStackPointing)
{
MarkLclVarAsDefinitelyStackPointing(lclNum);
JITDUMP("V%02u is stack pointing\n", lclNum);
}

if (!BitVecOps::IsMember(bitVecTraits, possiblyHeapPointingPointers, lclIndex) &&
!BitVecOps::IsEmptyIntersection(bitVecTraits, possiblyHeapPointingPointers,
m_ConnGraphAdjacencyMatrix[lclIndex]))
{
// We discovered a new pointer that may point to the heap.
JITDUMPEXEC(DumpIndex(lclIndex));
JITDUMP(" may point to the heap\n");
BitVecOps::AddElemD(bitVecTraits, possiblyHeapPointingPointers, lclIndex);
changed = true;
}
}
}
JITDUMP("\n---- done computing stack pointing locals\n");

// If a local is possibly stack pointing and not possibly heap pointing, then it is definitely stack pointing.
//
BitVec newDefinitelyStackPointingPointers = BitVecOps::UninitVal();
Copy link

Copilot AI Apr 26, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider adding an inline comment to clarify that subtracting the possibly heap-pointing pointers from the possibly stack-pointing pointers isolates the definitely stack-pointing locals, especially to support future maintenance.

Copilot uses AI. Check for mistakes.
BitVecOps::Assign(bitVecTraits, newDefinitelyStackPointingPointers, m_PossiblyStackPointingPointers);
BitVecOps::DiffD(bitVecTraits, newDefinitelyStackPointingPointers, possiblyHeapPointingPointers);
Comment on lines +890 to +892
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you can use BitVecOps::Diff directly here to avoid manually writing the copy.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. Will clean this up in a future escape PR.


// We should have only added to the set of things that are definitely stack pointing.
//
assert(BitVecOps::IsSubset(bitVecTraits, m_DefinitelyStackPointingPointers, newDefinitelyStackPointingPointers));
BitVecOps::AssignNoCopy(bitVecTraits, m_DefinitelyStackPointingPointers, newDefinitelyStackPointingPointers);

#ifdef DEBUG
if (comp->verbose)
Expand Down
48 changes: 48 additions & 0 deletions src/tests/JIT/opt/ObjectStackAllocation/ConnectionCycles.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Runtime.CompilerServices;
using Xunit;

public class X
{
public X() { a = 15; b = 35; }
public int a;
public int b;
}

public class ConnectionCycles
{
static bool b;

[Fact]
public static int Problem()
{
return SubProblem(false) + SubProblem(true);
}

[MethodImpl(MethodImplOptions.NoInlining)]
static int SubProblem(bool b)
{
X x1 = new X();
X x2 = new X();

if (b)
{
x1 = x2;
}
else
{
x2 = x1;
}

SideEffect();

return x1.a + x2.b;
}


[MethodImpl(MethodImplOptions.NoInlining)]
static void SideEffect() { }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<DebugType>None</DebugType>
<Optimize>True</Optimize>
</PropertyGroup>
<ItemGroup>
<Compile Include="$(MSBuildProjectName).cs" />
</ItemGroup>
</Project>
Loading