Skip to content

Commit

Permalink
Universal arm crossgen compiler (#58279)
Browse files Browse the repository at this point in the history
Stop generating OS specific compilers for the arm and arm64 architectures for use in crossgen2
- As it turns out the OS differences here are relatively minor and fairly easy to handle with runtime switches.
- However, when an exact target is known we can generate better code by having the various if statements evaluate to a constant true/false. (This is done for all runtime jit builds)
- This has been validated to produce binary identical output for generating System.Private.CoreLib.dll on the various architectures.
- This work reduces the distribution size of crossgen2, and also reduces the amount of time it takes to build everything (Most notably, the Mac build times in PR's are reduced by 5-7 minutes, but improvements are visible across all of/architecture pairs)
  • Loading branch information
davidwrighton authored Sep 28, 2021
1 parent de4151e commit fcaba18
Show file tree
Hide file tree
Showing 71 changed files with 784 additions and 526 deletions.
6 changes: 4 additions & 2 deletions src/coreclr/ToolBox/superpmi/mcs/removedup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,8 @@ bool RemoveDup::unique(MethodContext* mc)

CORINFO_METHOD_INFO newInfo;
unsigned newFlags = 0;
mc->repCompileMethod(&newInfo, &newFlags);
CORINFO_OS newOs = CORINFO_WINNT;
mc->repCompileMethod(&newInfo, &newFlags, &newOs);

// Assume that there are lots of duplicates, so don't allocate a new buffer for the MD5 hash data
// until we know we're going to add it to the map.
Expand Down Expand Up @@ -95,7 +96,8 @@ bool RemoveDup::uniqueLegacy(MethodContext* mc)

CORINFO_METHOD_INFO newInfo;
unsigned newFlags = 0;
mc->repCompileMethod(&newInfo, &newFlags);
CORINFO_OS newOs = CORINFO_WINNT;
mc->repCompileMethod(&newInfo, &newFlags, &newOs);

if (m_inFileLegacy->GetIndex(newInfo.ILCodeSize) == -1)
m_inFileLegacy->Add(newInfo.ILCodeSize, new DenseLightWeightMap<MethodContext*>());
Expand Down
8 changes: 5 additions & 3 deletions src/coreclr/ToolBox/superpmi/mcs/verbdumpmap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,17 @@ void DumpMapHeader()
// printf("process name,");
printf("method name,");
printf("full signature,");
printf("jit flags\n");
printf("jit flags,");
printf("os\n");
}

void DumpMap(int index, MethodContext* mc)
{
CORINFO_METHOD_INFO cmi;
unsigned int flags = 0;
CORINFO_OS os;

mc->repCompileMethod(&cmi, &flags);
mc->repCompileMethod(&cmi, &flags, &os);

const char* moduleName = nullptr;
const char* methodName = mc->repGetMethodName(cmi.ftn, &moduleName);
Expand Down Expand Up @@ -121,7 +123,7 @@ void DumpMap(int index, MethodContext* mc)
}
}

printf(", %s\n", SpmiDumpHelper::DumpJitFlags(rawFlags).c_str());
printf(", %s, %d\n", SpmiDumpHelper::DumpJitFlags(rawFlags).c_str(), (int)os);
}

