https://github.com/tlively created https://github.com/llvm/llvm-project/pull/223917
Clang defaults WebAssembly to a single-threaded model unless atomics and bulk-memory are enabled, whereas Triple::getDefaultThreadModel() previously defaulted to POSIX for all targets. Because Clang only emits the "thread-model" module flag when the active thread model differs from the triple's default, single-threaded Wasm objects recorded "thread-model"="single" while multithreaded objects omitted the flag. When linking mixed objects in LTO, the merged module inherited "single", causing passes like LICM and AtomicExpand to treat multithreaded programs as single-threaded. Change Triple::getDefaultThreadModel() to return ThreadModel::Single for WebAssembly so that multithreaded objects explicitly record "thread-model"= "posix" and single-threaded objects omit the flag. Additionally, update WebAssemblyCoalesceFeaturesAndStripAtomics to set the module thread model to POSIX when threading features are enabled and no explicit module flag is present, ensuring backend passes like AtomicExpandPass preserve atomics in raw IR modules compiled via llc. Assisted-By: Gemini >From 804a9390fdbb63cbb68e9b278055941824518f3b Mon Sep 17 00:00:00 2001 From: Thomas Lively <[email protected]> Date: Tue, 15 Sep 2026 22:45:19 -0700 Subject: [PATCH] [WebAssembly] Use Single as the default Triple thread model Clang defaults WebAssembly to a single-threaded model unless atomics and bulk-memory are enabled, whereas Triple::getDefaultThreadModel() previously defaulted to POSIX for all targets. Because Clang only emits the "thread-model" module flag when the active thread model differs from the triple's default, single-threaded Wasm objects recorded "thread-model"="single" while multithreaded objects omitted the flag. When linking mixed objects in LTO, the merged module inherited "single", causing passes like LICM and AtomicExpand to treat multithreaded programs as single-threaded. Change Triple::getDefaultThreadModel() to return ThreadModel::Single for WebAssembly so that multithreaded objects explicitly record "thread-model"= "posix" and single-threaded objects omit the flag. Additionally, update WebAssemblyCoalesceFeaturesAndStripAtomics to set the module thread model to POSIX when threading features are enabled and no explicit module flag is present, ensuring backend passes like AtomicExpandPass preserve atomics in raw IR modules compiled via llc. Assisted-By: Gemini --- clang/test/CodeGen/thread-model.c | 8 ++++++++ .../WebAssemblyCoalesceFeaturesAndStripAtomics.cpp | 10 +++++++++- llvm/lib/TargetParser/Triple.cpp | 6 +++++- 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/clang/test/CodeGen/thread-model.c b/clang/test/CodeGen/thread-model.c index cf6eb82c948a0..419615fb40edb 100644 --- a/clang/test/CodeGen/thread-model.c +++ b/clang/test/CodeGen/thread-model.c @@ -5,7 +5,15 @@ // RUN: %clang_cc1 -triple arm-none-linux-gnueabi -mthread-model posix -emit-llvm %s -o - | FileCheck %s --check-prefix=POSIX // RUN: %clang_cc1 -triple arm-none-linux-gnueabi -emit-llvm %s -o - | FileCheck %s --check-prefix=POSIX +// RUN: %clang_cc1 -triple wasm32-unknown-unknown -mthread-model single -emit-llvm %s -o - | FileCheck %s --check-prefix=WASM-SINGLE +// RUN: %clang_cc1 -triple wasm32-unknown-unknown -target-feature +atomics -target-feature +bulk-memory -mthread-model posix -emit-llvm %s -o - | FileCheck %s --check-prefix=WASM-POSIX +// RUN: %clang_cc1 -triple wasm32-unknown-unknown -target-feature +atomics -target-feature +bulk-memory -emit-llvm %s -o - | FileCheck %s --check-prefix=WASM-POSIX +// RUN: %clang_cc1 -triple wasm32-unknown-unknown -emit-llvm %s -o - | FileCheck %s --check-prefix=WASM-SINGLE + void f(void) {} // SINGLE: !{i32 1, !"thread-model", !"single"} // POSIX-NOT: "thread-model" + +// WASM-SINGLE-NOT: "thread-model" +// WASM-POSIX: !{i32 1, !"thread-model", !"posix"} diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyCoalesceFeaturesAndStripAtomics.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyCoalesceFeaturesAndStripAtomics.cpp index a040e531ee020..8c4b24806c9a9 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyCoalesceFeaturesAndStripAtomics.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyCoalesceFeaturesAndStripAtomics.cpp @@ -197,7 +197,15 @@ static bool coalesceFeaturesAndStripAtomics(Module &M, else if (StrippedTLS && !StrippedAtomics) stripAtomics(M); - recordFeatures(M, ST, Features, StrippedAtomics || StrippedTLS); + bool Stripped = StrippedAtomics || StrippedTLS; + if (!Stripped && + (Features[WebAssembly::FeatureAtomics] || + (CooperativeThreading && Features[WebAssembly::FeatureBulkMemory])) && + !M.getModuleFlag("thread-model")) { + M.setThreadModel(ThreadModel::POSIX); + } + + recordFeatures(M, ST, Features, Stripped); // Conservatively assume we have made some change return true; diff --git a/llvm/lib/TargetParser/Triple.cpp b/llvm/lib/TargetParser/Triple.cpp index ceabfe403e9c3..fb54408c0729f 100644 --- a/llvm/lib/TargetParser/Triple.cpp +++ b/llvm/lib/TargetParser/Triple.cpp @@ -2543,7 +2543,11 @@ FloatABI::ABIType Triple::getDefaultFloatABI() const { return FloatABI::Hard; } -ThreadModel Triple::getDefaultThreadModel() const { return ThreadModel::POSIX; } +ThreadModel Triple::getDefaultThreadModel() const { + if (isWasm()) + return ThreadModel::Single; + return ThreadModel::POSIX; +} LongDoubleFormat Triple::getDefaultLongDoubleFormat() const { switch (getArch()) { _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
