Skip to content

Commit

Permalink
[LoongArch64] Implement Inline TLS field access for LoongArch64. (#88819
Browse files Browse the repository at this point in the history
)
  • Loading branch information
LuckyXu-HF committed Jul 13, 2023
1 parent c6e8726 commit 76a7d1e
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 7 deletions.
9 changes: 8 additions & 1 deletion src/coreclr/jit/codegenloongarch64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand Down
6 changes: 6 additions & 0 deletions src/coreclr/jit/helperexpansion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
13 changes: 7 additions & 6 deletions src/coreclr/vm/jitinterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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


Expand Down Expand Up @@ -1452,10 +1452,11 @@ void CEEInfo::getThreadLocalStaticBlocksInfo (CORINFO_THREAD_STATIC_BLOCKS_INFO*
pInfo->tlsGetAddrFtnPtr = reinterpret_cast<void*>(&__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
Expand Down Expand Up @@ -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) ||
Expand Down
14 changes: 14 additions & 0 deletions src/coreclr/vm/loongarch64/asmhelpers.S
Original file line number Diff line number Diff line change
Expand Up @@ -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
// ------------------------------------------------------------------

0 comments on commit 76a7d1e

Please sign in to comment.