Skip to content

Commit

Permalink
Prototype a simple inter-procedural escape analysis
Browse files Browse the repository at this point in the history
  • Loading branch information
hez2010 committed Oct 5, 2024
1 parent 0372b50 commit 3ebe805
Show file tree
Hide file tree
Showing 21 changed files with 333 additions and 15 deletions.
4 changes: 4 additions & 0 deletions src/coreclr/inc/corinfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -3307,6 +3307,10 @@ class ICorDynamicInfo : public ICorStaticInfo
virtual void updateEntryPointForTailCall(CORINFO_CONST_LOOKUP* entryPoint) = 0;

virtual CORINFO_METHOD_HANDLE getSpecialCopyHelper(CORINFO_CLASS_HANDLE type) = 0;

virtual bool getIsLocalNonEscapes(CORINFO_METHOD_HANDLE method, uint32_t lclNum) = 0;

virtual void setIsLocalNonEscapes(CORINFO_METHOD_HANDLE method, uint32_t lclNum) = 0;
};

/**********************************************************************************/
Expand Down
8 changes: 8 additions & 0 deletions src/coreclr/inc/icorjitinfoimpl_generated.h
Original file line number Diff line number Diff line change
Expand Up @@ -742,6 +742,14 @@ uint32_t getJitFlags(
CORINFO_METHOD_HANDLE getSpecialCopyHelper(
CORINFO_CLASS_HANDLE type) override;

bool getIsLocalNonEscapes(
CORINFO_METHOD_HANDLE method,
uint32_t lclNum) override;

void setIsLocalNonEscapes(
CORINFO_METHOD_HANDLE method,
uint32_t lclNum) override;

/**********************************************************************************/
// clang-format on
/**********************************************************************************/
10 changes: 5 additions & 5 deletions src/coreclr/inc/jiteeversionguid.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,11 @@ typedef const GUID *LPCGUID;
#define GUID_DEFINED
#endif // !GUID_DEFINED

constexpr GUID JITEEVersionIdentifier = { /* 9b8ef809-94d4-41b6-9d4c-dd61379abbe0 */
0x9b8ef809,
0x94d4,
0x41b6,
{0x9d, 0x4c, 0xdd, 0x61, 0x37, 0x9a, 0xbb, 0xe0}
constexpr GUID JITEEVersionIdentifier = { /* 1512fc24-7751-4eb7-97ad-d8ec80571897 */
0x1512fc24,
0x7751,
0x4eb7,
{0x97, 0xad, 0xd8, 0xec, 0x80, 0x57, 0x18, 0x97}
};

//////////////////////////////////////////////////////////////////////////////////////////////////////////
Expand Down
2 changes: 2 additions & 0 deletions src/coreclr/jit/ICorJitInfo_names_generated.h
Original file line number Diff line number Diff line change
Expand Up @@ -180,5 +180,7 @@ DEF_CLR_API(getRelocTypeHint)
DEF_CLR_API(getExpectedTargetArchitecture)
DEF_CLR_API(getJitFlags)
DEF_CLR_API(getSpecialCopyHelper)
DEF_CLR_API(getIsLocalNonEscapes)
DEF_CLR_API(setIsLocalNonEscapes)

#undef DEF_CLR_API
19 changes: 19 additions & 0 deletions src/coreclr/jit/ICorJitInfo_wrapper_generated.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1742,6 +1742,25 @@ CORINFO_METHOD_HANDLE WrapICorJitInfo::getSpecialCopyHelper(
return temp;
}

bool WrapICorJitInfo::getIsLocalNonEscapes(
CORINFO_METHOD_HANDLE method,
uint32_t lclNum)
{
API_ENTER(getIsLocalNonEscapes);
bool temp = wrapHnd->getIsLocalNonEscapes(method, lclNum);
API_LEAVE(getIsLocalNonEscapes);
return temp;
}

void WrapICorJitInfo::setIsLocalNonEscapes(
CORINFO_METHOD_HANDLE method,
uint32_t lclNum)
{
API_ENTER(setIsLocalNonEscapes);
wrapHnd->setIsLocalNonEscapes(method, lclNum);
API_LEAVE(setIsLocalNonEscapes);
}

/**********************************************************************************/
// clang-format on
/**********************************************************************************/
2 changes: 1 addition & 1 deletion src/coreclr/jit/compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4660,7 +4660,7 @@ void Compiler::compCompile(void** methodCodePtr, uint32_t* methodCodeSize, JitFl
// local variable allocation on the stack.
ObjectAllocator objectAllocator(this); // PHASE_ALLOCATE_OBJECTS

if (compObjectStackAllocation() && opts.OptimizationEnabled())
if (compObjectStackAllocation())
{
objectAllocator.EnableObjectStackAllocation();
}
Expand Down
33 changes: 25 additions & 8 deletions src/coreclr/jit/objectalloc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,6 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
//
PhaseStatus ObjectAllocator::DoPhase()
{
if ((comp->optMethodFlags & OMF_HAS_NEWOBJ) == 0)
{
JITDUMP("no newobjs in this method; punting\n");
return PhaseStatus::MODIFIED_NOTHING;
}

bool enabled = IsObjectStackAllocationEnabled();
const char* disableReason = ": global config";

Expand Down Expand Up @@ -63,6 +57,12 @@ PhaseStatus ObjectAllocator::DoPhase()
m_IsObjectStackAllocationEnabled = false;
}

if ((comp->optMethodFlags & OMF_HAS_NEWOBJ) == 0)
{
JITDUMP("no newobjs in this method; punting\n");
return PhaseStatus::MODIFIED_NOTHING;
}

const bool didStackAllocate = MorphAllocObjNodes();

if (didStackAllocate)
Expand Down Expand Up @@ -134,7 +134,6 @@ void ObjectAllocator::AddConnGraphEdge(unsigned int sourceLclNum, unsigned int t

void ObjectAllocator::DoAnalysis()
{
assert(m_IsObjectStackAllocationEnabled);
assert(!m_AnalysisDone);

if (comp->lvaCount > 0)
Expand All @@ -144,6 +143,15 @@ void ObjectAllocator::DoAnalysis()

MarkEscapingVarsAndBuildConnGraph();
ComputeEscapingNodes(&m_bitVecTraits, m_EscapingPointers);

for (unsigned int lclNum = 0; lclNum < comp->lvaCount; ++lclNum)
{
if (!CanLclVarEscape(lclNum))
{
comp->info.compCompHnd->setIsLocalNonEscapes(comp->info.compMethodHnd, lclNum);
JITDUMP("V%02u does not escape\n", lclNum);
}
}
}

m_AnalysisDone = true;
Expand Down Expand Up @@ -719,13 +727,22 @@ bool ObjectAllocator::CanLclVarEscapeViaParentStack(ArrayStack<GenTree*>* parent

case GT_CALL:
{
GenTreeCall* asCall = parent->AsCall();
GenTreeCall* asCall = parent->AsCall();
CallArg* callArg = asCall->gtArgs.FindByNode(tree);

if (asCall->IsHelperCall())
{
canLclVarEscapeViaParentStack =
!Compiler::s_helperCallProperties.IsNoEscape(comp->eeGetHelperNum(asCall->gtCallMethHnd));
}
else if (asCall->gtCallType == gtCallTypes::CT_USER_FUNC && callArg != nullptr)
{
uint32_t argIndex = asCall->gtArgs.GetIndex(callArg);
if (comp->info.compCompHnd->getIsLocalNonEscapes(asCall->gtCallMethHnd, argIndex))
{
canLclVarEscapeViaParentStack = false;
}
}
break;
}

Expand Down
9 changes: 9 additions & 0 deletions src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1635,6 +1635,15 @@ private void setPatchpointInfo(PatchpointInfo* patchpointInfo)
private PatchpointInfo* getOSRInfo(ref uint ilOffset)
{ throw new NotImplementedException("getOSRInfo"); }

#pragma warning disable CA1822 // Mark members as static
private bool getIsLocalNonEscapes(CORINFO_METHOD_STRUCT_* method, uint lclNum)
{
return false;
}

private void setIsLocalNonEscapes(CORINFO_METHOD_STRUCT_* method, uint lclNum) { }
#pragma warning restore CA1822 // Mark members as static

#pragma warning disable CA1822 // Mark members as static
private void methodMustBeLoadedBeforeCodeIsRun(CORINFO_METHOD_STRUCT_* method)
#pragma warning restore CA1822 // Mark members as static
Expand Down
33 changes: 32 additions & 1 deletion src/coreclr/tools/Common/JitInterface/CorInfoImpl_generated.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2605,10 +2605,39 @@ private static uint _getJitFlags(IntPtr thisHandle, IntPtr* ppException, CORJIT_
}
}

[UnmanagedCallersOnly]
private static byte _getIsLocalNonEscapes(IntPtr thisHandle, IntPtr* ppException, CORINFO_METHOD_STRUCT_* method, uint lclNum)
{
var _this = GetThis(thisHandle);
try
{
return _this.getIsLocalNonEscapes(method, lclNum) ? (byte)1 : (byte)0;
}
catch (Exception ex)
{
*ppException = _this.AllocException(ex);
return default;
}
}

[UnmanagedCallersOnly]
private static void _setIsLocalNonEscapes(IntPtr thisHandle, IntPtr* ppException, CORINFO_METHOD_STRUCT_* method, uint lclNum)
{
var _this = GetThis(thisHandle);
try
{
_this.setIsLocalNonEscapes(method, lclNum);
}
catch (Exception ex)
{
*ppException = _this.AllocException(ex);
}
}


private static IntPtr GetUnmanagedCallbacks()
{
void** callbacks = (void**)Marshal.AllocCoTaskMem(sizeof(IntPtr) * 176);
void** callbacks = (void**)Marshal.AllocCoTaskMem(sizeof(IntPtr) * 178);

callbacks[0] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_METHOD_STRUCT_*, byte>)&_isIntrinsic;
callbacks[1] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_METHOD_STRUCT_*, byte>)&_notifyMethodInfoUsage;
Expand Down Expand Up @@ -2786,6 +2815,8 @@ private static IntPtr GetUnmanagedCallbacks()
callbacks[173] = (delegate* unmanaged<IntPtr, IntPtr*, uint>)&_getExpectedTargetArchitecture;
callbacks[174] = (delegate* unmanaged<IntPtr, IntPtr*, CORJIT_FLAGS*, uint, uint>)&_getJitFlags;
callbacks[175] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_CLASS_STRUCT_*, CORINFO_METHOD_STRUCT_*>)&_getSpecialCopyHelper;
callbacks[176] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_METHOD_STRUCT_*, uint, byte>)&_getIsLocalNonEscapes;
callbacks[177] = (delegate* unmanaged<IntPtr, IntPtr*, CORINFO_METHOD_STRUCT_*, uint, void>)&_setIsLocalNonEscapes;

return (IntPtr)callbacks;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -339,3 +339,5 @@ FUNCTIONS
uint32_t getExpectedTargetArchitecture()
uint32_t getJitFlags(CORJIT_FLAGS* flags, uint32_t sizeInBytes)
CORINFO_METHOD_HANDLE getSpecialCopyHelper(CORINFO_CLASS_HANDLE type) = 0;
bool getIsLocalNonEscapes(CORINFO_METHOD_HANDLE method, uint32_t lclNum);
void setIsLocalNonEscapes(CORINFO_METHOD_HANDLE method, uint32_t lclNum);
21 changes: 21 additions & 0 deletions src/coreclr/tools/aot/jitinterface/jitinterface_generated.h
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,8 @@ struct JitInterfaceCallbacks
uint32_t (* getExpectedTargetArchitecture)(void * thisHandle, CorInfoExceptionClass** ppException);
uint32_t (* getJitFlags)(void * thisHandle, CorInfoExceptionClass** ppException, CORJIT_FLAGS* flags, uint32_t sizeInBytes);
CORINFO_METHOD_HANDLE (* getSpecialCopyHelper)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE type);
bool (* getIsLocalNonEscapes)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_METHOD_HANDLE method, uint32_t lclNum);
void (* setIsLocalNonEscapes)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_METHOD_HANDLE method, uint32_t lclNum);

};

