Skip to content

#[thread_local]s are pessimized in #[no_mangle] functions #136042

Open
@purplesyringa

Description

@purplesyringa
#![feature(thread_local)]

use std::cell::Cell;

#[thread_local]
static THREAD_LOCAL: Cell<bool> = const { Cell::new(false) };

pub fn pub_mentions_thread_local() {
    let _ = THREAD_LOCAL;
}

#[no_mangle]
fn no_mangle_uses_thread_local() {
    let r = &THREAD_LOCAL;
    if !r.get() {
        r.set(true);
    }
}

compiles to:

no_mangle_uses_thread_local:
        push    rax
        data16
        lea     rdi, [rip + example::THREAD_LOCAL::h5a1be4459c52c6f4@TLSGD]
        data16
        data16
        rex64
        call    __tls_get_addr@PLT
        cmp     byte ptr [rax], 0
        jne     .LBB0_2
        data16
        lea     rdi, [rip + example::THREAD_LOCAL::h5a1be4459c52c6f4@TLSGD]
        data16
        data16
        rex64
        call    __tls_get_addr@PLT
        mov     byte ptr [rax], 1
.LBB0_2:
        pop     rax
        ret

example::THREAD_LOCAL::h5a1be4459c52c6f4:
        .zero   1

(https://godbolt.org/z/K69s4fzzz)

i.e. two accesses under the global-dynamic TLS model. I have two questions here:

  1. Why is the TLS resolved twice? It's sound to resolve it only once; in fact, the source code takes &THREAD_LOCAL just once. This might be an LLVM problem.

  2. Why is global-dynamic used instead of local-dynamic? Removing pub from pub_mentions_thread_local, deleting pub_mentions_thread_local altogether, or adding #[no_mangle] to it fixes this, even though that function literally has an empty MIR. This makes me suspect this is not an LLVM bug.

Here's another example.

I'm not positive that #[no_mangle] is to blame here, but that's the closest I have to a non-generic title.

std::thread_local! is unaffected.

@rustbot label +A-codegen +A-thread-locals +C-optimization +F-thread_local +T-compiler

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-codegenArea: Code generationA-thread-localsArea: Thread local storage (TLS)C-optimizationCategory: An issue highlighting optimization opportunities or PRs implementing suchF-thread_local`#![feature(thread_local)]`T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions