Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Armel support in crossgen2 #43706

Merged
merged 3 commits into from
Mar 17, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
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
5 changes: 5 additions & 0 deletions src/coreclr/inc/corjitflags.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,12 @@ class CORJIT_FLAGS

CORJIT_FLAG_NO_INLINING = 42, // JIT should not inline any called method into this method

#if defined(TARGET_ARM)
CORJIT_FLAG_SOFTFP_ABI = 43, // JIT should generate PC-relative address computations instead of EE relocation records
#else // !defined(TARGET_ARM)
CORJIT_FLAG_UNUSED16 = 43,
#endif // !defined(TARGET_ARM)

CORJIT_FLAG_UNUSED17 = 44,
CORJIT_FLAG_UNUSED18 = 45,
CORJIT_FLAG_UNUSED19 = 46,
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/inc/switches.h
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@
// do not work reliably with conservative GC.
#define FEATURE_CONSERVATIVE_GC 1

#if (defined(TARGET_ARM) && !defined(ARM_SOFTFP)) || defined(TARGET_ARM64)
#if (defined(TARGET_ARM) && (!defined(ARM_SOFTFP) || defined(CONFIGURABLE_ARM_ABI))) || defined(TARGET_ARM64)
#define FEATURE_HFA
#endif

Expand Down
1 change: 1 addition & 0 deletions src/coreclr/jit/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -490,6 +490,7 @@ if (CLR_CMAKE_BUILD_SUBSET_ALLJITS AND NOT CLR_CROSS_COMPONENTS_BUILD)

