From 39b5367cba5d706ece4091cb33e850b68486b53a Mon Sep 17 00:00:00 2001 From: Derek Schuff Date: Tue, 20 Mar 2018 22:01:32 +0000 Subject: [PATCH] [WebAssembly] Strip threadlocal attribute from globals in single thread mode The default thread model for wasm is single, and in this mode thread-local global variables can be lowered identically to non-thread-local variables. Differential Revision: https://reviews.llvm.org/D44703 llvm-svn: 328049 --- .../WebAssembly/WebAssemblyTargetMachine.cpp | 22 ++++++++++++++++++++-- llvm/test/CodeGen/WebAssembly/tls.ll | 17 +++++++++++++++++ 2 files changed, 37 insertions(+), 2 deletions(-) create mode 100644 llvm/test/CodeGen/WebAssembly/tls.ll diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp index a686e77..c006df0 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp @@ -126,6 +126,22 @@ WebAssemblyTargetMachine::getSubtargetImpl(const Function &F) const { } namespace { +class StripThreadLocal final : public ModulePass { + // The default thread model for wasm is single, where thread-local variables + // are identical to regular globals and should be treated the same. So this + // pass just converts all GlobalVariables to NotThreadLocal + static char ID; + + public: + StripThreadLocal() : ModulePass(ID) {} + bool runOnModule(Module &M) override { + for (auto &GV : M.globals()) + GV.setThreadLocalMode(GlobalValue::ThreadLocalMode::NotThreadLocal); + return true; + } +}; +char StripThreadLocal::ID = 0; + /// WebAssembly Code Generator Pass Configuration Options. class WebAssemblyPassConfig final : public TargetPassConfig { public: @@ -166,13 +182,15 @@ FunctionPass *WebAssemblyPassConfig::createTargetRegisterAllocator(bool) { //===----------------------------------------------------------------------===// void WebAssemblyPassConfig::addIRPasses() { - if (TM->Options.ThreadModel == ThreadModel::Single) + if (TM->Options.ThreadModel == ThreadModel::Single) { // In "single" mode, atomics get lowered to non-atomics. addPass(createLowerAtomicPass()); - else + addPass(new StripThreadLocal()); + } else { // Expand some atomic operations. WebAssemblyTargetLowering has hooks which // control specifically what gets lowered. addPass(createAtomicExpandPass()); + } // Lower .llvm.global_dtors into .llvm_global_ctors with __cxa_atexit calls. addPass(createWebAssemblyLowerGlobalDtors()); diff --git a/llvm/test/CodeGen/WebAssembly/tls.ll b/llvm/test/CodeGen/WebAssembly/tls.ll new file mode 100644 index 0000000..1c02f49 --- /dev/null +++ b/llvm/test/CodeGen/WebAssembly/tls.ll @@ -0,0 +1,17 @@ +; RUN: llc < %s -asm-verbose=false -disable-wasm-fallthrough-return-opt -disable-wasm-explicit-locals -thread-model=single | FileCheck --check-prefix=SINGLE %s +target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" +target triple = "wasm32-unknown-unknown-wasm" + +; SINGLE-LABEL: address_of_tls: +define i32 @address_of_tls() { + ; SINGLE: i32.const $push0=, tls + ; SINGLE-NEXT: return $pop0 + ret i32 ptrtoint(i32* @tls to i32) +} + +; SINGLE: .type tls,@object +; SINGLE-NEXT: .section .bss.tls,"",@ +; SINGLE-NEXT: .p2align 2 +; SINGLE-NEXT: tls: +; SINGLE-NEXT: .int32 0 +@tls = internal thread_local global i32 0 -- 2.7.4