int verbDumpMap::DoWork(const char* nameOfInput)
Expand Down
3 changes: 2 additions & 1 deletion src/coreclr/ToolBox/superpmi/mcs/verbildump.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -927,8 +927,9 @@ void DumpIL(MethodContext* mc)
{
CORINFO_METHOD_INFO cmi;
unsigned int flags = 0;
CORINFO_OS os = CORINFO_WINNT;

mc->repCompileMethod(&cmi, &flags);
mc->repCompileMethod(&cmi, &flags, &os);

const char* moduleName = nullptr;
const char* methodName = mc->repGetMethodName(cmi.ftn, &moduleName);
Expand Down
1 change: 1 addition & 0 deletions src/coreclr/ToolBox/superpmi/superpmi-shared/agnostic.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ struct Agnostic_CompileMethod
{
Agnostic_CORINFO_METHOD_INFO info;
DWORD flags;
DWORD os;
};

struct Agnostic_InitClass
Expand Down
3 changes: 2 additions & 1 deletion src/coreclr/ToolBox/superpmi/superpmi-shared/asmdumper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ void ASMDumper::DumpToFile(HANDLE hFile, MethodContext* mc, CompileResult* cr)
{
CORINFO_METHOD_INFO info;
unsigned flags = 0;
mc->repCompileMethod(&info, &flags);
CORINFO_OS os = CORINFO_WINNT;
mc->repCompileMethod(&info, &flags, &os);

#define bufflen 4096
DWORD bytesWritten;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
// * In the 32 bit jit this is implemented by code:CILJit.compileMethod
// * For the 64 bit jit this is implemented by code:PreJit.compileMethod
//
// Note: Obfuscators that are hacking the JIT depend on this method having __stdcall calling convention
// Note: setTargetOS must be called before this api is used.
CorJitResult compileMethod(ICorJitInfo* comp, /* IN */
struct CORINFO_METHOD_INFO* info, /* IN */
unsigned /* code:CorJitFlag */ flags, /* IN */
Expand All @@ -47,4 +47,10 @@ void getVersionIdentifier(GUID* versionIdentifier /* OUT */
// intrinsics, so the EE should use the default size (i.e. the size of the IL implementation).
unsigned getMaxIntrinsicSIMDVectorLength(CORJIT_FLAGS cpuCompileFlags); /* { return 0; } */

// Some JIT's may support multiple OSs. This api provides a means to specify to the JIT what OS it should
// be trying to compile. This api does not produce any errors, any errors are to be generated by the
// the compileMethod call, which will call back into the VM to ensure bits are correctly setup.
//
// Note: this api MUST be called before the compileMethod is called for the first time in the process.
void setTargetOS(CORINFO_OS os);
#endif
29 changes: 20 additions & 9 deletions src/coreclr/ToolBox/superpmi/superpmi-shared/methodcontext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -384,11 +384,13 @@ bool MethodContext::Equal(MethodContext* other)
// Compare MethodInfo's first.
CORINFO_METHOD_INFO otherInfo;
unsigned otherFlags = 0;
other->repCompileMethod(&otherInfo, &otherFlags);
CORINFO_OS otherOs = CORINFO_WINNT;
other->repCompileMethod(&otherInfo, &otherFlags, &otherOs);

CORINFO_METHOD_INFO ourInfo;
unsigned ourFlags = 0;
repCompileMethod(&ourInfo, &ourFlags);
CORINFO_OS ourOs = CORINFO_WINNT;
repCompileMethod(&ourInfo, &ourFlags, &ourOs);

if (otherInfo.ILCodeSize != ourInfo.ILCodeSize)
return false;
Expand Down Expand Up @@ -419,6 +421,8 @@ bool MethodContext::Equal(MethodContext* other)
return false;
if (otherFlags != ourFlags)
return false;
if (otherOs != ourOs)
return false;

// Now compare the other maps to "estimate" equality.

Expand Down Expand Up @@ -643,7 +647,7 @@ unsigned int toCorInfoSize(CorInfoType cit)
return -1;
}

void MethodContext::recCompileMethod(CORINFO_METHOD_INFO* info, unsigned flags)
void MethodContext::recCompileMethod(CORINFO_METHOD_INFO* info, unsigned flags, CORINFO_OS os)
{
if (CompileMethod == nullptr)
CompileMethod = new LightWeightMap<DWORD, Agnostic_CompileMethod>();
Expand All @@ -662,21 +666,23 @@ void MethodContext::recCompileMethod(CORINFO_METHOD_INFO* info, unsigned flags)
value.info.args = SpmiRecordsHelper::StoreAgnostic_CORINFO_SIG_INFO(info->args, CompileMethod, SigInstHandleMap);
value.info.locals = SpmiRecordsHelper::StoreAgnostic_CORINFO_SIG_INFO(info->locals, CompileMethod, SigInstHandleMap);

value.os = (DWORD)os;

value.flags = (DWORD)flags;

CompileMethod->Add(0, value);
DEBUG_REC(dmpCompileMethod(0, value));
}
void MethodContext::dmpCompileMethod(DWORD key, const Agnostic_CompileMethod& value)
{
printf("CompileMethod key %u, value ftn-%016llX scp-%016llX ilo-%u ils-%u ms-%u ehc-%u opt-%u rk-%u args-%s locals-%s flg-%08X",
printf("CompileMethod key %u, value ftn-%016llX scp-%016llX ilo-%u ils-%u ms-%u ehc-%u opt-%u rk-%u args-%s locals-%s flg-%08X os-%u",
key, value.info.ftn, value.info.scope, value.info.ILCode_offset, value.info.ILCodeSize, value.info.maxStack,
value.info.EHcount, value.info.options, value.info.regionKind,
SpmiDumpHelper::DumpAgnostic_CORINFO_SIG_INFO(value.info.args, CompileMethod, SigInstHandleMap).c_str(),
SpmiDumpHelper::DumpAgnostic_CORINFO_SIG_INFO(value.info.locals, CompileMethod, SigInstHandleMap).c_str(),
value.flags);
value.flags, value.os);
}
void MethodContext::repCompileMethod(CORINFO_METHOD_INFO* info, unsigned* flags)
void MethodContext::repCompileMethod(CORINFO_METHOD_INFO* info, unsigned* flags, CORINFO_OS* os)
{
AssertMapAndKeyExistNoMessage(CompileMethod, 0);

Expand All @@ -699,6 +705,7 @@ void MethodContext::repCompileMethod(CORINFO_METHOD_INFO* info, unsigned* flags)
info->locals = SpmiRecordsHelper::Restore_CORINFO_SIG_INFO(value.info.locals, CompileMethod, SigInstHandleMap);

*flags = (unsigned)value.flags;
*os = (CORINFO_OS)value.os;
}

void MethodContext::recGetMethodClass(CORINFO_METHOD_HANDLE methodHandle, CORINFO_CLASS_HANDLE classHandle)
Expand Down Expand Up @@ -4188,7 +4195,9 @@ void MethodContext::repGetEEInfo(CORINFO_EE_INFO* pEEInfoOut)
pEEInfoOut->osPageSize = (size_t)0x1000;
pEEInfoOut->maxUncheckedOffsetForNullObject = (size_t)((32 * 1024) - 1);
pEEInfoOut->targetAbi = CORINFO_DESKTOP_ABI;
#ifdef TARGET_UNIX
#ifdef TARGET_OSX
pEEInfoOut->osType = CORINFO_MACOS;
#elif defined(TARGET_UNIX)
pEEInfoOut->osType = CORINFO_UNIX;
#else
pEEInfoOut->osType = CORINFO_WINNT;
Expand Down Expand Up @@ -6848,7 +6857,8 @@ int MethodContext::dumpMethodIdentityInfoToBuffer(char* buff, int len, bool igno
}
else
{
repCompileMethod(&info, &flags);
CORINFO_OS os;
repCompileMethod(&info, &flags, &os);
pInfo = &info;
}

Expand Down Expand Up @@ -6982,7 +6992,8 @@ bool MethodContext::hasPgoData(bool& hasEdgeProfile, bool& hasClassProfile, bool
// Obtain the Method Info structure for this method
CORINFO_METHOD_INFO info;
unsigned flags = 0;
repCompileMethod(&info, &flags);
CORINFO_OS os;
repCompileMethod(&info, &flags, &os);

if ((GetPgoInstrumentationResults != nullptr) &&
(GetPgoInstrumentationResults->GetIndex(CastHandle(info.ftn)) != -1))
Expand Down
4 changes: 2 additions & 2 deletions src/coreclr/ToolBox/superpmi/superpmi-shared/methodcontext.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,9 +109,9 @@ class MethodContext

void dmpEnvironment(DWORD key, const Agnostic_Environment& value);

void recCompileMethod(CORINFO_METHOD_INFO* info, unsigned flags);
void recCompileMethod(CORINFO_METHOD_INFO* info, unsigned flags, CORINFO_OS os);
void dmpCompileMethod(DWORD key, const Agnostic_CompileMethod& value);
void repCompileMethod(CORINFO_METHOD_INFO* info, unsigned* flags);
void repCompileMethod(CORINFO_METHOD_INFO* info, unsigned* flags, CORINFO_OS* os);

void recGetMethodClass(CORINFO_METHOD_HANDLE methodHandle, CORINFO_CLASS_HANDLE classHandle);
void dmpGetMethodClass(DWORDLONG key, DWORDLONG value);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,12 @@

#define fatMC // this is nice to have on so ildump works...

void interceptor_ICJC::setTargetOS(CORINFO_OS os)
{
currentOs = os;
original_ICorJitCompiler->setTargetOS(os);
}

CorJitResult interceptor_ICJC::compileMethod(ICorJitInfo* comp, /* IN */
struct CORINFO_METHOD_INFO* info, /* IN */
unsigned /* code:CorJitFlag */ flags, /* IN */
Expand All @@ -24,7 +30,7 @@ CorJitResult interceptor_ICJC::compileMethod(ICorJitInfo* comp,
our_ICorJitInfo.mc = mc;
our_ICorJitInfo.mc->cr->recProcessName(GetCommandLineA());

our_ICorJitInfo.mc->recCompileMethod(info, flags);
our_ICorJitInfo.mc->recCompileMethod(info, flags, currentOs);

// force some extra data into our tables..
// data probably not needed with RyuJIT, but needed in 4.5 and 4.5.1 to help with catching cached values
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ class interceptor_ICJC : public ICorJitCompiler
// Added to help us track the original icjc and be able to easily indirect to it.
ICorJitCompiler* original_ICorJitCompiler;
HANDLE hFile;
CORINFO_OS currentOs;
};

#endif
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,16 @@ extern "C" DLLEXPORT ICorJitCompiler* getJit()
pJitInstance = new interceptor_ICJC();
pJitInstance->original_ICorJitCompiler = tICJI;

#ifdef TARGET_WINDOWS
pJitInstance->currentOs = CORINFO_WINNT;
#elif defined(TARGET_OSX)
pJitInstance->currentOs = CORINFO_MACOS;
#elif defined(TARGET_UNIX)
pJitInstance->currentOs = CORINFO_UNIX;
#else
#error No target os defined
#endif

// create our datafile
pJitInstance->hFile = CreateFileW(g_dataFileName, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@
#include "icorjitcompiler.h"
#include "icorjitinfo.h"

void interceptor_ICJC::setTargetOS(CORINFO_OS os)
{
original_ICorJitCompiler->setTargetOS(os);
}

CorJitResult interceptor_ICJC::compileMethod(ICorJitInfo* comp, /* IN */
struct CORINFO_METHOD_INFO* info, /* IN */
unsigned /* code:CorJitFlag */ flags, /* IN */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@
#include "icorjitcompiler.h"
#include "icorjitinfo.h"

void interceptor_ICJC::setTargetOS(CORINFO_OS os)
{
original_ICorJitCompiler->setTargetOS(os);
}

CorJitResult interceptor_ICJC::compileMethod(ICorJitInfo* comp, /* IN */
struct CORINFO_METHOD_INFO* info, /* IN */
unsigned /* code:CorJitFlag */ flags, /* IN */
Expand Down
8 changes: 5 additions & 3 deletions src/coreclr/ToolBox/superpmi/superpmi/jitinstance.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -303,14 +303,16 @@ JitInstance::Result JitInstance::CompileMethod(MethodContext* MethodToCompile, i

PAL_TRY(Param*, pParam, &param)
{
uint8_t* NEntryBlock = nullptr;
uint32_t NCodeSizeBlock = 0;
uint8_t* NEntryBlock = nullptr;
uint32_t NCodeSizeBlock = 0;
CORINFO_OS os = CORINFO_WINNT;

pParam->pThis->mc->repCompileMethod(&pParam->info, &pParam->flags);
pParam->pThis->mc->repCompileMethod(&pParam->info, &pParam->flags, &os);
if (pParam->collectThroughput)
{
pParam->pThis->lt.Start();
}
pParam->pThis->pJitInstance->setTargetOS(os);
CorJitResult jitResult = pParam->pThis->pJitInstance->compileMethod(pParam->pThis->icji, &pParam->info,
pParam->flags, &NEntryBlock, &NCodeSizeBlock);
if (pParam->collectThroughput)
Expand Down
3 changes: 2 additions & 1 deletion src/coreclr/ToolBox/superpmi/superpmi/methodstatsemitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@ void MethodStatsEmitter::Emit(int methodNumber, MethodContext* mc, ULONGLONG fir
// Obtain the IL code size for this method
CORINFO_METHOD_INFO info;
unsigned flags = 0;
mc->repCompileMethod(&info, &flags);
CORINFO_OS os = CORINFO_WINNT;
mc->repCompileMethod(&info, &flags, &os);

charCount += sprintf_s(rowData + charCount, _countof(rowData) - charCount, "%d,", info.ILCodeSize);
}
Expand Down
6 changes: 4 additions & 2 deletions src/coreclr/ToolBox/superpmi/superpmi/neardiffer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -930,7 +930,8 @@ bool NearDiffer::compareVars(MethodContext* mc, CompileResult* cr1, CompileResul

CORINFO_METHOD_INFO info;
unsigned flags = 0;
mc->repCompileMethod(&info, &flags);
CORINFO_OS os = CORINFO_WINNT;
mc->repCompileMethod(&info, &flags, &os);

bool set1 = cr1->repSetVars(&ftn_1, &cVars_1, &vars_1);
bool set2 = cr2->repSetVars(&ftn_2, &cVars_2, &vars_2);
Expand Down Expand Up @@ -1003,7 +1004,8 @@ bool NearDiffer::compareBoundaries(MethodContext* mc, CompileResult* cr1, Compil

CORINFO_METHOD_INFO info;
unsigned flags = 0;
mc->repCompileMethod(&info, &flags);
CORINFO_OS os = CORINFO_WINNT;
mc->repCompileMethod(&info, &flags, &os);

bool set1 = cr1->repSetBoundaries(&ftn_1, &cMap_1, &map_1);
bool set2 = cr2->repSetBoundaries(&ftn_2, &cMap_2, &map_2);
Expand Down
5 changes: 4 additions & 1 deletion src/coreclr/clrdefinitions.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,10 @@ function(set_target_definitions_to_custom_os_and_arch)
if ((TARGETDETAILS_ARCH STREQUAL "arm64") AND (TARGETDETAILS_OS STREQUAL "unix_osx"))
target_compile_definitions(${TARGETDETAILS_TARGET} PRIVATE OSX_ARM64_ABI)
endif()
else()
if (TARGETDETAILS_OS STREQUAL "unix_osx")
target_compile_definitions(${TARGETDETAILS_TARGET} PRIVATE TARGET_OSX)
endif()
elseif (TARGETDETAILS_OS STREQUAL "win")
target_compile_definitions(${TARGETDETAILS_TARGET} PRIVATE TARGET_WINDOWS)
endif((TARGETDETAILS_OS MATCHES "^unix"))

Expand Down
26 changes: 16 additions & 10 deletions src/coreclr/crosscomponents.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,33 @@

if (CLR_CMAKE_HOST_OS STREQUAL CLR_CMAKE_TARGET_OS)
install_clr (TARGETS
clrjit
DESTINATIONS . sharedFramework
COMPONENT crosscomponents
)
install_clr (TARGETS
clrjit
jitinterface_${ARCH_HOST_NAME}
DESTINATIONS .
COMPONENT crosscomponents
)

if(CLR_CMAKE_TARGET_OSX AND ARCH_TARGET_NAME STREQUAL arm64)
if (CLR_CMAKE_TARGET_OSX AND ARCH_TARGET_NAME STREQUAL arm64)
install_clr (TARGETS
clrjit_universal_${ARCH_TARGET_NAME}_${ARCH_HOST_NAME}
DESTINATIONS .
COMPONENT crosscomponents
)
elseif (CLR_CMAKE_TARGET_ARCH_ARM OR CLR_CMAKE_TARGET_ARCH_ARM64)
install_clr (TARGETS
clrjit_unix_osx_${ARCH_TARGET_NAME}_${ARCH_HOST_NAME}
DESTINATIONS . sharedFramework
clrjit_universal_${ARCH_TARGET_NAME}_${ARCH_HOST_NAME}
DESTINATIONS .
COMPONENT crosscomponents
)
elseif (CLR_CMAKE_TARGET_UNIX)
install_clr (TARGETS
clrjit_unix_${ARCH_TARGET_NAME}_${ARCH_HOST_NAME}
DESTINATIONS . sharedFramework
DESTINATIONS .
COMPONENT crosscomponents
)
else()
install_clr (TARGETS
clrjit_win_${ARCH_TARGET_NAME}_${ARCH_HOST_NAME}
DESTINATIONS .
COMPONENT crosscomponents
)
endif()
Expand Down
Loading

0 comments on commit fcaba18

Please sign in to comment.