create_standalone_jit(TARGET clrjit_unix_armel_${ARCH_HOST_NAME} OS unix ARCH armel)
create_standalone_jit(TARGET clrjit_unix_arm_${ARCH_HOST_NAME} OS unix ARCH arm)
target_compile_definitions(clrjit_unix_arm_${ARCH_HOST_NAME} PRIVATE ARM_SOFTFP CONFIGURABLE_ARM_ABI)
create_standalone_jit(TARGET clrjit_win_arm_${ARCH_HOST_NAME} OS win ARCH arm)
create_standalone_jit(TARGET clrjit_win_x86_${ARCH_HOST_NAME} OS win ARCH x86)
else()
Expand Down
99 changes: 52 additions & 47 deletions src/coreclr/jit/codegencommon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4004,40 +4004,38 @@ void CodeGen::genFnPrologCalleeRegArgs(regNumber xtraReg, bool* pXtraRegClobbere

if (doingFloat)
{
#if defined(FEATURE_HFA) || defined(UNIX_AMD64_ABI)
insCopy = ins_Copy(TYP_DOUBLE);
// Compute xtraReg here when we have a float argument
assert(xtraReg == REG_NA);
#ifndef UNIX_AMD64_ABI
if (GlobalJitOptions::compFeatureHfa)
#endif // !UNIX_AMD64_ABI
{
insCopy = ins_Copy(TYP_DOUBLE);
// Compute xtraReg here when we have a float argument
assert(xtraReg == REG_NA);

regMaskTP fpAvailMask;
regMaskTP fpAvailMask;

fpAvailMask = RBM_FLT_CALLEE_TRASH & ~regArgMaskLive;
#if defined(FEATURE_HFA)
fpAvailMask &= RBM_ALLDOUBLE;
#else
#if !defined(UNIX_AMD64_ABI)
#error Error. Wrong architecture.
#endif // !defined(UNIX_AMD64_ABI)
#endif // defined(FEATURE_HFA)
fpAvailMask = RBM_FLT_CALLEE_TRASH & ~regArgMaskLive;
if (GlobalJitOptions::compFeatureHfa)
{
fpAvailMask &= RBM_ALLDOUBLE;
}

if (fpAvailMask == RBM_NONE)
{
fpAvailMask = RBM_ALLFLOAT & ~regArgMaskLive;
#if defined(FEATURE_HFA)
fpAvailMask &= RBM_ALLDOUBLE;
#else
#if !defined(UNIX_AMD64_ABI)
#error Error. Wrong architecture.
#endif // !defined(UNIX_AMD64_ABI)
#endif // defined(FEATURE_HFA)
}
if (fpAvailMask == RBM_NONE)
{
fpAvailMask = RBM_ALLFLOAT & ~regArgMaskLive;
if (GlobalJitOptions::compFeatureHfa)
{
fpAvailMask &= RBM_ALLDOUBLE;
}
}

assert(fpAvailMask != RBM_NONE);
assert(fpAvailMask != RBM_NONE);

// We pick the lowest avail register number
regMaskTP tempMask = genFindLowestBit(fpAvailMask);
xtraReg = genRegNumFromMask(tempMask);
#elif defined(TARGET_X86)
// We pick the lowest avail register number
regMaskTP tempMask = genFindLowestBit(fpAvailMask);
xtraReg = genRegNumFromMask(tempMask);
}
#if defined(TARGET_X86)
// This case shouldn't occur on x86 since NYI gets converted to an assert
NYI("Homing circular FP registers via xtraReg");
#endif
Expand Down Expand Up @@ -9562,20 +9560,26 @@ bool Compiler::IsHfa(CORINFO_CLASS_HANDLE hClass)

bool Compiler::IsHfa(GenTree* tree)
{
#ifdef FEATURE_HFA
return IsHfa(gtGetStructHandleIfPresent(tree));
#else
return false;
#endif
if (GlobalJitOptions::compFeatureHfa)
{
return IsHfa(gtGetStructHandleIfPresent(tree));
}
else
{
return false;
}
}

var_types Compiler::GetHfaType(GenTree* tree)
{
#ifdef FEATURE_HFA
return GetHfaType(gtGetStructHandleIfPresent(tree));
#else
return TYP_UNDEF;
#endif
if (GlobalJitOptions::compFeatureHfa)
{
return GetHfaType(gtGetStructHandleIfPresent(tree));
}
else
{
return TYP_UNDEF;
}
}

unsigned Compiler::GetHfaCount(GenTree* tree)
Expand All @@ -9585,18 +9589,19 @@ unsigned Compiler::GetHfaCount(GenTree* tree)

var_types Compiler::GetHfaType(CORINFO_CLASS_HANDLE hClass)
{
#ifdef FEATURE_HFA
if (hClass != NO_CLASS_HANDLE)
if (GlobalJitOptions::compFeatureHfa)
{
CorInfoHFAElemType elemKind = info.compCompHnd->getHFAType(hClass);
if (elemKind != CORINFO_HFA_ELEM_NONE)
if (hClass != NO_CLASS_HANDLE)
{
// This type may not appear elsewhere, but it will occupy a floating point register.
compFloatingPointUsed = true;
CorInfoHFAElemType elemKind = info.compCompHnd->getHFAType(hClass);
if (elemKind != CORINFO_HFA_ELEM_NONE)
{
// This type may not appear elsewhere, but it will occupy a floating point register.
compFloatingPointUsed = true;
}
return HfaTypeFromElemKind(elemKind);
}
return HfaTypeFromElemKind(elemKind);
}
#endif // FEATURE_HFA
return TYP_UNDEF;
}

Expand Down
131 changes: 53 additions & 78 deletions src/coreclr/jit/compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,12 @@ bool Compiler::s_pJitFunctionFileInitialized = false;
MethodSet* Compiler::s_pJitMethodSet = nullptr;
#endif // DEBUG

#ifdef CONFIGURABLE_ARM_ABI
// static
bool GlobalJitOptions::compFeatureHfa = false;
LONG GlobalJitOptions::compUseSoftFPConfigured = 0;
#endif // CONFIGURABLE_ARM_ABI

/*****************************************************************************
*
* Little helpers to grab the current cycle counter value; this is done
Expand Down Expand Up @@ -468,49 +474,6 @@ var_types Compiler::getJitGCType(BYTE gcType)
return result;
}

#ifdef ARM_SOFTFP
//---------------------------------------------------------------------------
// IsSingleFloat32Struct:
// Check if the given struct type contains only one float32 value type
//
// Arguments:
// clsHnd - the handle for the struct type
//
// Return Value:
// true if the given struct type contains only one float32 value type,
// false otherwise.
//

bool Compiler::isSingleFloat32Struct(CORINFO_CLASS_HANDLE clsHnd)
{
for (;;)
{
// all of class chain must be of value type and must have only one field
if (!info.compCompHnd->isValueClass(clsHnd) || info.compCompHnd->getClassNumInstanceFields(clsHnd) != 1)
{
return false;
}

CORINFO_CLASS_HANDLE* pClsHnd = &clsHnd;
CORINFO_FIELD_HANDLE fldHnd = info.compCompHnd->getFieldInClass(clsHnd, 0);
CorInfoType fieldType = info.compCompHnd->getFieldType(fldHnd, pClsHnd);

switch (fieldType)
{
case CORINFO_TYPE_VALUECLASS:
clsHnd = *pClsHnd;
break;

case CORINFO_TYPE_FLOAT:
return true;

default:
return false;
}
}
}
#endif // ARM_SOFTFP

#ifdef TARGET_X86
//---------------------------------------------------------------------------
// isTrivialPointerSizedStruct:
Expand Down Expand Up @@ -623,53 +586,44 @@ var_types Compiler::getPrimitiveTypeForStruct(unsigned structSize, CORINFO_CLASS

var_types useType = TYP_UNKNOWN;

// Start by determining if we have an HFA/HVA with a single element.
#ifdef FEATURE_HFA
// Start by determining if we have an HFA/HVA with a single element.
if (GlobalJitOptions::compFeatureHfa)
{
#if defined(TARGET_WINDOWS) && defined(TARGET_ARM64)
// Arm64 Windows VarArg methods arguments will not classify HFA types, they will need to be treated
// as if they are not HFA types.
if (!isVarArg)
// Arm64 Windows VarArg methods arguments will not classify HFA types, they will need to be treated
// as if they are not HFA types.
if (!isVarArg)
#endif // defined(TARGET_WINDOWS) && defined(TARGET_ARM64)
{
switch (structSize)
{
case 4:
case 8:
switch (structSize)
{
case 4:
case 8:
#ifdef TARGET_ARM64
case 16:
case 16:
#endif // TARGET_ARM64
{
var_types hfaType;
#ifdef ARM_SOFTFP
// For ARM_SOFTFP, HFA is unsupported so we need to check in another way.
// This matters only for size-4 struct because bigger structs would be processed with RetBuf.
if (isSingleFloat32Struct(clsHnd))
{
hfaType = TYP_FLOAT;
}
#else // !ARM_SOFTFP
hfaType = GetHfaType(clsHnd);
#endif // ARM_SOFTFP
// We're only interested in the case where the struct size is equal to the size of the hfaType.
if (varTypeIsValidHfaType(hfaType))
{
if (genTypeSize(hfaType) == structSize)
var_types hfaType = GetHfaType(clsHnd);
// We're only interested in the case where the struct size is equal to the size of the hfaType.
if (varTypeIsValidHfaType(hfaType))
{
useType = hfaType;
}
else
{
return TYP_UNKNOWN;
if (genTypeSize(hfaType) == structSize)
{
useType = hfaType;
}
else
{
return TYP_UNKNOWN;
}
}
}
}
}
if (useType != TYP_UNKNOWN)
{
return useType;
if (useType != TYP_UNKNOWN)
{
return useType;
}
}
}
#endif // FEATURE_HFA

// Now deal with non-HFA/HVA structs.
switch (structSize)
Expand Down Expand Up @@ -3273,6 +3227,27 @@ void Compiler::compInitOptions(JitFlags* jitFlags)
}
#endif // FEATURE_FASTTAILCALL

#ifdef CONFIGURABLE_ARM_ABI
opts.compUseSoftFP = jitFlags->IsSet(JitFlags::JIT_FLAG_SOFTFP_ABI);
unsigned int softFPConfig = opts.compUseSoftFP ? 2 : 1;
unsigned int oldSoftFPConfig =
InterlockedCompareExchange(&GlobalJitOptions::compUseSoftFPConfigured, softFPConfig, 0);
if (oldSoftFPConfig != softFPConfig && oldSoftFPConfig != 0)
{
// There are no current scenarios where the abi can change during the lifetime of a process
// that uses the JIT. If such a change occurs, either compFeatureHfa will need to change to a TLS static
// or we will need to have some means to reset the flag safely.
NO_WAY("SoftFP ABI setting changed during lifetime of process");
}

GlobalJitOptions::compFeatureHfa = !opts.compUseSoftFP;
#elif defined(ARM_SOFTFP)
// Armel is unconditionally enabled in the JIT. Verify that the VM side agrees.
assert(jitFlags->IsSet(JitFlags::JIT_FLAG_SOFTFP_ABI));
#elif TARGET_ARM
assert(!jitFlags->IsSet(JitFlags::JIT_FLAG_SOFTFP_ABI));
#endif // CONFIGURABLE_ARM_ABI

opts.compScopeInfo = opts.compDbgInfo;

#ifdef LATE_DISASM
Expand Down
Loading