Skip to content
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
12 changes: 11 additions & 1 deletion src/coreclr/jit/codegenriscv64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1607,7 +1607,17 @@ void CodeGen::genCodeForStoreLclVar(GenTreeLclVar* lclNode)
}
else // store into register (i.e move into register)
{
inst_Mov(targetType, targetReg, dataReg, true);
if (data->IsIconHandle(GTF_ICON_TLS_HDL))
{
assert(data->AsIntCon()->IconValue() == 0);
emitAttr attr = emitActualTypeSize(targetType);
// need to load the address from thread pointer reg
emit->emitIns_R_R(INS_mov, attr, targetReg, REG_TP);
}
else
{
inst_Mov(targetType, targetReg, dataReg, true);
}
genProduceReg(lclNode);
}
}
Expand Down
10 changes: 7 additions & 3 deletions src/coreclr/jit/helperexpansion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -652,17 +652,21 @@ bool Compiler::fgExpandThreadLocalAccessForCall(BasicBlock** pBlock, Statement*
#ifdef UNIX_X86_ABI
tlsRefCall->gtFlags &= ~GTF_CALL_POP_ARGS;
#endif // UNIX_X86_ABI
#elif defined(TARGET_ARM64)
#elif defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64)
// Code sequence to access thread local variable on linux/arm64:
//
// 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
//
// Code sequence to access thread local variable on linux/riscv64:
//
// mov targetReg, $tp, 0

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mov targetReg, $tp is ok ?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that's what gcc/clang emits on RISC-V to access a thread local var.

// ld rd, targetReg(cns)
tlsValue = gtNewIconHandleNode(0, GTF_ICON_TLS_HDL);
#else
assert(!"Unsupported scenario of optimizing TLS access on Linux Arm32/x86");
Expand Down
14 changes: 6 additions & 8 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 defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64)
#elif defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64)

extern "C" size_t GetThreadStaticsVariableOffset();

#endif // TARGET_ARM64 || TARGET_LOONGARCH64
#endif // TARGET_ARM64 || TARGET_LOONGARCH64 || TARGET_RISCV64
#endif // TARGET_WINDOWS


Expand Down Expand Up @@ -1452,9 +1452,9 @@ void CEEInfo::getThreadLocalStaticBlocksInfo (CORINFO_THREAD_STATIC_BLOCKS_INFO*
pInfo->tlsGetAddrFtnPtr = reinterpret_cast<void*>(&__tls_get_addr);
pInfo->tlsIndexObject = GetTlsIndexObjectAddress();

#elif defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64)
#elif defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64)

// For Linux arm64/loongarch64, just get the offset of thread static variable, and during execution,
// For Linux arm64/loongarch64/riscv64, 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();
Expand Down Expand Up @@ -1588,20 +1588,18 @@ void CEEInfo::getFieldInfo (CORINFO_RESOLVED_TOKEN * pResolvedToken,
// Optimization is disabled for linux/x86
#elif defined(TARGET_LINUX_MUSL) && defined(TARGET_ARM64)
// Optimization is disabled for linux musl arm64
#elif defined(TARGET_RISCV64)
// Optimization is disabled for riscv64
#else
bool optimizeThreadStaticAccess = true;
#if !defined(TARGET_OSX) && defined(TARGET_UNIX) && defined(TARGET_AMD64)
// For linux/x64, check if compiled coreclr as .so file and not single file.
// For single file, the `tls_index` might not be accurate.
// Do not perform this optimization in such case.
optimizeThreadStaticAccess = GetTlsIndexObjectAddress() != nullptr;
#endif // TARGET_UNIX && TARGET_AMD64
#endif // !TARGET_OSX && TARGET_UNIX && TARGET_AMD64

if (optimizeThreadStaticAccess)
{
// For windows x64/x86/arm64, linux x64/arm64/loongarch64:
// For windows x64/x86/arm64, linux x64/arm64/loongarch64/riscv64:
// 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
9 changes: 9 additions & 0 deletions src/coreclr/vm/riscv64/asmhelpers.S
Original file line number Diff line number Diff line change
Expand Up @@ -954,3 +954,12 @@ NESTED_ENTRY OnCallCountThresholdReachedStub, _TEXT, NoHandler
NESTED_END OnCallCountThresholdReachedStub, _TEXT

#endif // FEATURE_TIERED_COMPILATION

// ------------------------------------------------------------------
// size_t GetThreadStaticsVariableOffset()

// Load offset of native thread local variable `t_ThreadStatics` in TCB and return it in `a0` register.
LEAF_ENTRY GetThreadStaticsVariableOffset, _TEXT
la.tls.ie a0, t_ThreadStatics
EPILOG_RETURN
LEAF_END GetThreadStaticsVariableOffset, _TEXT