Expand Down Expand Up @@ -1919,4 +1921,23 @@ class JitInterfaceWrapper : public ICorJitInfo
if (pException != nullptr) throw pException;
return temp;
}

virtual bool getIsLocalNonEscapes(
CORINFO_METHOD_HANDLE method,
uint32_t lclNum)
{
CorInfoExceptionClass* pException = nullptr;
bool temp = _callbacks->getIsLocalNonEscapes(_thisHandle, &pException, method, lclNum);
if (pException != nullptr) throw pException;
return temp;
}

virtual void setIsLocalNonEscapes(
CORINFO_METHOD_HANDLE method,
uint32_t lclNum)
{
CorInfoExceptionClass* pException = nullptr;
_callbacks->setIsLocalNonEscapes(_thisHandle, &pException, method, lclNum);
if (pException != nullptr) throw pException;
}
};
6 changes: 6 additions & 0 deletions src/coreclr/tools/superpmi/superpmi-shared/agnostic.h
Original file line number Diff line number Diff line change
Expand Up @@ -609,6 +609,12 @@ struct Agnostic_ConfigIntInfo
DWORD defaultValue;
};

struct Agnostic_LocalNonEscapes
{
DWORDLONG method;
DWORD lclNum;
};

// SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASSING_DESCRIPTOR
struct Agnostic_GetSystemVAmd64PassStructInRegisterDescriptor
{
Expand Down
1 change: 1 addition & 0 deletions src/coreclr/tools/superpmi/superpmi-shared/lwmlist.h
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ LWM(GetFpStructLowering, DWORDLONG, Agnostic_GetFpStructLowering)
LWM(GetTailCallHelpers, Agnostic_GetTailCallHelpers, Agnostic_CORINFO_TAILCALL_HELPERS)
LWM(UpdateEntryPointForTailCall, Agnostic_CORINFO_CONST_LOOKUP, Agnostic_CORINFO_CONST_LOOKUP)
LWM(GetSpecialCopyHelper, DWORDLONG, DWORDLONG)
LWM(GetIsLocalNonEscapes, Agnostic_LocalNonEscapes, DWORD)
LWM(GetThreadTLSIndex, DWORD, DLD)
LWM(GetTokenTypeAsHandle, GetTokenTypeAsHandleValue, DWORDLONG)
LWM(GetTypeForBox, DWORDLONG, DWORDLONG)
Expand Down
59 changes: 59 additions & 0 deletions src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7216,6 +7216,65 @@ CORINFO_METHOD_HANDLE MethodContext::repGetSpecialCopyHelper(CORINFO_CLASS_HANDL
return (CORINFO_METHOD_HANDLE)value;
}


void MethodContext::recGetIsLocalNonEscapes(CORINFO_METHOD_HANDLE method, uint32_t lclNum, bool result)
{
if (GetIsLocalNonEscapes == nullptr)
GetIsLocalNonEscapes = new LightWeightMap<Agnostic_LocalNonEscapes, DWORD>();

Agnostic_LocalNonEscapes key;
ZeroMemory(&key, sizeof(key)); // Zero key including any struct padding
key.method = CastHandle(method);
key.lclNum = lclNum;

DWORD value = result ? 1 : 0;
GetIsLocalNonEscapes->Add(key, value);
DEBUG_REC(dmpGetIsLocalNonEscapes(key, value));
}

void MethodContext::dmpGetIsLocalNonEscapes(const Agnostic_LocalNonEscapes& key, bool result)
{
printf("getIsLocalNonEscapes key { method = %016" PRIX64 ", lclNum=%16X }, value %d" PRIX64 "", key.method,
key.lclNum, (DWORD)result);
}

bool MethodContext::repGetIsLocalNonEscapes(CORINFO_METHOD_HANDLE method, uint32_t lclNum)
{
Agnostic_LocalNonEscapes key;
ZeroMemory(&key, sizeof(key)); // Zero key including any struct padding
key.method = CastHandle(method);
key.lclNum = lclNum;
DWORD value =
LookupByKeyOrMiss(GetIsLocalNonEscapes, key, ": key { method = %016" PRIX64 ", lclNum = %016X }",
key.method, key.lclNum);
DEBUG_REP(dmpGetIsLocalNonEscapes(key, value));
return value == 0 ? false : true;
}

void MethodContext::recSetIsLocalNonEscapes(CORINFO_METHOD_HANDLE method, uint32_t lclNum)
{
Agnostic_LocalNonEscapes key;
ZeroMemory(&key, sizeof(key)); // Zero key including any struct padding
key.method = CastHandle(method);
key.lclNum = lclNum;

DEBUG_REC(dmpSetSpecialCopyHelper(key));
}

void MethodContext::dmpSetIsLocalNonEscapes(const Agnostic_LocalNonEscapes& key)
{
printf("setIsLocalNonEscapes key { method = %016" PRIX64 ", lclNum = %016X }", key.method, key.lclNum);
}

void MethodContext::repSetIsLocalNonEscapes(CORINFO_METHOD_HANDLE method, uint32_t lclNum)
{
Agnostic_LocalNonEscapes key;
ZeroMemory(&key, sizeof(key)); // Zero key including any struct padding
key.method = CastHandle(method);
key.lclNum = lclNum;
DEBUG_REP(dmpSetIsLocalNonEscapes(key, value));
}

void MethodContext::dmpSigInstHandleMap(DWORD key, DWORDLONG value)
{
printf("SigInstHandleMap key %u, value %016" PRIX64 "", key, value);
Expand Down
9 changes: 9 additions & 0 deletions src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h
Original file line number Diff line number Diff line change
Expand Up @@ -897,6 +897,14 @@ class MethodContext
void recGetSpecialCopyHelper(CORINFO_CLASS_HANDLE type, CORINFO_METHOD_HANDLE helper);
void dmpGetSpecialCopyHelper(DWORDLONG key, DWORDLONG value);
CORINFO_METHOD_HANDLE repGetSpecialCopyHelper(CORINFO_CLASS_HANDLE type);

void recGetIsLocalNonEscapes(CORINFO_METHOD_HANDLE method, uint32_t lclNum, bool result);
void dmpGetIsLocalNonEscapes(const Agnostic_LocalNonEscapes& key, bool result);
bool repGetIsLocalNonEscapes(CORINFO_METHOD_HANDLE method, uint32_t lclNum);

void recSetIsLocalNonEscapes(CORINFO_METHOD_HANDLE method, uint32_t lclNum);
void dmpSetIsLocalNonEscapes(const Agnostic_LocalNonEscapes& key);
void repSetIsLocalNonEscapes(CORINFO_METHOD_HANDLE method, uint32_t lclNum);

void dmpSigInstHandleMap(DWORD key, DWORDLONG value);

Expand Down Expand Up @@ -1192,6 +1200,7 @@ enum mcPackets
Packet_GetSpecialCopyHelper = 224,
Packet_GetClassAssemblyName = 225,
Packet_GetSZArrayHelperEnumeratorClass = 226,
Packet_GetIsLocalNonEscapes = 227,
};

void SetDebugDumpVariables();
Expand Down
15 changes: 15 additions & 0 deletions src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2029,3 +2029,18 @@ CORINFO_METHOD_HANDLE interceptor_ICJI::getSpecialCopyHelper(CORINFO_CLASS_HANDL
mc->recGetSpecialCopyHelper(type, temp);
return temp;
}

bool interceptor_ICJI::getIsLocalNonEscapes(CORINFO_METHOD_HANDLE method, uint32_t lclNum)
{
mc->cr->AddCall("getIsLocalNonEscapes");
bool result = original_ICorJitInfo->getIsLocalNonEscapes(method, lclNum);
mc->recGetIsLocalNonEscapes(method, lclNum, result);
return result;
}

void interceptor_ICJI::setIsLocalNonEscapes(CORINFO_METHOD_HANDLE method, uint32_t lclNum)
{
mc->cr->AddCall("setIsLocalNonEscapes");
original_ICorJitInfo->setIsLocalNonEscapes(method, lclNum);
mc->recSetIsLocalNonEscapes(method, lclNum);
}
Loading

0 comments on commit 3ebe805

Please sign in to comment.