From 56be51caaafd867826775bc59d327136e388342b Mon Sep 17 00:00:00 2001 From: xuliangyu Date: Thu, 13 Jul 2023 16:42:33 +0800 Subject: [PATCH] [LoongArch64] Implement Inline TLS field access for LoongArch64. --- src/coreclr/jit/codegenloongarch64.cpp | 9 ++++++++- src/coreclr/jit/helperexpansion.cpp | 6 ++++++ src/coreclr/vm/jitinterface.cpp | 13 +++++++------ src/coreclr/vm/loongarch64/asmhelpers.S | 14 ++++++++++++++ 4 files changed, 35 insertions(+), 7 deletions(-) diff --git a/src/coreclr/jit/codegenloongarch64.cpp b/src/coreclr/jit/codegenloongarch64.cpp index 6198764c91839e..6e649a11760724 100644 --- a/src/coreclr/jit/codegenloongarch64.cpp +++ b/src/coreclr/jit/codegenloongarch64.cpp @@ -1966,7 +1966,14 @@ void CodeGen::genCodeForStoreLclVar(GenTreeLclVar* lclNode) } else // store into register (i.e move into register) { - if (dataReg != targetReg) + if (data->IsIconHandle(GTF_ICON_TLS_HDL)) + { + assert(data->AsIntCon()->IconValue() == 0); + emitAttr attr = emitActualTypeSize(targetType); + // need to load the address from $tp. + emit->emitIns_R_R_I(INS_ori, attr, targetReg, REG_TP, 0); + } + else if (dataReg != targetReg) { // Assign into targetReg when dataReg (from op1) is not the same register inst_Mov(targetType, targetReg, dataReg, true, emitActualTypeSize(targetType)); diff --git a/src/coreclr/jit/helperexpansion.cpp b/src/coreclr/jit/helperexpansion.cpp index b95f75f075a784..271030a9e2dd9c 100644 --- a/src/coreclr/jit/helperexpansion.cpp +++ b/src/coreclr/jit/helperexpansion.cpp @@ -658,6 +658,12 @@ bool Compiler::fgExpandThreadLocalAccessForCall(BasicBlock** pBlock, Statement* // mrs xt, tpidr_elf0 // mov xd, [xt+cns] tlsValue = gtNewIconHandleNode(0, GTF_ICON_TLS_HDL); +#elif defined(TARGET_LOONGARCH64) + // Code sequence to access thread local variable on linux/loongarch64: + // + // ori, targetReg, $tp, 0 + // load rd, targetReg, cns + tlsValue = gtNewIconHandleNode(0, GTF_ICON_TLS_HDL); #else assert(!"Unsupported scenario of optimizing TLS access on Linux Arm32/x86"); #endif diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index e813d6f2d274e9..f105806bc532be 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -1414,11 +1414,11 @@ static void* GetTlsIndexObjectAddress() return GetThreadStaticDescriptor(p); } -#elif TARGET_ARM64 +#elif defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) extern "C" size_t GetThreadStaticsVariableOffset(); -#endif // TARGET_ARM64 +#endif // TARGET_ARM64 || TARGET_LOONGARCH64 #endif // TARGET_WINDOWS @@ -1452,10 +1452,11 @@ void CEEInfo::getThreadLocalStaticBlocksInfo (CORINFO_THREAD_STATIC_BLOCKS_INFO* pInfo->tlsGetAddrFtnPtr = reinterpret_cast(&__tls_get_addr); pInfo->tlsIndexObject = GetTlsIndexObjectAddress(); -#elif defined(TARGET_ARM64) +#elif defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) - // For Linux/arm64, just get the offset of thread static variable, and during execution, - // this offset, taken from trpid_elp0 system register gives back the thread variable address. + // For Linux arm64/loongarch64, just get the offset of thread static variable, and during execution, + // this offset, arm64 taken from trpid_elp0 system register gives back the thread variable address. + // this offset, loongarch64 taken from $tp register gives back the thread variable address. threadStaticBaseOffset = GetThreadStaticsVariableOffset(); #else @@ -1600,7 +1601,7 @@ void CEEInfo::getFieldInfo (CORINFO_RESOLVED_TOKEN * pResolvedToken, if (optimizeThreadStaticAccess) { - // For windows x64/x86/arm64, linux x64/arm64: + // For windows x64/x86/arm64, linux x64/arm64/loongarch64: // We convert the TLS access to the optimized helper where we will store // the static blocks in TLS directly and access them via inline code. if ((pResult->helper == CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_NOCTOR) || diff --git a/src/coreclr/vm/loongarch64/asmhelpers.S b/src/coreclr/vm/loongarch64/asmhelpers.S index dd429114767abf..7fcf19e94e7d37 100644 --- a/src/coreclr/vm/loongarch64/asmhelpers.S +++ b/src/coreclr/vm/loongarch64/asmhelpers.S @@ -1079,3 +1079,17 @@ NESTED_ENTRY OnCallCountThresholdReachedStub, _TEXT, NoHandler NESTED_END OnCallCountThresholdReachedStub, _TEXT #endif // FEATURE_TIERED_COMPILATION + +// ------------------------------------------------------------------ +// size_t GetThreadStaticsVariableOffset() + +// Helper to calculate the offset of native thread local variable `t_ThreadStatics` in TCB. The offset has to be found at runtime +// once linker does its relocation and fixup of thread locals. The offset, after calculation is returned in `$a0` register. + +LEAF_ENTRY GetThreadStaticsVariableOffset, _TEXT + PROLOG_SAVE_REG_PAIR_INDEXED 22, 1, 16 + la.tls.ie $a0, t_ThreadStatics + EPILOG_RESTORE_REG_PAIR_INDEXED 22, 1, 16 + EPILOG_RETURN +LEAF_END GetThreadStaticsVariableOffset, _TEXT +// ------------------------------------------------------------------